diff options
| author | Paul Stansifer <paul.stansifer@gmail.com> | 2012-07-26 16:16:28 -0700 |
|---|---|---|
| committer | Paul Stansifer <paul.stansifer@gmail.com> | 2012-07-26 16:16:28 -0700 |
| commit | 97422f0f0fdcbdd17a769fa9588e76b8bf8a5bdf (patch) | |
| tree | a91f89c585b54fccf34cd873d2488d2cb3c09909 /src | |
| parent | 8209b2e9b383b9e38a09b1ec79c7b5691aeb5d22 (diff) | |
| parent | 44631722ff234241cb7100103320a402fe4fdfa9 (diff) | |
| download | rust-97422f0f0fdcbdd17a769fa9588e76b8bf8a5bdf.tar.gz rust-97422f0f0fdcbdd17a769fa9588e76b8bf8a5bdf.zip | |
Merge branch 'incoming' of github.com:mozilla/rust
Diffstat (limited to 'src')
55 files changed, 772 insertions, 420 deletions
diff --git a/src/libcore/arc.rs b/src/libcore/arc.rs index 28f07264410..9c46df9731b 100644 --- a/src/libcore/arc.rs +++ b/src/libcore/arc.rs @@ -3,10 +3,9 @@ * share immutable data between tasks. */ -import comm::{port, chan, methods}; import sys::methods; -export arc, get, clone, shared_arc, get_arc; +export arc, get, clone; export exclusive, methods; @@ -122,49 +121,6 @@ impl methods<T: send> for exclusive<T> { } } -// Convenience code for sharing arcs between tasks - -type get_chan<T: const send> = chan<chan<arc<T>>>; - -// (terminate, get) -type shared_arc<T: const send> = (shared_arc_res, get_chan<T>); - -class shared_arc_res { - let c: comm::chan<()>; - new(c: comm::chan<()>) { self.c = c; } - drop { self.c.send(()); } -} - -fn shared_arc<T: send const>(-data: T) -> shared_arc<T> { - let a = arc::arc(data); - let p = port(); - let c = chan(p); - do task::spawn() |move a| { - let mut live = true; - let terminate = port(); - let get = port(); - - c.send((chan(terminate), chan(get))); - - while live { - alt comm::select2(terminate, get) { - either::left(()) { live = false; } - either::right(cc) { - comm::send(cc, arc::clone(&a)); - } - } - } - }; - let (terminate, get) = p.recv(); - (shared_arc_res(terminate), get) -} - -fn get_arc<T: send const>(c: get_chan<T>) -> arc::arc<T> { - let p = port(); - c.send(chan(p)); - p.recv() -} - #[cfg(test)] mod tests { import comm::*; @@ -197,25 +153,6 @@ mod tests { } #[test] - fn auto_share_arc() { - let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let (_res, arc_c) = shared_arc(v); - - let p = port(); - let c = chan(p); - - do task::spawn() { - let arc_v = get_arc(arc_c); - let v = *get(&arc_v); - assert v[2] == 3; - - c.send(()); - }; - - assert p.recv() == (); - } - - #[test] #[ignore] // this can probably infinite loop too. fn exclusive_arc() { let mut futures = ~[]; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 1bdf3b9909a..d10b9603af0 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1,10 +1,10 @@ /// Interfaces used for comparison. -iface ord { - fn lt(&&other: self) -> bool; +trait ord { + pure fn lt(&&other: self) -> bool; } -iface eq { - fn eq(&&other: self) -> bool; +trait eq { + pure fn eq(&&other: self) -> bool; } diff --git a/src/libcore/core.rc b/src/libcore/core.rc index d298ff15a9e..11e305e22e8 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -161,6 +161,7 @@ mod tuple; // Ubiquitous-utility-type modules +mod ops; mod cmp; mod num; mod hash; diff --git a/src/libcore/core.rs b/src/libcore/core.rs index 4738574fdb4..fdf53524188 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -30,6 +30,8 @@ import float::num; import f32::num; import f64::num; import num::num; +import ops::{const, copy, send, owned}; +import ops::{add, sub, mul, div, modulo, neg, bitops, index}; export path, option, some, none, unreachable; export extensions; @@ -42,6 +44,9 @@ export immutable_copyable_vector, iter_trait_extensions, vec_concat; export base_iter, copyable_iter, extended_iter; export tuple_ops, extended_tuple_ops; export ptr; +// The following exports are the core operators and kinds +export const, copy, send, owned; +export add, sub, mul, div, modulo, neg, bitops, index; // Export the log levels as global constants. Higher levels mean // more-verbosity. Error is the bottom level, default logging level is diff --git a/src/libcore/dlist.rs b/src/libcore/dlist.rs index 087194f721d..cd36d14816c 100644 --- a/src/libcore/dlist.rs +++ b/src/libcore/dlist.rs @@ -18,12 +18,28 @@ enum dlist_node<T> = @{ mut next: dlist_link<T> }; -// Needs to be an @-box so nodes can back-reference it. -enum dlist<T> = @{ - mut size: uint, - mut hd: dlist_link<T>, - mut tl: dlist_link<T> -}; +class dlist_root<T> { + let mut size: uint; + let mut hd: dlist_link<T>; + let mut tl: dlist_link<T>; + new() { + self.size = 0; self.hd = none; self.tl = none; + } + drop { + /* FIXME (#????) This doesn't work during task failure - the box + * annihilator might have killed some of our nodes already. This will + * be safe to uncomment when the box annihilator is safer. As is, + * this makes test_dlist_cyclic_link below crash the runtime. + // Empty the list. Not doing this explicitly would leave cyclic links + // around, not to be freed until cycle collection at task exit. + while self.hd.is_some() { + self.unlink(self.hd.get()); + } + */ + } +} + +type dlist<T> = @dlist_root<T>; impl private_methods<T> for dlist_node<T> { pure fn assert_links() { @@ -91,7 +107,7 @@ pure fn new_dlist_node<T>(+data: T) -> dlist_node<T> { /// Creates a new, empty dlist. pure fn new_dlist<T>() -> dlist<T> { - dlist(@{mut size: 0, mut hd: none, mut tl: none}) + @unchecked { dlist_root() } } /// Creates a new dlist with a single element @@ -118,7 +134,7 @@ fn concat<T>(lists: dlist<dlist<T>>) -> dlist<T> { result } -impl private_methods<T> for dlist<T> { +impl private_methods<T> for dlist_root<T> { pure fn new_link(-data: T) -> dlist_link<T> { some(dlist_node(@{data: data, mut linked: true, mut prev: none, mut next: none})) @@ -288,20 +304,6 @@ impl extensions<T> for dlist<T> { tl.map(|nobe| self.unlink(nobe)); tl } - /// Remove data from the head of the list. O(1). - fn pop() -> option<T> { - do option::map_consume(self.pop_n()) |nobe| { - let dlist_node(@{ data: x, _ }) <- nobe; - x - } - } - /// Remove data from the tail of the list. O(1). - fn pop_tail() -> option<T> { - do option::map_consume(self.pop_tail_n()) |nobe| { - let dlist_node(@{ data: x, _ }) <- nobe; - x - } - } /// Get the node at the list's head. O(1). pure fn peek_n() -> option<dlist_node<T>> { self.hd } /// Get the node at the list's tail. O(1). @@ -334,7 +336,7 @@ impl extensions<T> for dlist<T> { * to the other list's head. O(1). */ fn append(them: dlist<T>) { - if box::ptr_eq(*self, *them) { + if box::ptr_eq(self, them) { fail ~"Cannot append a dlist to itself!" } if them.len() > 0 { @@ -351,7 +353,7 @@ impl extensions<T> for dlist<T> { * list's tail to this list's head. O(1). */ fn prepend(them: dlist<T>) { - if box::ptr_eq(*self, *them) { + if box::ptr_eq(self, them) { fail ~"Cannot prepend a dlist to itself!" } if them.len() > 0 { @@ -366,15 +368,25 @@ impl extensions<T> for dlist<T> { /// Reverse the list's elements in place. O(n). fn reverse() { - let temp = new_dlist::<T>(); + do option::while_some(self.hd) |nobe| { + let next_nobe = nobe.next; + self.remove(nobe); + self.make_mine(nobe); + self.add_head(some(nobe)); + next_nobe + } + } + + /** + * Remove everything from the list. This is important because the cyclic + * links won't otherwise be automatically refcounted-collected. O(n). + */ + fn clear() { + // Cute as it would be to simply detach the list and proclaim "O(1)!", + // the GC would still be a hidden O(n). Better to be honest about it. while !self.is_empty() { - let nobe = self.pop_n().get(); - nobe.linked = true; // meh, kind of disorganised. - temp.add_head(some(nobe)); + let _ = self.pop_n(); } - self.hd = temp.hd; - self.tl = temp.tl; - self.size = temp.size; } /// Iterate over nodes. @@ -431,6 +443,10 @@ impl extensions<T> for dlist<T> { } impl extensions<T: copy> for dlist<T> { + /// Remove data from the head of the list. O(1). + fn pop() -> option<T> { self.pop_n().map (|nobe| nobe.data) } + /// Remove data from the tail of the list. O(1). + fn pop_tail() -> option<T> { self.pop_tail_n().map (|nobe| nobe.data) } /// Get data at the list's head. O(1). pure fn peek() -> option<T> { self.peek_n().map (|nobe| nobe.data) } /// Get data at the list's tail. O(1). @@ -596,6 +612,13 @@ mod tests { a.assert_consistent(); assert a.is_empty(); } #[test] + fn test_dlist_clear() { + let a = from_vec(~[5,4,3,2,1]); + a.clear(); + assert a.len() == 0; + a.assert_consistent(); + } + #[test] fn test_dlist_is_empty() { let empty = new_dlist::<int>(); let full1 = from_vec(~[1,2,3]); @@ -847,7 +870,7 @@ mod tests { l.assert_consistent(); assert l.is_empty(); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_asymmetric_link() { + fn test_dlist_asymmetric_link() { let l = new_dlist::<int>(); let _one = l.push_n(1); let two = l.push_n(2); @@ -855,7 +878,7 @@ mod tests { l.assert_consistent(); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_cyclic_list() { + fn test_dlist_cyclic_list() { let l = new_dlist::<int>(); let one = l.push_n(1); let _two = l.push_n(2); @@ -865,32 +888,32 @@ mod tests { l.assert_consistent(); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_headless() { + fn test_dlist_headless() { new_dlist::<int>().head(); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_insert_already_present_before() { + fn test_dlist_insert_already_present_before() { let l = new_dlist::<int>(); let one = l.push_n(1); let two = l.push_n(2); l.insert_n_before(two, one); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_insert_already_present_after() { + fn test_dlist_insert_already_present_after() { let l = new_dlist::<int>(); let one = l.push_n(1); let two = l.push_n(2); l.insert_n_after(one, two); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_insert_before_orphan() { + fn test_dlist_insert_before_orphan() { let l = new_dlist::<int>(); let one = new_dlist_node(1); let two = new_dlist_node(2); l.insert_n_before(one, two); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_insert_after_orphan() { + fn test_dlist_insert_after_orphan() { let l = new_dlist::<int>(); let one = new_dlist_node(1); let two = new_dlist_node(2); diff --git a/src/libcore/f32.rs b/src/libcore/f32.rs index c72aa6e3aef..3e7bc0097f7 100644 --- a/src/libcore/f32.rs +++ b/src/libcore/f32.rs @@ -168,15 +168,15 @@ pure fn log2(n: f32) -> f32 { } impl num of num::num for f32 { - fn add(&&other: f32) -> f32 { ret self + other; } - fn sub(&&other: f32) -> f32 { ret self - other; } - fn mul(&&other: f32) -> f32 { ret self * other; } - fn div(&&other: f32) -> f32 { ret self / other; } - fn modulo(&&other: f32) -> f32 { ret self % other; } - fn neg() -> f32 { ret -self; } - - fn to_int() -> int { ret self as int; } - fn from_int(n: int) -> f32 { ret n as f32; } + pure fn add(&&other: f32) -> f32 { ret self + other; } + pure fn sub(&&other: f32) -> f32 { ret self - other; } + pure fn mul(&&other: f32) -> f32 { ret self * other; } + pure fn div(&&other: f32) -> f32 { ret self / other; } + pure fn modulo(&&other: f32) -> f32 { ret self % other; } + pure fn neg() -> f32 { ret -self; } + + pure fn to_int() -> int { ret self as int; } + pure fn from_int(n: int) -> f32 { ret n as f32; } } // diff --git a/src/libcore/f64.rs b/src/libcore/f64.rs index 40488d9f8f4..9e84c432bad 100644 --- a/src/libcore/f64.rs +++ b/src/libcore/f64.rs @@ -195,15 +195,15 @@ pure fn log2(n: f64) -> f64 { } impl num of num::num for f64 { - fn add(&&other: f64) -> f64 { ret self + other; } - fn sub(&&other: f64) -> f64 { ret self - other; } - fn mul(&&other: f64) -> f64 { ret self * other; } - fn div(&&other: f64) -> f64 { ret self / other; } - fn modulo(&&other: f64) -> f64 { ret self % other; } - fn neg() -> f64 { ret -self; } - - fn to_int() -> int { ret self as int; } - fn from_int(n: int) -> f64 { ret n as f64; } + pure fn add(&&other: f64) -> f64 { ret self + other; } + pure fn sub(&&other: f64) -> f64 { ret self - other; } + pure fn mul(&&other: f64) -> f64 { ret self * other; } + pure fn div(&&other: f64) -> f64 { ret self / other; } + pure fn modulo(&&other: f64) -> f64 { ret self % other; } + pure fn neg() -> f64 { ret -self; } + + pure fn to_int() -> int { ret self as int; } + pure fn from_int(n: int) -> f64 { ret n as f64; } } // diff --git a/src/libcore/float.rs b/src/libcore/float.rs index 0139c60873b..8b8cc4664dc 100644 --- a/src/libcore/float.rs +++ b/src/libcore/float.rs @@ -403,32 +403,32 @@ fn pow_with_uint(base: uint, pow: uint) -> float { ret total; } -fn is_positive(x: float) -> bool { f64::is_positive(x as f64) } -fn is_negative(x: float) -> bool { f64::is_negative(x as f64) } -fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) } -fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) } -fn is_zero(x: float) -> bool { f64::is_zero(x as f64) } -fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) } -fn is_finite(x: float) -> bool { f64::is_finite(x as f64) } -fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) } - -fn abs(x: float) -> float { f64::abs(x as f64) as float } -fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float } -fn atan(x: float) -> float { f64::atan(x as f64) as float } -fn sin(x: float) -> float { f64::sin(x as f64) as float } -fn cos(x: float) -> float { f64::cos(x as f64) as float } -fn tan(x: float) -> float { f64::tan(x as f64) as float } +pure fn is_positive(x: float) -> bool { f64::is_positive(x as f64) } +pure fn is_negative(x: float) -> bool { f64::is_negative(x as f64) } +pure fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) } +pure fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) } +pure fn is_zero(x: float) -> bool { f64::is_zero(x as f64) } +pure fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) } +pure fn is_finite(x: float) -> bool { f64::is_finite(x as f64) } +pure fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) } + +pure fn abs(x: float) -> float { f64::abs(x as f64) as float } +pure fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float } +pure fn atan(x: float) -> float { f64::atan(x as f64) as float } +pure fn sin(x: float) -> float { f64::sin(x as f64) as float } +pure fn cos(x: float) -> float { f64::cos(x as f64) as float } +pure fn tan(x: float) -> float { f64::tan(x as f64) as float } impl num of num::num for float { - fn add(&&other: float) -> float { ret self + other; } - fn sub(&&other: float) -> float { ret self - other; } - fn mul(&&other: float) -> float { ret self * other; } - fn div(&&other: float) -> float { ret self / other; } - fn modulo(&&other: float) -> float { ret self % other; } - fn neg() -> float { ret -self; } - - fn to_int() -> int { ret self as int; } - fn from_int(n: int) -> float { ret n as float; } + pure fn add(&&other: float) -> float { ret self + other; } + pure fn sub(&&other: float) -> float { ret self - other; } + pure fn mul(&&other: float) -> float { ret self * other; } + pure fn div(&&other: float) -> float { ret self / other; } + pure fn modulo(&&other: float) -> float { ret self % other; } + pure fn neg() -> float { ret -self; } + + pure fn to_int() -> int { ret self as int; } + pure fn from_int(n: int) -> float { ret n as float; } } #[test] diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 02ce125e35c..2b950e4a797 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -112,27 +112,27 @@ fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { fn str(i: T) -> ~str { ret to_str(i, 10u); } impl ord of ord for T { - fn lt(&&other: T) -> bool { + pure fn lt(&&other: T) -> bool { ret self < other; } } impl eq of eq for T { - fn eq(&&other: T) -> bool { + pure fn eq(&&other: T) -> bool { ret self == other; } } impl num of num::num for T { - fn add(&&other: T) -> T { ret self + other; } - fn sub(&&other: T) -> T { ret self - other; } - fn mul(&&other: T) -> T { ret self * other; } - fn div(&&other: T) -> T { ret self / other; } - fn modulo(&&other: T) -> T { ret self % other; } - fn neg() -> T { ret -self; } - - fn to_int() -> int { ret self as int; } - fn from_int(n: int) -> T { ret n as T; } + pure fn add(&&other: T) -> T { ret self + other; } + pure fn sub(&&other: T) -> T { ret self - other; } + pure fn mul(&&other: T) -> T { ret self * other; } + pure fn div(&&other: T) -> T { ret self / other; } + pure fn modulo(&&other: T) -> T { ret self % other; } + pure fn neg() -> T { ret -self; } + + pure fn to_int() -> int { ret self as int; } + pure fn from_int(n: int) -> T { ret n as T; } } impl times of iter::times for T { diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 25d1b5e6680..3704f2b70da 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -687,7 +687,11 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: seek_style) -> fn read_whole_file_str(file: ~str) -> result<~str, ~str> { result::chain(read_whole_file(file), |bytes| { - result::ok(str::from_bytes(bytes)) + if str::is_utf8(bytes) { + result::ok(str::from_bytes(bytes)) + } else { + result::err(file + ~" is not UTF-8") + } }) } diff --git a/src/libcore/num.rs b/src/libcore/num.rs index 130b259c1df..03868527655 100644 --- a/src/libcore/num.rs +++ b/src/libcore/num.rs @@ -1,17 +1,17 @@ /// An interface for numbers. -iface num { +trait num { // FIXME: Cross-crate overloading doesn't work yet. (#2615) // FIXME: Interface inheritance. (#2616) - fn add(&&other: self) -> self; - fn sub(&&other: self) -> self; - fn mul(&&other: self) -> self; - fn div(&&other: self) -> self; - fn modulo(&&other: self) -> self; - fn neg() -> self; + pure fn add(&&other: self) -> self; + pure fn sub(&&other: self) -> self; + pure fn mul(&&other: self) -> self; + pure fn div(&&other: self) -> self; + pure fn modulo(&&other: self) -> self; + pure fn neg() -> self; - fn to_int() -> int; - fn from_int(n: int) -> self; // FIXME (#2376) Static functions. + pure fn to_int() -> int; + pure fn from_int(n: int) -> self; // FIXME (#2376) Static functions. // n.b. #2376 is for classes, not ifaces, but it could be generalized... } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs new file mode 100644 index 00000000000..61efe704974 --- /dev/null +++ b/src/libcore/ops.rs @@ -0,0 +1,66 @@ +// Core operators and kinds. + +#[lang="const"] +trait const { + // Empty. +} + +#[lang="copy"] +trait copy { + // Empty. +} + +#[lang="send"] +trait send { + // Empty. +} + +#[lang="owned"] +trait owned { + // Empty. +} + +#[lang="add"] +trait add<RHS,Result> { + pure fn add(rhs: RHS) -> Result; +} + +#[lang="sub"] +trait sub<RHS,Result> { + pure fn sub(rhs: RHS) -> Result; +} + +#[lang="mul"] +trait mul<RHS,Result> { + pure fn mul(rhs: RHS) -> Result; +} + +#[lang="div"] +trait div<RHS,Result> { + pure fn div(rhs: RHS) -> Result; +} + +#[lang="modulo"] +trait modulo<RHS,Result> { + pure fn modulo(rhs: RHS) -> Result; +} + +#[lang="neg"] +trait neg<RHS,Result> { + pure fn neg(rhs: RHS) -> Result; +} + +#[lang="bitops"] +trait bitops<RHS,BitCount,Result> { + pure fn and(rhs: RHS) -> Result; + pure fn or(rhs: RHS) -> Result; + pure fn xor(rhs: RHS) -> Result; + pure fn shl(n: BitCount) -> Result; + pure fn shr(n: BitCount) -> Result; +} + +#[lang="index"] +trait index<Index,Result> { + pure fn index(index: Index) -> Result; +} + diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 27cd8ef7caf..4ffa040250f 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -30,59 +30,6 @@ macro_rules! move { // places. Once there is unary move, it can be removed. fn move<T>(-x: T) -> T { x } -/** - -Some thoughts about fixed buffers. - -The idea is if a protocol is bounded, we will synthesize a record that -has a field for each state. Each of these states contains a packet for -the messages that are legal to be sent in that state. Then, instead of -allocating, the send code just finds a pointer to the right field and -uses that instead. - -Unforunately, this makes things kind of tricky. We need to be able to -find the buffer, which means we need to pass it around. This could -either be associated with the (send|recv)_packet classes, or with the -packet itself. We will also need some form of reference counting so we -can track who has the responsibility of freeing the buffer. - -We want to preserve the ability to do things like optimistic buffer -re-use, and skipping over to a new buffer when necessary. What I mean -is, suppose we had the typical stream protocol. It'd make sense to -amortize allocation costs by allocating a buffer with say 16 -messages. When the sender gets to the end of the buffer, it could -check if the receiver is done with the packet in slot 0. If so, it can -just reuse that one, checking if the receiver is done with the next -one in each case. If it is ever not done, it just allocates a new -buffer and skips over to that. - -Also, since protocols are in libcore, we have to do this in a way that -maintains backwards compatibility. - -buffer header and buffer. Cast as c_void when necessary. - -=== - -Okay, here are some new ideas. - -It'd be nice to keep the bounded/unbounded case as uniform as -possible. It leads to less code duplication, and less things that can -go sublty wrong. For the bounded case, we could either have a struct -with a bunch of unique pointers to pre-allocated packets, or we could -lay them out inline. Inline layout is better, if for no other reason -than that we don't have to allocate each packet -individually. Currently we pass unique packets around as unsafe -pointers, but they are actually unique pointers. We should instead use -real unsafe pointers. This makes freeing data and running destructors -trickier though. Thus, we should allocate all packets in parter of a -higher level buffer structure. Packets can maintain a pointer to their -buffer, and this is the part that gets freed. - -It might be helpful to have some idea of a semi-unique pointer (like -being partially pregnant, also like an ARC). - -*/ - enum state { empty, full, @@ -805,6 +752,12 @@ class port_set<T: send> : recv<T> { vec::push(self.ports, port) } + fn chan() -> chan<T> { + let (ch, po) = stream(); + self.add(po); + ch + } + fn try_recv() -> option<T> { let mut result = none; while result == none && self.ports.len() > 0 { @@ -869,3 +822,52 @@ impl chan<T: send> of channel<T> for shared_chan<T> { fn shared_chan<T:send>(+c: chan<T>) -> shared_chan<T> { arc::exclusive(c) } + +trait select2<T: send, U: send> { + fn try_select() -> either<option<T>, option<U>>; + fn select() -> either<T, U>; +} + +impl<T: send, U: send, Left: selectable recv<T>, Right: selectable recv<U>> + of select2<T, U> for (Left, Right) { + + fn select() -> either<T, U> { + alt self { + (lp, rp) { + alt select2i(lp, rp) { + left(()) { left (lp.recv()) } + right(()) { right(rp.recv()) } + } + } + } + } + + fn try_select() -> either<option<T>, option<U>> { + alt self { + (lp, rp) { + alt select2i(lp, rp) { + left(()) { left (lp.try_recv()) } + right(()) { right(rp.try_recv()) } + } + } + } + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_select2() { + let (c1, p1) = pipes::stream(); + let (c2, p2) = pipes::stream(); + + c1.send("abc"); + + alt (p1, p2).select() { + right(_) { fail } + _ { } + } + + c2.send(123); + } +} diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 75e17cd6a9b..9561ed4e65f 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -53,27 +53,27 @@ pure fn compl(i: T) -> T { } impl ord of ord for T { - fn lt(&&other: T) -> bool { + pure fn lt(&&other: T) -> bool { ret self < other; } } impl eq of eq for T { - fn eq(&&other: T) -> bool { + pure fn eq(&&other: T) -> bool { ret self == other; } } impl num of num::num for T { - fn add(&&other: T) -> T { ret self + other; } - fn sub(&&other: T) -> T { ret self - other; } - fn mul(&&other: T) -> T { ret self * other; } - fn div(&&other: T) -> T { ret self / other; } - fn modulo(&&other: T) -> T { ret self % other; } - fn neg() -> T { ret -self; } - - fn to_int() -> int { ret self as int; } - fn from_int(n: int) -> T { ret n as T; } + pure fn add(&&other: T) -> T { ret self + other; } + pure fn sub(&&other: T) -> T { ret self - other; } + pure fn mul(&&other: T) -> T { ret self * other; } + pure fn div(&&other: T) -> T { ret self / other; } + pure fn modulo(&&other: T) -> T { ret self % other; } + pure fn neg() -> T { ret -self; } + + pure fn to_int() -> int { ret self as int; } + pure fn from_int(n: int) -> T { ret n as T; } } /** diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs index a89148ecec9..f74cbba23ce 100644 --- a/src/libstd/cmp.rs +++ b/src/libstd/cmp.rs @@ -2,24 +2,24 @@ const fuzzy_epsilon: float = 1.0e-6; -iface fuzzy_eq { - fn fuzzy_eq(&&other: self) -> bool; +trait fuzzy_eq { + pure fn fuzzy_eq(&&other: self) -> bool; } impl fuzzy_eq of fuzzy_eq for float { - fn fuzzy_eq(&&other: float) -> bool { + pure fn fuzzy_eq(&&other: float) -> bool { ret float::abs(self - other) < fuzzy_epsilon; } } impl fuzzy_eq of fuzzy_eq for f32 { - fn fuzzy_eq(&&other: f32) -> bool { + pure fn fuzzy_eq(&&other: f32) -> bool { ret f32::abs(self - other) < (fuzzy_epsilon as f32); } } impl fuzzy_eq of fuzzy_eq for f64 { - fn fuzzy_eq(&&other: f64) -> bool { + pure fn fuzzy_eq(&&other: f64) -> bool { ret f64::abs(self - other) < (fuzzy_epsilon as f64); } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index fb27724e369..4988adf9373 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -87,7 +87,7 @@ enum def { def_upvar(node_id /* local id of closed over var */, @def /* closed over def */, node_id /* expr node that creates the closure */), - def_class(def_id), + def_class(def_id, bool /* has constructor */), def_region(node_id) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 37e8671facd..0cf593efdc3 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -53,7 +53,7 @@ pure fn def_id_of_def(d: def) -> def_id { def_fn(id, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_class(id) { id } + def_use(id) | def_class(id, _) { id } def_arg(id, _) | def_local(id, _) | def_self(id) | def_upvar(id, _, _) | def_binding(id) | def_region(id) { local_def(id) diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index c9b35e561bb..f367fb63985 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -183,7 +183,6 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { {mode: ast::infer(self.next_id()), ty: ty, ident: name, - // FIXME #2886: should this be the same as the infer id? id: self.next_id()} } @@ -280,7 +279,6 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt { } fn ty_path_ast_builder(path: @ast::path) -> @ast::ty { - // FIXME #2886: make sure the node ids are legal. @{id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: self.empty_span()} diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 52aa88e6cb6..a6734b285a1 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -14,6 +14,7 @@ import io::{reader_util, writer_util}; import getopts::{optopt, optmulti, optflag, optflagopt, opt_present}; import back::{x86, x86_64}; import std::map::hashmap; +import lib::llvm::llvm; enum pp_mode {ppm_normal, ppm_expanded, ppm_typed, ppm_identified, ppm_expanded_identified } @@ -169,6 +170,9 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, session::sess_os_to_meta_os(sess.targ_cfg.os), sess.opts.static)); + time(time_passes, ~"language item collection", || + middle::lang_items::collect_language_items(crate, sess)); + let { def_map: def_map, exp_map: exp_map, impl_map: impl_map, @@ -440,6 +444,9 @@ fn build_session_options(match: getopts::match, } debugging_opts |= this_bit; } + if debugging_opts & session::debug_llvm != 0 { + llvm::LLVMSetDebug(1); + } let output_type = if parse_only || no_trans { diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index 64ae30895c4..61ef9f73c3f 100644 --- a/src/rustc/driver/session.rs +++ b/src/rustc/driver/session.rs @@ -40,6 +40,7 @@ const borrowck_stats: uint = 1024u; const borrowck_note_pure: uint = 2048; const borrowck_note_loan: uint = 4096; const no_landing_pads: uint = 8192; +const debug_llvm: uint = 16384; fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"ppregions", ~"prettyprint regions with \ @@ -61,7 +62,8 @@ fn debugging_opts_map() -> ~[(~str, ~str, uint)] { (~"borrowck-note-loan", ~"note where loans are req'd", borrowck_note_loan), (~"no-landing-pads", ~"omit landing pads for unwinding", - no_landing_pads) + no_landing_pads), + (~"debug-llvm", ~"enable debug output from LLVM", debug_llvm) ] } diff --git a/src/rustc/lib/llvm.rs b/src/rustc/lib/llvm.rs index 376012dcf4e..7dbefa8e498 100644 --- a/src/rustc/lib/llvm.rs +++ b/src/rustc/lib/llvm.rs @@ -969,6 +969,9 @@ extern mod llvm { fn LLVMConstNamedStruct(S: TypeRef, ConstantVals: *ValueRef, Count: c_uint) -> ValueRef; + + /** Enables LLVM debug output. */ + fn LLVMSetDebug(Enabled: c_int); } fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) { diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index 7f97583fe3d..0ba76c49246 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -25,6 +25,7 @@ export get_enum_variants; export get_impls_for_mod; export get_trait_methods; export get_method_names_if_trait; +export get_item_attrs; export each_path; export get_type; export get_impl_traits; @@ -149,6 +150,14 @@ fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id) ret decoder::get_method_names_if_trait(cdata, def.node); } +fn get_item_attrs(cstore: cstore::cstore, + def_id: ast::def_id, + f: fn(~[@ast::meta_item])) { + + let cdata = cstore::get_crate_data(cstore, def_id.crate); + decoder::get_item_attrs(cdata, def_id.node, f) +} + fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::field_ty] { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, def.crate); diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 3ff9ded3f1e..83684413641 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -39,6 +39,7 @@ export get_crate_vers; export get_impls_for_mod; export get_trait_methods; export get_method_names_if_trait; +export get_item_attrs; export get_crate_module_paths; export def_like; export dl_def; @@ -282,7 +283,8 @@ fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num) let fam_ch = item_family(item); alt fam_ch { 'c' { dl_def(ast::def_const(did)) } - 'C' { dl_def(ast::def_class(did)) } + 'C' { dl_def(ast::def_class(did, true)) } + 'S' { dl_def(ast::def_class(did, false)) } 'u' { dl_def(ast::def_fn(did, ast::unsafe_fn)) } 'f' { dl_def(ast::def_fn(did, ast::impure_fn)) } 'p' { dl_def(ast::def_fn(did, ast::pure_fn)) } @@ -659,6 +661,18 @@ fn get_method_names_if_trait(cdata: cmd, node_id: ast::node_id) ret some(resulting_method_names); } +fn get_item_attrs(cdata: cmd, + node_id: ast::node_id, + f: fn(~[@ast::meta_item])) { + + let item = lookup_item(node_id, cdata.data); + do ebml::tagged_docs(item, tag_attributes) |attributes| { + do ebml::tagged_docs(attributes, tag_attribute) |attribute| { + f(get_meta_items(attribute)); + } + } +} + // Helper function that gets either fields or methods fn get_class_members(cdata: cmd, id: ast::node_id, p: fn(char) -> bool) -> ~[ty::field_ty] { @@ -694,7 +708,7 @@ fn family_has_type_params(fam_ch: char) -> bool { alt check fam_ch { 'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' { false } 'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C' - | 'a' + | 'a' | 'S' { true } } } @@ -738,6 +752,7 @@ fn item_family_to_str(fam: char) -> ~str { 'i' { ret ~"impl"; } 'I' { ret ~"trait"; } 'C' { ret ~"class"; } + 'S' { ret ~"struct"; } 'g' { ret ~"public field"; } 'j' { ret ~"private field"; } } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index b2847b3acc5..e1ed9fe396a 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -663,7 +663,16 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, /* Now, make an item for the class itself */ ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - encode_family(ebml_w, 'C'); + + alt ctor { + none { + encode_family(ebml_w, 'S'); + } + some(_) { + encode_family(ebml_w, 'C'); + } + } + encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ebml_w, item.ident); @@ -759,6 +768,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ebml_w, item.ident); + encode_attributes(ebml_w, item.attrs); let mut i = 0u; for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| { alt ms[i] { diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 002b4d97e23..1f5f7c4518d 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -369,8 +369,8 @@ impl of tr for ast::def { ast::def_upvar(nid1, def, nid2) { ast::def_upvar(xcx.tr_id(nid1), @(*def).tr(xcx), xcx.tr_id(nid2)) } - ast::def_class(did) { - ast::def_class(did.tr(xcx)) + ast::def_class(did, has_constructor) { + ast::def_class(did.tr(xcx), has_constructor) } ast::def_region(nid) { ast::def_region(xcx.tr_id(nid)) } } diff --git a/src/rustc/middle/borrowck/categorization.rs b/src/rustc/middle/borrowck/categorization.rs index f5879145a9d..4088945e550 100644 --- a/src/rustc/middle/borrowck/categorization.rs +++ b/src/rustc/middle/borrowck/categorization.rs @@ -196,7 +196,7 @@ impl public_methods for borrowck_ctxt { ast::def_foreign_mod(_) | ast::def_const(_) | ast::def_use(_) | ast::def_variant(_, _) | ast::def_ty(_) | ast::def_prim_ty(_) | - ast::def_ty_param(_, _) | ast::def_class(_) | + ast::def_ty_param(_, _) | ast::def_class(_, _) | ast::def_region(_) { @{id:id, span:span, cat:cat_special(sk_static_item), lp:none, diff --git a/src/rustc/middle/lang_items.rs b/src/rustc/middle/lang_items.rs new file mode 100644 index 00000000000..2353da51f98 --- /dev/null +++ b/src/rustc/middle/lang_items.rs @@ -0,0 +1,209 @@ +// Detecting language items. +// +// Language items are items that represent concepts intrinsic to the language +// itself. Examples are: +// +// * Traits that specify "kinds"; e.g. "const", "copy", "send". +// +// * Traits that represent operators; e.g. "add", "sub", "index". +// +// * Functions called by the compiler itself. + +import driver::session::session; +import metadata::csearch::{each_path, get_item_attrs}; +import metadata::cstore::{iter_crate_data}; +import metadata::decoder::{dl_def, dl_field, dl_impl}; +import syntax::ast::{crate, def_id, def_ty, lit_str, meta_item, meta_list}; +import syntax::ast::{meta_name_value, meta_word}; +import syntax::ast_util::{local_def}; +import syntax::visit::{default_simple_visitor, mk_simple_visitor}; +import syntax::visit::{visit_crate, visit_item}; + +import std::map::{hashmap, str_hash}; +import str_eq = str::eq; + +class LanguageItems { + let mut const_trait: option<def_id>; + let mut copy_trait: option<def_id>; + let mut send_trait: option<def_id>; + let mut owned_trait: option<def_id>; + + let mut add_trait: option<def_id>; + let mut sub_trait: option<def_id>; + let mut mul_trait: option<def_id>; + let mut div_trait: option<def_id>; + let mut modulo_trait: option<def_id>; + let mut neg_trait: option<def_id>; + let mut bitops_trait: option<def_id>; + let mut index_trait: option<def_id>; + + new() { + self.const_trait = none; + self.copy_trait = none; + self.send_trait = none; + self.owned_trait = none; + + self.add_trait = none; + self.sub_trait = none; + self.mul_trait = none; + self.div_trait = none; + self.modulo_trait = none; + self.neg_trait = none; + self.bitops_trait = none; + self.index_trait = none; + } +} + +class LanguageItemCollector { + let items: LanguageItems; + + let crate: @crate; + let session: session; + + let item_refs: hashmap<~str,&mut option<def_id>>; + + new(crate: @crate, session: session) { + self.crate = crate; + self.session = session; + + self.items = LanguageItems(); + + self.item_refs = str_hash(); + } + + // XXX: Needed to work around an issue with constructors. + fn init() { + self.item_refs.insert(~"const", &mut self.items.const_trait); + self.item_refs.insert(~"copy", &mut self.items.copy_trait); + self.item_refs.insert(~"send", &mut self.items.send_trait); + self.item_refs.insert(~"owned", &mut self.items.owned_trait); + + self.item_refs.insert(~"add", &mut self.items.add_trait); + self.item_refs.insert(~"sub", &mut self.items.sub_trait); + self.item_refs.insert(~"mul", &mut self.items.mul_trait); + self.item_refs.insert(~"div", &mut self.items.div_trait); + self.item_refs.insert(~"modulo", &mut self.items.modulo_trait); + self.item_refs.insert(~"neg", &mut self.items.neg_trait); + self.item_refs.insert(~"bitops", &mut self.items.bitops_trait); + self.item_refs.insert(~"index", &mut self.items.index_trait); + } + + fn match_and_collect_meta_item(item_def_id: def_id, + meta_item: meta_item) { + + alt meta_item.node { + meta_name_value(key, literal) => { + alt literal.node { + lit_str(value) => { + self.match_and_collect_item(item_def_id, + *key, + *value); + } + _ => { + // Skip. + } + } + } + meta_word(*) | meta_list(*) { + // Skip. + } + } + } + + fn match_and_collect_item(item_def_id: def_id, key: ~str, value: ~str) { + if !str_eq(key, ~"lang") { + ret; // Didn't match. + } + + alt self.item_refs.find(value) { + none => { + // Didn't match. + } + some(item_ref) => { + // Check for duplicates. + alt copy *item_ref { + some(original_def_id) + if original_def_id != item_def_id => { + + self.session.warn(#fmt("duplicate entry for `%s`", + value)); + } + some(_) | none => { + // OK. + } + } + + // Matched. + *item_ref = some(item_def_id); + } + } + } + + fn collect_local_language_items() { + let this = unsafe { ptr::addr_of(self) }; + visit_crate(*self.crate, (), mk_simple_visitor(@{ + visit_item: |item| { + for item.attrs.each |attribute| { + unsafe { + (*this).match_and_collect_meta_item(local_def(item + .id), + attribute.node + .value); + } + } + } + with *default_simple_visitor() + })); + } + + fn collect_external_language_items() { + let crate_store = self.session.cstore; + do iter_crate_data(crate_store) |crate_number, _crate_metadata| { + for each_path(crate_store, crate_number) |path_entry| { + let def_id; + alt path_entry.def_like { + dl_def(def_ty(did)) => { + def_id = did; + } + dl_def(_) | dl_impl(_) | dl_field { + // Skip this. + again; + } + } + + do get_item_attrs(crate_store, def_id) |meta_items| { + for meta_items.each |meta_item| { + self.match_and_collect_meta_item(def_id, *meta_item); + } + } + } + } + } + + fn check_completeness() { + for self.item_refs.each |key, item_ref| { + alt copy *item_ref { + none => { + self.session.warn(#fmt("no item found for `%s`", key)); + } + some(did) => { + // OK. + } + } + } + } + + fn collect() { + self.init(); + self.collect_local_language_items(); + self.collect_external_language_items(); + self.check_completeness(); + } +} + +fn collect_language_items(crate: @crate, session: session) -> LanguageItems { + let collector = LanguageItemCollector(crate, session); + collector.collect(); + copy collector.items +} + diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index ca00aeaa0f4..cc6874bc967 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -467,7 +467,7 @@ fn determine_rp_in_ty(ty: @ast::ty, alt ty.node { ast::ty_path(_, id) { alt cx.def_map.get(id) { - ast::def_ty(did) | ast::def_class(did) { + ast::def_ty(did) | ast::def_class(did, _) { if did.crate == ast::local_crate { cx.add_dep(did.node, cx.item_id); } else { diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs index bddf83c429e..e75268cde7f 100644 --- a/src/rustc/middle/resolve3.rs +++ b/src/rustc/middle/resolve3.rs @@ -41,7 +41,7 @@ import syntax::visit::{visit_mod, visit_ty, vt}; import box::ptr_eq; import dvec::{dvec, extensions}; -import option::get; +import option::{get, is_some}; import str::{connect, split_str}; import vec::pop; @@ -604,7 +604,7 @@ class Resolver { let unused_import_lint_level: level; let trait_info: hashmap<def_id,@hashmap<Atom,()>>; - let structs: hashmap<def_id,()>; + let structs: hashmap<def_id,bool>; // The number of imports that are currently unresolved. let mut unresolved_imports: uint; @@ -926,7 +926,8 @@ class Resolver { (*name_bindings).define_impl(impl_info); // Record the def ID of this struct. - self.structs.insert(local_def(item.id), ()); + self.structs.insert(local_def(item.id), + is_some(optional_ctor)); visit_item(item, new_parent, visitor); } @@ -1378,12 +1379,16 @@ class Resolver { (*child_name_bindings).define_type(def); } - def_class(def_id) { + def_class(def_id, has_constructor) { #debug("(building reduced graph for external \ - crate) building value and type %s", - final_ident); - (*child_name_bindings).define_value(def); + crate) building type %s (value? %d)", + final_ident, + if has_constructor { 1 } else { 0 }); (*child_name_bindings).define_type(def); + + if has_constructor { + (*child_name_bindings).define_value(def); + } } def_self(*) | def_arg(*) | def_local(*) | def_prim_ty(*) | def_ty_param(*) | def_binding(*) | @@ -4201,7 +4206,9 @@ class Resolver { some(definition @ def_ty(class_id)) if self.structs.contains_key(class_id) { - self.record_def(expr.id, def_class(class_id)); + let has_constructor = self.structs.get(class_id); + let class_def = def_class(class_id, has_constructor); + self.record_def(expr.id, class_def); } _ { self.session.span_err(path.span, diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index b6b1873b1dc..465aeebe3af 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -2587,7 +2587,7 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> ~str { fn def_has_ty_params(def: ast::def) -> bool { alt def { - ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_) + ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_, _) { true } _ { false } } diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index ebd189a15b7..3baea12ab48 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -270,7 +270,7 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>( path_to_str(path))); } some(d) { d }}; alt a_def { - ast::def_ty(did) | ast::def_class(did) { + ast::def_ty(did) | ast::def_class(did, _) { ast_path_to_ty(self, rscope, did, path, id).ty } ast::def_prim_ty(nty) { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 0b78fd1a505..eaf0e90b26d 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1649,7 +1649,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Resolve the path. let class_id; alt tcx.def_map.find(id) { - some(ast::def_class(type_def_id)) => { + some(ast::def_class(type_def_id, _)) => { class_id = type_def_id; } _ => { @@ -2160,7 +2160,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> } ast::def_fn(id, _) | ast::def_const(id) | - ast::def_variant(_, id) | ast::def_class(id) { + ast::def_variant(_, id) | ast::def_class(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_binding(nid) { diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs index 2231d9b320a..d1052fd6a2a 100644 --- a/src/rustc/middle/typeck/check/regionmanip.rs +++ b/src/rustc/middle/typeck/check/regionmanip.rs @@ -200,7 +200,7 @@ fn region_of(fcx: @fn_ctxt, expr: @ast::expr) -> ty::region { ast::def_foreign_mod(_) | ast::def_const(_) | ast::def_use(_) | ast::def_variant(_, _) | ast::def_ty(_) | ast::def_prim_ty(_) | - ast::def_ty_param(_, _) | ast::def_class(_) | + ast::def_ty_param(_, _) | ast::def_class(_, _) | ast::def_region(_) { ty::re_static } diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc index 406c46cc6c6..b2cce508e57 100644 --- a/src/rustc/rustc.rc +++ b/src/rustc/rustc.rc @@ -88,6 +88,7 @@ mod middle { mod region; mod const_eval; mod astencode; + mod lang_items; } mod front { diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index a9f759b26aa..4a927744f07 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Debug.h" #include "llvm-c/Core.h" #include "llvm-c/BitReader.h" #include "llvm-c/Object.h" @@ -185,3 +186,7 @@ extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, unwrap(target), unwrap(source), order)); } + +extern "C" void LLVMSetDebug(int Enabled) { + DebugFlag = Enabled; +} diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index f3a3d7f4f23..64b560999be 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -528,6 +528,7 @@ LLVMSetAlignment LLVMSetCleanup LLVMSetCurrentDebugLocation LLVMSetDataLayout +LLVMSetDebug LLVMSetFunctionCallConv LLVMSetGC LLVMSetGlobalConstant diff --git a/src/test/compile-fail/not-utf8.bin b/src/test/compile-fail/not-utf8.bin new file mode 100644 index 00000000000..4148e5b88fe --- /dev/null +++ b/src/test/compile-fail/not-utf8.bin Binary files differdiff --git a/src/test/compile-fail/not-utf8.rs b/src/test/compile-fail/not-utf8.rs new file mode 100644 index 00000000000..2038f139359 --- /dev/null +++ b/src/test/compile-fail/not-utf8.rs @@ -0,0 +1,5 @@ +// error-pattern: is not UTF-8 + +fn foo() { + #include("not-utf8.bin") +} diff --git a/src/test/run-pass/issue-3029.rs b/src/test/run-pass/issue-3029.rs new file mode 100644 index 00000000000..352ada202e2 --- /dev/null +++ b/src/test/run-pass/issue-3029.rs @@ -0,0 +1,8 @@ +// xfail-test +fn fail_then_concat() { + let x = ~[], y = ~[3]; + fail; + x += y; + ~"good" + ~"bye"; +} + diff --git a/src/test/run-pass/issue-868.rs b/src/test/run-pass/issue-868.rs new file mode 100644 index 00000000000..dcc8c4e08db --- /dev/null +++ b/src/test/run-pass/issue-868.rs @@ -0,0 +1,15 @@ +fn f<T>(g: fn() -> T) -> T { g() } + +fn main() { + let _x = f( | | { 10 }); + // used to be: cannot determine a type for this expression + f(| | { }); + // ditto + f( | | { ()}); + // always worked + let _: () = f(| | { }); + // empty block with no type info should compile too + let _ = f(||{}); + let _ = (||{}); +} + diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index 532daf3651c..eb866ee7b3e 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -1,31 +1,29 @@ use std; -import comm; -import comm::chan; -import comm::send; +import pipes; +import pipes::chan; +import pipes::port; import task; fn main() { test05(); } fn test05_start(ch : chan<int>) { - log(error, ch); - send(ch, 10); + ch.send(10); #error("sent 10"); - send(ch, 20); + ch.send(20); #error("sent 20"); - send(ch, 30); + ch.send(30); #error("sent 30"); } fn test05() { - let po = comm::port(); - let ch = comm::chan(po); + let (ch, po) = pipes::stream(); task::spawn(|| test05_start(ch) ); - let mut value = comm::recv(po); + let mut value = po.recv(); log(error, value); - value = comm::recv(po); + value = po.recv(); log(error, value); - value = comm::recv(po); + value = po.recv(); log(error, value); assert (value == 30); } diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index 1d0963a29dc..ef94a13c072 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -1,28 +1,27 @@ use std; import task; -import comm; +import pipes; -fn start(c: comm::chan<comm::chan<~str>>) { - let p = comm::port(); - comm::send(c, comm::chan(p)); +fn start(c: pipes::chan<pipes::chan<~str>>) { + let (ch, p) = pipes::stream(); + c.send(ch); let mut a; let mut b; - a = comm::recv(p); + a = p.recv(); assert a == ~"A"; log(error, a); - b = comm::recv(p); + b = p.recv(); assert b == ~"B"; log(error, b); } fn main() { - let p = comm::port(); - let ch = comm::chan(p); + let (ch, p) = pipes::stream(); let child = task::spawn(|| start(ch) ); - let c = comm::recv(p); - comm::send(c, ~"A"); - comm::send(c, ~"B"); + let c = p.recv(); + c.send(~"A"); + c.send(~"B"); task::yield(); } diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index f96f9d148d0..5e1e5c5facd 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -1,15 +1,14 @@ use std; -import comm; +import pipes; import task; -fn start(c: comm::chan<comm::chan<int>>) { - let p: comm::port<int> = comm::port(); - comm::send(c, comm::chan(p)); +fn start(c: pipes::chan<pipes::chan<int>>) { + let (ch, p) = pipes::stream(); + c.send(ch); } fn main() { - let p = comm::port(); - let ch = comm::chan(p); + let (ch, p) = pipes::stream(); let child = task::spawn(|| start(ch) ); - let c = comm::recv(p); + let c = p.recv(); } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index 3ded4aac5ae..88220437c43 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -1,17 +1,16 @@ use std; import task; -import comm; -import comm::send; +import pipes; +import pipes::send; -fn start(c: comm::chan<int>, start: int, number_of_messages: int) { +fn start(c: pipes::chan<int>, start: int, number_of_messages: int) { let mut i: int = 0; - while i < number_of_messages { send(c, start + i); i += 1; } + while i < number_of_messages { c.send(start + i); i += 1; } } fn main() { #debug("Check that we don't deadlock."); - let p = comm::port::<int>(); - let ch = comm::chan(p); + let (ch, p) = pipes::stream(); task::try(|| start(ch, 0, 10) ); #debug("Joined task"); } diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index ef9c4ae5010..268b6d06dfd 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -1,15 +1,14 @@ -use std; -import comm; import task; fn main() { - let po = comm::port::<int>(); - let ch = comm::chan(po); + let po = pipes::port_set(); // Spawn 10 tasks each sending us back one int. let mut i = 10; while (i > 0) { log(debug, i); + let (ch, p) = pipes::stream(); + po.add(p); task::spawn(|copy i| child(i, ch) ); i = i - 1; } @@ -18,17 +17,16 @@ fn main() { // anything back, so we deadlock here. i = 10; - let mut value = 0; while (i > 0) { log(debug, i); - value = comm::recv(po); + po.recv(); i = i - 1; } #debug("main thread exiting"); } -fn child(x: int, ch: comm::chan<int>) { +fn child(x: int, ch: pipes::chan<int>) { log(debug, x); - comm::send(ch, copy x); + ch.send(x); } diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index d9291fd6898..71a732490ce 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -1,23 +1,21 @@ // xfail-win32 use std; -import comm; import task; -fn start(c: comm::chan<int>, i0: int) { +fn start(c: pipes::chan<int>, i0: int) { let mut i = i0; while i > 0 { - comm::send(c, 0); + c.send(0); i = i - 1; } } fn main() { - let p = comm::port(); // Spawn a task that sends us back messages. The parent task // is likely to terminate before the child completes, so from // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! - let ch = comm::chan(p); - let child = task::spawn(|| start(ch, 10) ); - let c = comm::recv(p); + let (ch, p) = pipes::stream(); + task::spawn(|| start(ch, 10)); + p.recv(); } diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index bc46de64cd7..2d1c72df713 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -1,44 +1,41 @@ // -*- rust -*- use std; -import comm; -import comm::send; -import comm::port; -import comm::recv; -import comm::chan; +import pipes; +import pipes::send; +import pipes::port; +import pipes::recv; +import pipes::chan; // Tests of ports and channels on various types fn test_rec() { type r = {val0: int, val1: u8, val2: char}; - let po = comm::port(); - let ch = chan(po); + let (ch, po) = pipes::stream(); let r0: r = {val0: 0, val1: 1u8, val2: '2'}; - send(ch, r0); + ch.send(r0); let mut r1: r; - r1 = recv(po); + r1 = po.recv(); assert (r1.val0 == 0); assert (r1.val1 == 1u8); assert (r1.val2 == '2'); } fn test_vec() { - let po = port(); - let ch = chan(po); + let (ch, po) = pipes::stream(); let v0: ~[int] = ~[0, 1, 2]; - send(ch, v0); - let v1 = recv(po); + ch.send(v0); + let v1 = po.recv(); assert (v1[0] == 0); assert (v1[1] == 1); assert (v1[2] == 2); } fn test_str() { - let po = port(); - let ch = chan(po); - let s0 = ~"test"; - send(ch, s0); - let s1 = recv(po); + let (ch, po) = pipes::stream(); + let s0 = "test"; + ch.send(s0); + let s1 = po.recv(); assert (s1[0] == 't' as u8); assert (s1[1] == 'e' as u8); assert (s1[2] == 's' as u8); @@ -47,33 +44,36 @@ fn test_str() { fn test_tag() { enum t { tag1, tag2(int), tag3(int, u8, char), } - let po = port(); - let ch = chan(po); - send(ch, tag1); - send(ch, tag2(10)); - send(ch, tag3(10, 11u8, 'A')); + let (ch, po) = pipes::stream(); + ch.send(tag1); + ch.send(tag2(10)); + ch.send(tag3(10, 11u8, 'A')); let mut t1: t; - t1 = recv(po); + t1 = po.recv(); assert (t1 == tag1); - t1 = recv(po); + t1 = po.recv(); assert (t1 == tag2(10)); - t1 = recv(po); + t1 = po.recv(); assert (t1 == tag3(10, 11u8, 'A')); } fn test_chan() { - let po = port(); - let ch = chan(po); - let po0 = port(); - let ch0 = chan(po0); - send(ch, ch0); - let ch1 = recv(po); + let (ch, po) = pipes::stream(); + let (ch0, po0) = pipes::stream(); + ch.send(ch0); + let ch1 = po.recv(); // Does the transmitted channel still work? - send(ch1, 10); + ch1.send(10); let mut i: int; - i = recv(po0); + i = po0.recv(); assert (i == 10); } -fn main() { test_rec(); test_vec(); test_str(); test_tag(); test_chan(); } +fn main() { + test_rec(); + test_vec(); + test_str(); + test_tag(); + test_chan(); +} diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index c03db442022..05c057d85fd 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -1,9 +1,9 @@ use std; import task; -import comm; -import comm::chan; -import comm::send; -import comm::recv; +import pipes; +import pipes::chan; +import pipes::send; +import pipes::recv; fn main() { #debug("===== WITHOUT THREADS ====="); test00(); } @@ -12,7 +12,7 @@ fn test00_start(ch: chan<int>, message: int, count: int) { let mut i: int = 0; while i < count { #debug("Sending Message"); - send(ch, message + 0); + ch.send(message + 0); i = i + 1; } #debug("Ending test00_start"); @@ -24,14 +24,14 @@ fn test00() { #debug("Creating tasks"); - let po = comm::port(); - let ch = chan(po); + let po = pipes::port_set(); let mut i: int = 0; // Create and spawn tasks... let mut results = ~[]; while i < number_of_tasks { + let ch = po.chan(); do task::task().future_result(|-r| { results += ~[r]; }).spawn |copy i| { @@ -45,7 +45,7 @@ fn test00() { for results.each |r| { i = 0; while i < number_of_messages { - let value = recv(po); + let value = po.recv(); sum += value; i = i + 1; } diff --git a/src/test/run-pass/task-comm-4.rs b/src/test/run-pass/task-comm-4.rs index f7de33c63d6..9b99c1cb799 100644 --- a/src/test/run-pass/task-comm-4.rs +++ b/src/test/run-pass/task-comm-4.rs @@ -1,44 +1,43 @@ use std; -import comm; -import comm::send; +import pipes; +import pipes::send; fn main() { test00(); } fn test00() { let mut r: int = 0; let mut sum: int = 0; - let p = comm::port(); - let c = comm::chan(p); - send(c, 1); - send(c, 2); - send(c, 3); - send(c, 4); - r = comm::recv(p); + let (c, p) = pipes::stream(); + c.send(1); + c.send(2); + c.send(3); + c.send(4); + r = p.recv(); sum += r; log(debug, r); - r = comm::recv(p); + r = p.recv(); sum += r; log(debug, r); - r = comm::recv(p); + r = p.recv(); sum += r; log(debug, r); - r = comm::recv(p); + r = p.recv(); sum += r; log(debug, r); - send(c, 5); - send(c, 6); - send(c, 7); - send(c, 8); - r = comm::recv(p); + c.send(5); + c.send(6); + c.send(7); + c.send(8); + r = p.recv(); sum += r; log(debug, r); - r = comm::recv(p); + r = p.recv(); sum += r; log(debug, r); - r = comm::recv(p); + r = p.recv(); sum += r; log(debug, r); - r = comm::recv(p); + r = p.recv(); sum += r; log(debug, r); assert (sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); diff --git a/src/test/run-pass/task-comm-5.rs b/src/test/run-pass/task-comm-5.rs index a0d4f4595be..249bdaf1c9a 100644 --- a/src/test/run-pass/task-comm-5.rs +++ b/src/test/run-pass/task-comm-5.rs @@ -1,17 +1,16 @@ use std; -import comm; +import pipes; fn main() { test00(); } fn test00() { let r: int = 0; let mut sum: int = 0; - let p = comm::port(); - let c = comm::chan(p); + let (c, p) = pipes::stream(); let number_of_messages: int = 1000; let mut i: int = 0; - while i < number_of_messages { comm::send(c, i + 0); i += 1; } + while i < number_of_messages { c.send(i + 0); i += 1; } i = 0; - while i < number_of_messages { sum += comm::recv(p); i += 1; } + while i < number_of_messages { sum += p.recv(); i += 1; } assert (sum == number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs index b363b25e864..8bc93a78913 100644 --- a/src/test/run-pass/task-comm-6.rs +++ b/src/test/run-pass/task-comm-6.rs @@ -1,37 +1,37 @@ use std; -import comm; -import comm::send; -import comm::chan; -import comm::recv; +import pipes; +import pipes::send; +import pipes::chan; +import pipes::recv; fn main() { test00(); } fn test00() { let mut r: int = 0; let mut sum: int = 0; - let p = comm::port(); - let c0 = chan(p); - let c1 = chan(p); - let c2 = chan(p); - let c3 = chan(p); + let p = pipes::port_set(); + let c0 = p.chan(); + let c1 = p.chan(); + let c2 = p.chan(); + let c3 = p.chan(); let number_of_messages: int = 1000; let mut i: int = 0; while i < number_of_messages { - send(c0, i + 0); - send(c1, i + 0); - send(c2, i + 0); - send(c3, i + 0); + c0.send(i + 0); + c1.send(i + 0); + c2.send(i + 0); + c3.send(i + 0); i += 1; } i = 0; while i < number_of_messages { - r = recv(p); + r = p.recv(); sum += r; - r = recv(p); + r = p.recv(); sum += r; - r = recv(p); + r = p.recv(); sum += r; - r = recv(p); + r = p.recv(); sum += r; i += 1; } diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index b8922400777..1df3de6ba1e 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -1,43 +1,45 @@ use std; import task; -import comm; fn main() { test00(); } -fn test00_start(c: comm::chan<int>, start: int, number_of_messages: int) { +fn test00_start(c: pipes::chan<int>, start: int, number_of_messages: int) { let mut i: int = 0; - while i < number_of_messages { comm::send(c, start + i); i += 1; } + while i < number_of_messages { c.send(start + i); i += 1; } } fn test00() { let mut r: int = 0; let mut sum: int = 0; - let p = comm::port(); + let p = pipes::port_set(); let number_of_messages: int = 10; - let c = comm::chan(p); + let c = p.chan(); do task::spawn { test00_start(c, number_of_messages * 0, number_of_messages); } + let c = p.chan(); do task::spawn { test00_start(c, number_of_messages * 1, number_of_messages); } + let c = p.chan(); do task::spawn { test00_start(c, number_of_messages * 2, number_of_messages); } + let c = p.chan(); do task::spawn { test00_start(c, number_of_messages * 3, number_of_messages); } let mut i: int = 0; while i < number_of_messages { - r = comm::recv(p); + r = p.recv(); sum += r; - r = comm::recv(p); + r = p.recv(); sum += r; - r = comm::recv(p); + r = p.recv(); sum += r; - r = comm::recv(p); + r = p.recv(); sum += r; i += 1; } diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 964029dee20..939cfd15797 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -1,20 +1,19 @@ use std; import task; -import comm; fn main() { test00(); } -fn test00_start(c: comm::chan<int>, number_of_messages: int) { +fn test00_start(c: pipes::chan<int>, number_of_messages: int) { let mut i: int = 0; - while i < number_of_messages { comm::send(c, i + 0); i += 1; } + while i < number_of_messages { c.send(i + 0); i += 1; } } fn test00() { let r: int = 0; let mut sum: int = 0; - let p = comm::port(); + let p = pipes::port_set(); let number_of_messages: int = 10; - let ch = comm::chan(p); + let ch = p.chan(); let mut result = none; do task::task().future_result(|-r| { result = some(r); }).spawn { @@ -23,7 +22,7 @@ fn test00() { let mut i: int = 0; while i < number_of_messages { - sum += comm::recv(p); + sum += p.recv(); log(debug, r); i += 1; } diff --git a/src/test/run-pass/trivial-message.rs b/src/test/run-pass/trivial-message.rs index 487b440ee42..ab3efd6b22e 100644 --- a/src/test/run-pass/trivial-message.rs +++ b/src/test/run-pass/trivial-message.rs @@ -1,14 +1,12 @@ -use std; -import comm::*; +import pipes::{port, chan}; /* This is about the simplest program that can successfully send a message. */ fn main() { - let po = port(); - let ch = chan(po); - send(ch, 42); - let r = recv(po); + let (ch, po) = pipes::stream(); + ch.send(42); + let r = po.recv(); log(error, r); } diff --git a/src/test/run-pass/unreachable-code.rs b/src/test/run-pass/unreachable-code.rs new file mode 100644 index 00000000000..0d1a4991751 --- /dev/null +++ b/src/test/run-pass/unreachable-code.rs @@ -0,0 +1,31 @@ +// xfail-pretty + +fn id(x: bool) -> bool { x } + +fn call_id() { + let c <- fail; + id(c); +} + +fn call_id_2() { id(true) && id(ret); } + +fn call_id_3() { id(ret) && id(ret); } + +fn log_fail() { log(error, fail); } + +fn log_ret() { log(error, ret); } + +fn log_break() { loop { log(error, break); } } + +fn log_again() { loop { log(error, again); } } + +fn ret_ret() -> int { ret (ret 2) + 3; } + +fn ret_guard() { + alt 2 { + x if (ret) { x; } + _ {} + } +} + +fn main() {} |
