diff options
Diffstat (limited to 'src')
119 files changed, 4132 insertions, 3313 deletions
diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 54723253141..2a28b767d0a 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -33,34 +33,36 @@ fn load_errors(testfile: &Path) -> ~[expected_error] { return error_patterns; } -fn parse_expected(line_num: uint, line: ~str) -> ~[expected_error] unsafe { - let error_tag = ~"//~"; - let mut idx; - match str::find_str(line, error_tag) { - None => return ~[], - Some(nn) => { idx = (nn as uint) + str::len(error_tag); } - } +fn parse_expected(line_num: uint, line: ~str) -> ~[expected_error] { + unsafe { + let error_tag = ~"//~"; + let mut idx; + match str::find_str(line, error_tag) { + None => return ~[], + Some(nn) => { idx = (nn as uint) + str::len(error_tag); } + } - // "//~^^^ kind msg" denotes a message expected - // three lines above current line: - let mut adjust_line = 0u; - let len = str::len(line); - while idx < len && line[idx] == ('^' as u8) { - adjust_line += 1u; - idx += 1u; - } + // "//~^^^ kind msg" denotes a message expected + // three lines above current line: + let mut adjust_line = 0u; + let len = str::len(line); + while idx < len && line[idx] == ('^' as u8) { + adjust_line += 1u; + idx += 1u; + } - // Extract kind: - while idx < len && line[idx] == (' ' as u8) { idx += 1u; } - let start_kind = idx; - while idx < len && line[idx] != (' ' as u8) { idx += 1u; } - let kind = str::to_lower(str::slice(line, start_kind, idx)); + // Extract kind: + while idx < len && line[idx] == (' ' as u8) { idx += 1u; } + let start_kind = idx; + while idx < len && line[idx] != (' ' as u8) { idx += 1u; } + let kind = str::to_lower(str::slice(line, start_kind, idx)); - // Extract msg: - while idx < len && line[idx] == (' ' as u8) { idx += 1u; } - let msg = str::slice(line, idx, len); + // Extract msg: + while idx < len && line[idx] == (' ' as u8) { idx += 1u; } + let msg = str::slice(line, idx, len); - debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg); + debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg); - return ~[{line: line_num - adjust_line, kind: kind, msg: msg}]; + return ~[{line: line_num - adjust_line, kind: kind, msg: msg}]; + } } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 9fe5d9acb9b..e0a170c7445 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -146,15 +146,17 @@ fn parse_name_directive(line: ~str, directive: ~str) -> bool { } fn parse_name_value_directive(line: ~str, - directive: ~str) -> Option<~str> unsafe { - let keycolon = directive + ~":"; - match str::find_str(line, keycolon) { - Some(colon) => { - let value = str::slice(line, colon + str::len(keycolon), - str::len(line)); - debug!("%s: %s", directive, value); - Some(value) + directive: ~str) -> Option<~str> { + unsafe { + let keycolon = directive + ~":"; + match str::find_str(line, keycolon) { + Some(colon) => { + let value = str::slice(line, colon + str::len(keycolon), + str::len(line)); + debug!("%s: %s", directive, value); + Some(value) + } + None => None } - None => None } } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 7b0ef583f40..f1af335eebf 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -273,7 +273,7 @@ fn check_expected_errors(expected_errors: ~[errors::expected_error], procres: procres) { // true if we found the error in question - let found_flags = vec::to_mut(vec::from_elem( + let found_flags = vec::cast_to_mut(vec::from_elem( vec::len(expected_errors), false)); if procres.status == 0 { diff --git a/src/libcargo/cargo.rc b/src/libcargo/cargo.rc index dc48266e152..193adc10997 100644 --- a/src/libcargo/cargo.rc +++ b/src/libcargo/cargo.rc @@ -1135,28 +1135,30 @@ fn get_temp_workdir(c: &Cargo) -> Path { } } -fn cmd_install(c: &Cargo) unsafe { - let wd = get_temp_workdir(c); +fn cmd_install(c: &Cargo) { + unsafe { + let wd = get_temp_workdir(c); - if vec::len(c.opts.free) == 2u { - let cwd = os::getcwd(); - let status = run::run_program(~"cp", ~[~"-R", cwd.to_str(), - wd.to_str()]); + if vec::len(c.opts.free) == 2u { + let cwd = os::getcwd(); + let status = run::run_program(~"cp", ~[~"-R", cwd.to_str(), + wd.to_str()]); - if status != 0 { - fail fmt!("could not copy directory: %s", cwd.to_str()); - } + if status != 0 { + fail fmt!("could not copy directory: %s", cwd.to_str()); + } - install_source(c, &wd); - return; - } + install_source(c, &wd); + return; + } - sync(c); + sync(c); - let query = c.opts.free[2]; - c.current_install = query.to_str(); + let query = c.opts.free[2]; + c.current_install = query.to_str(); - install_query(c, &wd, query); + install_query(c, &wd, query); + } } fn sync(c: &Cargo) { diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index c6285f62377..aa63f253fee 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -154,7 +154,7 @@ pub pure fn from_elem<T: Copy>(n_elts: uint, t: T) -> @[T] { * Creates and initializes an immutable managed vector by moving all the * elements from an owned vector. */ -fn from_owned<T>(v: ~[T]) -> @[T] { +pub fn from_owned<T>(v: ~[T]) -> @[T] { let mut av = @[]; unsafe { raw::reserve(&mut av, v.len()); @@ -169,7 +169,7 @@ fn from_owned<T>(v: ~[T]) -> @[T] { * Creates and initializes an immutable managed vector by copying all the * elements of a slice. */ -fn from_slice<T:Copy>(v: &[T]) -> @[T] { +pub fn from_slice<T:Copy>(v: &[T]) -> @[T] { from_fn(v.len(), |i| v[i]) } diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index 92ac1faf306..34b058f6a3b 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -145,7 +145,7 @@ impl<A> DVec<A> { #[inline(always)] fn swap_mut(f: &fn(v: ~[mut A]) -> ~[mut A]) { do self.swap |v| { - vec::from_mut(f(vec::to_mut(move v))) + vec::cast_from_mut(f(vec::cast_to_mut(move v))) } } diff --git a/src/libcore/f32.rs b/src/libcore/f32.rs index 4c1cc890de9..795a9f9371c 100644 --- a/src/libcore/f32.rs +++ b/src/libcore/f32.rs @@ -56,7 +56,6 @@ delegate!(fn exp2(n: c_float) -> c_float = cmath::c_float_utils::exp2) delegate!(fn abs(n: c_float) -> c_float = cmath::c_float_utils::abs) delegate!(fn abs_sub(a: c_float, b: c_float) -> c_float = cmath::c_float_utils::abs_sub) -delegate!(fn floor(n: c_float) -> c_float = cmath::c_float_utils::floor) delegate!(fn mul_add(a: c_float, b: c_float, c: c_float) -> c_float = cmath::c_float_utils::mul_add) delegate!(fn fmax(a: c_float, b: c_float) -> c_float = @@ -141,6 +140,10 @@ pub pure fn ge(x: f32, y: f32) -> bool { return x >= y; } #[inline(always)] pub pure fn gt(x: f32, y: f32) -> bool { return x > y; } +/// Returns `x` rounded down +#[inline(always)] +pub pure fn floor(x: f32) -> f32 { unsafe { floorf32(x) } } + // FIXME (#1999): replace the predicates below with llvm intrinsics or // calls to the libmath macros in the rust runtime for performance. @@ -298,6 +301,11 @@ impl f32: num::One { static pure fn one() -> f32 { 1.0 } } +#[abi="rust-intrinsic"] +pub extern { + fn floorf32(val: f32) -> f32; +} + // // Local Variables: // mode: rust diff --git a/src/libcore/f64.rs b/src/libcore/f64.rs index cbcdc2e81e6..8cd94c9357d 100644 --- a/src/libcore/f64.rs +++ b/src/libcore/f64.rs @@ -57,7 +57,6 @@ delegate!(fn exp2(n: c_double) -> c_double = cmath::c_double_utils::exp2) delegate!(fn abs(n: c_double) -> c_double = cmath::c_double_utils::abs) delegate!(fn abs_sub(a: c_double, b: c_double) -> c_double = cmath::c_double_utils::abs_sub) -delegate!(fn floor(n: c_double) -> c_double = cmath::c_double_utils::floor) delegate!(fn mul_add(a: c_double, b: c_double, c: c_double) -> c_double = cmath::c_double_utils::mul_add) delegate!(fn fmax(a: c_double, b: c_double) -> c_double = @@ -210,12 +209,16 @@ pub pure fn is_infinite(x: f64) -> bool { return x == infinity || x == neg_infinity; } -/// Returns true if `x`is a finite number +/// Returns true if `x` is a finite number #[inline(always)] pub pure fn is_finite(x: f64) -> bool { return !(is_NaN(x) || is_infinite(x)); } +/// Returns `x` rounded down +#[inline(always)] +pub pure fn floor(x: f64) -> f64 { unsafe { floorf64(x) } } + // FIXME (#1999): add is_normal, is_subnormal, and fpclassify /* Module: consts */ @@ -322,6 +325,11 @@ impl f64: num::One { static pure fn one() -> f64 { 1.0 } } +#[abi="rust-intrinsic"] +pub extern { + fn floorf64(val: f64) -> f64; +} + // // Local Variables: // mode: rust diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index cc318fb4add..c44a814e53b 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -109,14 +109,36 @@ pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T } * ~~~ */ #[inline(always)] -pub pure fn range(lo: T, hi: T, it: fn(T) -> bool) { - let mut i = lo; - while i < hi { - if !it(i) { break } - i += 1 as T; +/// Iterate over the range [`start`,`start`+`step`..`stop`) +pub pure fn range_step(start: T, stop: T, step: T, it: fn(T) -> bool) { + let mut i = start; + if step == 0 { + fail ~"range_step called with step == 0"; + } else if step > 0 { // ascending + while i < stop { + if !it(i) { break } + i += step; + } + } else { // descending + while i > stop { + if !it(i) { break } + i += step; + } } } +#[inline(always)] +/// Iterate over the range [`lo`..`hi`) +pub pure fn range(lo: T, hi: T, it: fn(T) -> bool) { + range_step(lo, hi, 1 as T, it); +} + +#[inline(always)] +/// Iterate over the range [`hi`..`lo`) +pub pure fn range_rev(hi: T, lo: T, it: fn(T) -> bool) { + range_step(hi, lo, -1 as T, it); +} + /// Computes the bitwise complement #[inline(always)] pub pure fn compl(i: T) -> T { @@ -351,3 +373,45 @@ fn test_times_negative() { use iter::Times; for (-10).times { log(error, ~"nope!"); } } + +#[test] +pub fn test_ranges() { + let mut l = ~[]; + + for range(0,3) |i| { + l.push(i); + } + for range_rev(13,10) |i| { + l.push(i); + } + for range_step(20,26,2) |i| { + l.push(i); + } + for range_step(36,30,-2) |i| { + l.push(i); + } + assert l == ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32]; + + // None of the `fail`s should execute. + for range(10,0) |_i| { + fail ~"unreachable"; + } + for range_rev(0,10) |_i| { + fail ~"unreachable"; + } + for range_step(10,0,1) |_i| { + fail ~"unreachable"; + } + for range_step(0,10,-1) |_i| { + fail ~"unreachable"; + } +} + +#[test] +#[should_fail] +fn test_range_step_zero_step() { + for range_step(0,10,0) |_i| {} +} diff --git a/src/libcore/oldcomm.rs b/src/libcore/oldcomm.rs index ae3116b08f0..c221df293dc 100644 --- a/src/libcore/oldcomm.rs +++ b/src/libcore/oldcomm.rs @@ -121,8 +121,9 @@ pub fn listen<T: Owned, U>(f: fn(Chan<T>) -> U) -> U { } struct PortPtr<T:Owned> { - po: *rust_port, - drop unsafe { + po: *rust_port, + drop { + unsafe { do task::unkillable { // Once the port is detached it's guaranteed not to receive further // messages @@ -140,6 +141,7 @@ struct PortPtr<T:Owned> { recv_::<T>(self.po); } rustrt::del_port(self.po); + } } } } @@ -209,7 +211,7 @@ pub fn send<T: Owned>(ch: Chan<T>, data: T) { let Chan_(p) = ch; let data_ptr = ptr::addr_of(&data) as *(); let res = rustrt::rust_port_id_send(p, data_ptr); - if res != 0 unsafe { + if res != 0 { // Data sent successfully cast::forget(move data); } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index ffd41bc05b1..d30d0905a0f 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -84,10 +84,12 @@ pub fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T { pub fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool) -> Option<~str> { - let buf = vec::to_mut(vec::from_elem(tmpbuf_sz, 0u8 as c_char)); + let buf = vec::cast_to_mut(vec::from_elem(tmpbuf_sz, 0u8 as c_char)); do vec::as_mut_buf(buf) |b, sz| { - if f(b, sz as size_t) unsafe { - Some(str::raw::from_buf(b as *u8)) + if f(b, sz as size_t) { + unsafe { + Some(str::raw::from_buf(b as *u8)) + } } else { None } @@ -111,7 +113,7 @@ pub mod win32 { let mut res = None; let mut done = false; while !done { - let buf = vec::to_mut(vec::from_elem(n as uint, 0u16)); + let buf = vec::cast_to_mut(vec::from_elem(n as uint, 0u16)); do vec::as_mut_buf(buf) |b, _sz| { let k : DWORD = f(b, tmpbuf_sz as DWORD); if k == (0 as DWORD) { @@ -1269,7 +1271,7 @@ mod tests { }; assert (ostream as uint != 0u); let s = ~"hello"; - let mut buf = vec::to_mut(str::to_bytes(s) + ~[0 as u8]); + let mut buf = vec::cast_to_mut(str::to_bytes(s) + ~[0 as u8]); do vec::as_mut_buf(buf) |b, _len| { assert (libc::fwrite(b as *c_void, 1u as size_t, (str::len(s) + 1u) as size_t, ostream) diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index c25a7a66c48..b32357e7356 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -193,8 +193,10 @@ impl PacketHeader { reinterpret_cast(&self.buffer) } - fn set_buffer<T: Owned>(b: ~Buffer<T>) unsafe { - self.buffer = reinterpret_cast(&b); + fn set_buffer<T: Owned>(b: ~Buffer<T>) { + unsafe { + self.buffer = reinterpret_cast(&b); + } } } @@ -356,19 +358,21 @@ pub unsafe fn get_buffer<T: Owned>(p: *PacketHeader) -> ~Buffer<T> { struct BufferResource<T: Owned> { buffer: ~Buffer<T>, - drop unsafe { - let b = move_it!(self.buffer); - //let p = ptr::addr_of(*b); - //error!("drop %?", p); - let old_count = atomic_sub_rel(&mut b.header.ref_count, 1); - //let old_count = atomic_xchng_rel(b.header.ref_count, 0); - if old_count == 1 { - // The new count is 0. - - // go go gadget drop glue - } - else { - forget(move b) + drop { + unsafe { + let b = move_it!(self.buffer); + //let p = ptr::addr_of(*b); + //error!("drop %?", p); + let old_count = atomic_sub_rel(&mut b.header.ref_count, 1); + //let old_count = atomic_xchng_rel(b.header.ref_count, 0); + if old_count == 1 { + // The new count is 0. + + // go go gadget drop glue + } + else { + forget(move b) + } } } } @@ -641,18 +645,20 @@ fn wait_many<T: Selectable>(pkts: &[T]) -> uint { let mut data_avail = false; let mut ready_packet = pkts.len(); - for pkts.eachi |i, p| unsafe { - let p = unsafe { &*p.header() }; - let old = p.mark_blocked(this); - match old { - Full | Terminated => { - data_avail = true; - ready_packet = i; - (*p).state = old; - break; - } - Blocked => fail ~"blocking on blocked packet", - Empty => () + for pkts.eachi |i, p| { + unsafe { + let p = &*p.header(); + let old = p.mark_blocked(this); + match old { + Full | Terminated => { + data_avail = true; + ready_packet = i; + (*p).state = old; + break; + } + Blocked => fail ~"blocking on blocked packet", + Empty => () + } } } @@ -1072,23 +1078,27 @@ impl<T: Owned> Port<T>: GenericPort<T> { } impl<T: Owned> Port<T>: Peekable<T> { - pure fn peek() -> bool unsafe { - let mut endp = None; - endp <-> self.endp; - let peek = match &endp { - &Some(ref endp) => pipes::peek(endp), - &None => fail ~"peeking empty stream" - }; - self.endp <-> endp; - peek + pure fn peek() -> bool { + unsafe { + let mut endp = None; + endp <-> self.endp; + let peek = match &endp { + &Some(ref endp) => pipes::peek(endp), + &None => fail ~"peeking empty stream" + }; + self.endp <-> endp; + peek + } } } impl<T: Owned> Port<T>: Selectable { - pure fn header() -> *PacketHeader unsafe { - match self.endp { - Some(ref endp) => endp.header(), - None => fail ~"peeking empty stream" + pure fn header() -> *PacketHeader { + unsafe { + match self.endp { + Some(ref endp) => endp.header(), + None => fail ~"peeking empty stream" + } } } } diff --git a/src/libcore/private.rs b/src/libcore/private.rs index c4401ec0d7e..1d6260db130 100644 --- a/src/libcore/private.rs +++ b/src/libcore/private.rs @@ -64,22 +64,26 @@ pub unsafe fn run_in_bare_thread(f: ~fn()) { let (port, chan) = pipes::stream(); // FIXME #4525: Unfortunate that this creates an extra scheduler but it's // necessary since rust_raw_thread_join_delete is blocking - do task::spawn_sched(task::SingleThreaded) unsafe { - let closure: &fn() = || { - f() - }; - let thread = rustrt::rust_raw_thread_start(closure); - rustrt::rust_raw_thread_join_delete(thread); - chan.send(()); + do task::spawn_sched(task::SingleThreaded) { + unsafe { + let closure: &fn() = || { + f() + }; + let thread = rustrt::rust_raw_thread_start(closure); + rustrt::rust_raw_thread_join_delete(thread); + chan.send(()); + } } port.recv(); } #[test] -fn test_run_in_bare_thread() unsafe { - let i = 100; - do run_in_bare_thread { - assert i == 100; +fn test_run_in_bare_thread() { + unsafe { + let i = 100; + do run_in_bare_thread { + assert i == 100; + } } } @@ -273,8 +277,10 @@ pub unsafe fn weaken_task(f: fn(oldcomm::Port<()>)) { struct Unweaken { ch: oldcomm::Chan<()>, - drop unsafe { - rustrt::rust_task_unweaken(cast::reinterpret_cast(&self.ch)); + drop { + unsafe { + rustrt::rust_task_unweaken(cast::reinterpret_cast(&self.ch)); + } } } @@ -359,37 +365,40 @@ struct ArcData<T> { struct ArcDestruct<T> { mut data: *libc::c_void, - drop unsafe { - if self.data.is_null() { - return; // Happens when destructing an unwrapper's handle. - } - do task::unkillable { - let data: ~ArcData<T> = cast::reinterpret_cast(&self.data); - let new_count = rusti::atomic_xsub(&mut data.count, 1) - 1; - assert new_count >= 0; - if new_count == 0 { - // Were we really last, or should we hand off to an unwrapper? - // It's safe to not xchg because the unwrapper will set the - // unwrap lock *before* dropping his/her reference. In effect, - // being here means we're the only *awake* task with the data. - if data.unwrapper != 0 { - let p: UnwrapProto = - cast::reinterpret_cast(&data.unwrapper); - let (message, response) = option::swap_unwrap(p); - // Send 'ready' and wait for a response. - pipes::send_one(move message, ()); - // Unkillable wait. Message guaranteed to come. - if pipes::recv_one(move response) { - // Other task got the data. - cast::forget(move data); + drop { + unsafe { + if self.data.is_null() { + return; // Happens when destructing an unwrapper's handle. + } + do task::unkillable { + let data: ~ArcData<T> = cast::reinterpret_cast(&self.data); + let new_count = rusti::atomic_xsub(&mut data.count, 1) - 1; + assert new_count >= 0; + if new_count == 0 { + // Were we really last, or should we hand off to an + // unwrapper? It's safe to not xchg because the unwrapper + // will set the unwrap lock *before* dropping his/her + // reference. In effect, being here means we're the only + // *awake* task with the data. + if data.unwrapper != 0 { + let p: UnwrapProto = + cast::reinterpret_cast(&data.unwrapper); + let (message, response) = option::swap_unwrap(p); + // Send 'ready' and wait for a response. + pipes::send_one(move message, ()); + // Unkillable wait. Message guaranteed to come. + if pipes::recv_one(move response) { + // Other task got the data. + cast::forget(move data); + } else { + // Other task was killed. drop glue takes over. + } } else { - // Other task was killed. drop glue takes over. + // drop glue takes over. } } else { - // drop glue takes over. + cast::forget(move data); } - } else { - cast::forget(move data); } } } @@ -406,18 +415,21 @@ pub unsafe fn unwrap_shared_mutable_state<T: Owned>(rc: SharedMutableState<T>) struct DeathThroes<T> { mut ptr: Option<~ArcData<T>>, mut response: Option<pipes::ChanOne<bool>>, - drop unsafe { - let response = option::swap_unwrap(&mut self.response); - // In case we get killed early, we need to tell the person who - // tried to wake us whether they should hand-off the data to us. - if task::failing() { - pipes::send_one(move response, false); - // Either this swap_unwrap or the one below (at "Got here") - // ought to run. - cast::forget(option::swap_unwrap(&mut self.ptr)); - } else { - assert self.ptr.is_none(); - pipes::send_one(move response, true); + drop { + unsafe { + let response = option::swap_unwrap(&mut self.response); + // In case we get killed early, we need to tell the person who + // tried to wake us whether they should hand-off the data to + // us. + if task::failing() { + pipes::send_one(move response, false); + // Either this swap_unwrap or the one below (at "Got + // here") ought to run. + cast::forget(option::swap_unwrap(&mut self.ptr)); + } else { + assert self.ptr.is_none(); + pipes::send_one(move response, true); + } } } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 513a3095292..f059c119f49 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -165,8 +165,10 @@ pub pure fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T { (I couldn't think of a cutesy name for this one.) */ #[inline(always)] -pub pure fn to_uint<T>(thing: &T) -> uint unsafe { - cast::reinterpret_cast(&thing) +pub pure fn to_uint<T>(thing: &T) -> uint { + unsafe { + cast::reinterpret_cast(&thing) + } } /// Determine if two borrowed pointers point to the same thing. @@ -215,10 +217,12 @@ impl<T> *mut T: Ptr<T> { #[cfg(notest)] impl<T> *const T : Eq { #[inline(always)] - pure fn eq(&self, other: &*const T) -> bool unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); - return a == b; + pure fn eq(&self, other: &*const T) -> bool { + unsafe { + let a: uint = cast::reinterpret_cast(&(*self)); + let b: uint = cast::reinterpret_cast(&(*other)); + return a == b; + } } #[inline(always)] pure fn ne(&self, other: &*const T) -> bool { !(*self).eq(other) } @@ -228,28 +232,36 @@ impl<T> *const T : Eq { #[cfg(notest)] impl<T> *const T : Ord { #[inline(always)] - pure fn lt(&self, other: &*const T) -> bool unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); - return a < b; + pure fn lt(&self, other: &*const T) -> bool { + unsafe { + let a: uint = cast::reinterpret_cast(&(*self)); + let b: uint = cast::reinterpret_cast(&(*other)); + return a < b; + } } #[inline(always)] - pure fn le(&self, other: &*const T) -> bool unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); - return a <= b; + pure fn le(&self, other: &*const T) -> bool { + unsafe { + let a: uint = cast::reinterpret_cast(&(*self)); + let b: uint = cast::reinterpret_cast(&(*other)); + return a <= b; + } } #[inline(always)] - pure fn ge(&self, other: &*const T) -> bool unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); - return a >= b; + pure fn ge(&self, other: &*const T) -> bool { + unsafe { + let a: uint = cast::reinterpret_cast(&(*self)); + let b: uint = cast::reinterpret_cast(&(*other)); + return a >= b; + } } #[inline(always)] - pure fn gt(&self, other: &*const T) -> bool unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); - return a > b; + pure fn gt(&self, other: &*const T) -> bool { + unsafe { + let a: uint = cast::reinterpret_cast(&(*self)); + let b: uint = cast::reinterpret_cast(&(*other)); + return a > b; + } } } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d1c85d6482d..12246255b77 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -366,10 +366,12 @@ Section: Transforming strings * * The result vector is not null-terminated. */ -pub pure fn to_bytes(s: &str) -> ~[u8] unsafe { - let mut v: ~[u8] = ::cast::transmute(from_slice(s)); - vec::raw::set_len(&mut v, len(s)); - v +pub pure fn to_bytes(s: &str) -> ~[u8] { + unsafe { + let mut v: ~[u8] = ::cast::transmute(from_slice(s)); + vec::raw::set_len(&mut v, len(s)); + v + } } /// Work with the string as a byte slice, not including trailing null. @@ -454,8 +456,10 @@ pure fn split_char_inner(s: &str, sep: char, count: uint, allow_empty: bool) let mut i = 0u, start = 0u; while i < l && done < count { if s[i] == b { - if allow_empty || start < i unsafe { - result.push(unsafe { raw::slice_bytes(s, start, i) }); + if allow_empty || start < i { + unsafe { + result.push(raw::slice_bytes(s, start, i)); + } } start = i + 1u; done += 1u; @@ -497,16 +501,20 @@ pure fn split_inner(s: &str, sepfn: fn(cc: char) -> bool, count: uint, while i < l && done < count { let CharRange {ch, next} = char_range_at(s, i); if sepfn(ch) { - if allow_empty || start < i unsafe { - result.push(unsafe { raw::slice_bytes(s, start, i)}); + if allow_empty || start < i { + unsafe { + result.push(raw::slice_bytes(s, start, i)); + } } start = next; done += 1u; } i = next; } - if allow_empty || start < l unsafe { - result.push(unsafe { raw::slice_bytes(s, start, l) }); + if allow_empty || start < l { + unsafe { + result.push(raw::slice_bytes(s, start, l)); + } } result } @@ -1490,17 +1498,20 @@ pub pure fn to_utf16(s: &str) -> ~[u16] { // Arithmetic with u32 literals is easier on the eyes than chars. let mut ch = cch as u32; - if (ch & 0xFFFF_u32) == ch unsafe { - // The BMP falls through (assuming non-surrogate, as it should) - assert ch <= 0xD7FF_u32 || ch >= 0xE000_u32; - u.push(ch as u16) - } else unsafe { - // Supplementary planes break into surrogates. - assert ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32; - ch -= 0x1_0000_u32; - let w1 = 0xD800_u16 | ((ch >> 10) as u16); - let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all(~[w1, w2]) + unsafe { + if (ch & 0xFFFF_u32) == ch { + // The BMP falls through (assuming non-surrogate, as it + // should) + assert ch <= 0xD7FF_u32 || ch >= 0xE000_u32; + u.push(ch as u16) + } else { + // Supplementary planes break into surrogates. + assert ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32; + ch -= 0x1_0000_u32; + let w1 = 0xD800_u16 | ((ch >> 10) as u16); + let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + u.push_all(~[w1, w2]) + } } } u diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 322aa895eb4..914eccd3d86 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -213,24 +213,26 @@ pub mod tests { } #[test] - pub fn synthesize_closure() unsafe { - let x = 10; - let f: fn(int) -> int = |y| x + y; + pub fn synthesize_closure() { + unsafe { + let x = 10; + let f: fn(int) -> int = |y| x + y; - assert f(20) == 30; + assert f(20) == 30; - let original_closure: Closure = cast::transmute(move f); + let original_closure: Closure = cast::transmute(move f); - let actual_function_pointer = original_closure.code; - let environment = original_closure.env; + let actual_function_pointer = original_closure.code; + let environment = original_closure.env; - let new_closure = Closure { - code: actual_function_pointer, - env: environment - }; + let new_closure = Closure { + code: actual_function_pointer, + env: environment + }; - let new_f: fn(int) -> int = cast::transmute(move new_closure); - assert new_f(20) == 30; + let new_f: fn(int) -> int = cast::transmute(move new_closure); + assert new_f(20) == 30; + } } } diff --git a/src/libcore/task/local_data.rs b/src/libcore/task/local_data.rs index 990d309a159..05a4e35b249 100644 --- a/src/libcore/task/local_data.rs +++ b/src/libcore/task/local_data.rs @@ -86,79 +86,97 @@ pub unsafe fn local_data_modify<T: Durable>( } #[test] -fn test_tls_multitask() unsafe { - fn my_key(_x: @~str) { } - local_data_set(my_key, @~"parent data"); - do task::spawn unsafe { - assert local_data_get(my_key).is_none(); // TLS shouldn't carry over. - local_data_set(my_key, @~"child data"); - assert *(local_data_get(my_key).get()) == ~"child data"; - // should be cleaned up for us +fn test_tls_multitask() { + unsafe { + fn my_key(_x: @~str) { } + local_data_set(my_key, @~"parent data"); + do task::spawn { + unsafe { + // TLS shouldn't carry over. + assert local_data_get(my_key).is_none(); + local_data_set(my_key, @~"child data"); + assert *(local_data_get(my_key).get()) == ~"child data"; + // should be cleaned up for us + } + } + // Must work multiple times + assert *(local_data_get(my_key).get()) == ~"parent data"; + assert *(local_data_get(my_key).get()) == ~"parent data"; + assert *(local_data_get(my_key).get()) == ~"parent data"; } - // Must work multiple times - assert *(local_data_get(my_key).get()) == ~"parent data"; - assert *(local_data_get(my_key).get()) == ~"parent data"; - assert *(local_data_get(my_key).get()) == ~"parent data"; } #[test] -fn test_tls_overwrite() unsafe { - fn my_key(_x: @~str) { } - local_data_set(my_key, @~"first data"); - local_data_set(my_key, @~"next data"); // Shouldn't leak. - assert *(local_data_get(my_key).get()) == ~"next data"; +fn test_tls_overwrite() { + unsafe { + fn my_key(_x: @~str) { } + local_data_set(my_key, @~"first data"); + local_data_set(my_key, @~"next data"); // Shouldn't leak. + assert *(local_data_get(my_key).get()) == ~"next data"; + } } #[test] -fn test_tls_pop() unsafe { - fn my_key(_x: @~str) { } - local_data_set(my_key, @~"weasel"); - assert *(local_data_pop(my_key).get()) == ~"weasel"; - // Pop must remove the data from the map. - assert local_data_pop(my_key).is_none(); +fn test_tls_pop() { + unsafe { + fn my_key(_x: @~str) { } + local_data_set(my_key, @~"weasel"); + assert *(local_data_pop(my_key).get()) == ~"weasel"; + // Pop must remove the data from the map. + assert local_data_pop(my_key).is_none(); + } } #[test] -fn test_tls_modify() unsafe { - fn my_key(_x: @~str) { } - local_data_modify(my_key, |data| { - match data { - Some(@ref val) => fail ~"unwelcome value: " + *val, - None => Some(@~"first data") - } - }); - local_data_modify(my_key, |data| { - match data { - Some(@~"first data") => Some(@~"next data"), - Some(@ref val) => fail ~"wrong value: " + *val, - None => fail ~"missing value" - } - }); - assert *(local_data_pop(my_key).get()) == ~"next data"; +fn test_tls_modify() { + unsafe { + fn my_key(_x: @~str) { } + local_data_modify(my_key, |data| { + match data { + Some(@ref val) => fail ~"unwelcome value: " + *val, + None => Some(@~"first data") + } + }); + local_data_modify(my_key, |data| { + match data { + Some(@~"first data") => Some(@~"next data"), + Some(@ref val) => fail ~"wrong value: " + *val, + None => fail ~"missing value" + } + }); + assert *(local_data_pop(my_key).get()) == ~"next data"; + } } #[test] -fn test_tls_crust_automorestack_memorial_bug() unsafe { - // This might result in a stack-canary clobber if the runtime fails to set - // sp_limit to 0 when calling the cleanup extern - it might automatically - // jump over to the rust stack, which causes next_c_sp to get recorded as - // Something within a rust stack segment. Then a subsequent upcall (esp. - // for logging, think vsnprintf) would run on a stack smaller than 1 MB. - fn my_key(_x: @~str) { } - do task::spawn { - unsafe { local_data_set(my_key, @~"hax"); } +fn test_tls_crust_automorestack_memorial_bug() { + unsafe { + // This might result in a stack-canary clobber if the runtime fails to + // set sp_limit to 0 when calling the cleanup extern - it might + // automatically jump over to the rust stack, which causes next_c_sp + // to get recorded as something within a rust stack segment. Then a + // subsequent upcall (esp. for logging, think vsnprintf) would run on + // a stack smaller than 1 MB. + fn my_key(_x: @~str) { } + do task::spawn { + unsafe { local_data_set(my_key, @~"hax"); } + } } } #[test] -fn test_tls_multiple_types() unsafe { - fn str_key(_x: @~str) { } - fn box_key(_x: @@()) { } - fn int_key(_x: @int) { } - do task::spawn unsafe { - local_data_set(str_key, @~"string data"); - local_data_set(box_key, @@()); - local_data_set(int_key, @42); +fn test_tls_multiple_types() { + unsafe { + fn str_key(_x: @~str) { } + fn box_key(_x: @@()) { } + fn int_key(_x: @int) { } + do task::spawn { + unsafe { + local_data_set(str_key, @~"string data"); + local_data_set(box_key, @@()); + local_data_set(int_key, @42); + } + } } } @@ -167,31 +185,38 @@ fn test_tls_overwrite_multiple_types() { fn str_key(_x: @~str) { } fn box_key(_x: @@()) { } fn int_key(_x: @int) { } - do task::spawn unsafe { - local_data_set(str_key, @~"string data"); - local_data_set(int_key, @42); - // This could cause a segfault if overwriting-destruction is done with - // the crazy polymorphic transmute rather than the provided finaliser. - local_data_set(int_key, @31337); + do task::spawn { + unsafe { + local_data_set(str_key, @~"string data"); + local_data_set(int_key, @42); + // This could cause a segfault if overwriting-destruction is done + // with the crazy polymorphic transmute rather than the provided + // finaliser. + local_data_set(int_key, @31337); + } } } #[test] #[should_fail] #[ignore(cfg(windows))] -fn test_tls_cleanup_on_failure() unsafe { - fn str_key(_x: @~str) { } - fn box_key(_x: @@()) { } - fn int_key(_x: @int) { } - local_data_set(str_key, @~"parent data"); - local_data_set(box_key, @@()); - do task::spawn unsafe { // spawn_linked - local_data_set(str_key, @~"string data"); +fn test_tls_cleanup_on_failure() { + unsafe { + fn str_key(_x: @~str) { } + fn box_key(_x: @@()) { } + fn int_key(_x: @int) { } + local_data_set(str_key, @~"parent data"); local_data_set(box_key, @@()); - local_data_set(int_key, @42); + do task::spawn { + unsafe { // spawn_linked + local_data_set(str_key, @~"string data"); + local_data_set(box_key, @@()); + local_data_set(int_key, @42); + fail; + } + } + // Not quite nondeterministic. + local_data_set(int_key, @31337); fail; } - // Not quite nondeterministic. - local_data_set(int_key, @31337); - fail; } diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index c08f0f9c997..e6aa5b35bb8 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -29,10 +29,12 @@ pub trait LocalData { } impl<T: Durable> @T: LocalData { } impl LocalData: Eq { - pure fn eq(&self, other: &@LocalData) -> bool unsafe { - let ptr_a: (uint, uint) = cast::reinterpret_cast(&(*self)); - let ptr_b: (uint, uint) = cast::reinterpret_cast(other); - return ptr_a == ptr_b; + pure fn eq(&self, other: &@LocalData) -> bool { + unsafe { + let ptr_a: (uint, uint) = cast::reinterpret_cast(&(*self)); + let ptr_b: (uint, uint) = cast::reinterpret_cast(other); + return ptr_a == ptr_b; + } } pure fn ne(&self, other: &@LocalData) -> bool { !(*self).eq(other) } } @@ -43,11 +45,14 @@ type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData); // Has to be a pointer at outermost layer; the foreign call returns void *. type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>; -extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe { - assert !map_ptr.is_null(); - // Get and keep the single reference that was created at the beginning. - let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr); - // All local_data will be destroyed along with the map. +extern fn cleanup_task_local_map(map_ptr: *libc::c_void) { + unsafe { + assert !map_ptr.is_null(); + // Get and keep the single reference that was created at the + // beginning. + let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr); + // All local_data will be destroyed along with the map. + } } // Gets the map from the runtime. Lazily initialises if not done so already. diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index 22e187d7768..3f2f2e99ee8 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -114,17 +114,21 @@ impl<A: ToStr Copy, B: ToStr Copy, C: ToStr Copy> (A, B, C): ToStr { impl<A: ToStr> ~[A]: ToStr { #[inline(always)] - pure fn to_str() -> ~str unsafe { - // Bleh -- not really unsafe - // push_str and push_char - let mut acc = ~"[", first = true; - for vec::each(self) |elt| unsafe { - if first { first = false; } - else { str::push_str(&mut acc, ~", "); } - str::push_str(&mut acc, elt.to_str()); + pure fn to_str() -> ~str { + unsafe { + // Bleh -- not really unsafe + // push_str and push_char + let mut acc = ~"[", first = true; + for vec::each(self) |elt| { + unsafe { + if first { first = false; } + else { str::push_str(&mut acc, ~", "); } + str::push_str(&mut acc, elt.to_str()); + } + } + str::push_char(&mut acc, ']'); + move acc } - str::push_char(&mut acc, ']'); - move acc } } diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index a7eb2f80725..841b8876333 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -13,6 +13,7 @@ #[forbid(deprecated_pattern)]; use T = self::inst::T; +use T_SIGNED = self::inst::T_SIGNED; use char; use cmp::{Eq, Ord}; @@ -69,13 +70,39 @@ pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T } pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T } #[inline(always)] +/** + * Iterate over the range [`start`,`start`+`step`..`stop`) + * + */ +pub pure fn range_step(start: T, stop: T, step: T_SIGNED, it: fn(T) -> bool) { + let mut i = start; + if step == 0 { + fail ~"range_step called with step == 0"; + } + if step >= 0 { + while i < stop { + if !it(i) { break } + i += step as T; + } + } + else { + while i > stop { + if !it(i) { break } + i -= -step as T; + } + } +} + +#[inline(always)] /// Iterate over the range [`lo`..`hi`) pub pure fn range(lo: T, hi: T, it: fn(T) -> bool) { - let mut i = lo; - while i < hi { - if !it(i) { break } - i += 1 as T; - } + range_step(lo, hi, 1 as T_SIGNED, it); +} + +#[inline(always)] +/// Iterate over the range [`hi`..`lo`) +pub pure fn range_rev(hi: T, lo: T, it: fn(T) -> bool) { + range_step(hi, lo, -1 as T_SIGNED, it); } /// Computes the bitwise complement @@ -330,3 +357,51 @@ pub fn test_times() { for ten.times { accum += 1; } assert (accum == 10); } +use io; +#[test] +pub fn test_ranges() { + let mut l = ~[]; + + for range(0,3) |i| { + l.push(i); + } + for range_rev(13,10) |i| { + l.push(i); + } + for range_step(20,26,2) |i| { + l.push(i); + } + for range_step(36,30,-2) |i| { + l.push(i); + } + + assert l == ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32]; + + // None of the `fail`s should execute. + for range(0,0) |_i| { + fail ~"unreachable"; + } + for range_rev(0,0) |_i| { + fail ~"unreachable"; + } + for range_step(10,0,1) |_i| { + fail ~"unreachable"; + } + for range_step(0,1,-10) |_i| { + fail ~"unreachable"; + } +} + +#[test] +#[should_fail] +fn test_range_step_zero_step_up() { + for range_step(0,10,0) |_i| {} +} +#[test] +#[should_fail] +fn test_range_step_zero_step_down() { + for range_step(0,-10,0) |_i| {} +} diff --git a/src/libcore/uint-template/u16.rs b/src/libcore/uint-template/u16.rs index c4c299a4b79..b9a007af2f6 100644 --- a/src/libcore/uint-template/u16.rs +++ b/src/libcore/uint-template/u16.rs @@ -12,5 +12,7 @@ mod inst { pub type T = u16; + #[allow(non_camel_case_types)] + pub type T_SIGNED = i16; pub const bits: uint = 16; } diff --git a/src/libcore/uint-template/u32.rs b/src/libcore/uint-template/u32.rs index 6979bb7b5cc..141509c49e5 100644 --- a/src/libcore/uint-template/u32.rs +++ b/src/libcore/uint-template/u32.rs @@ -12,5 +12,7 @@ mod inst { pub type T = u32; + #[allow(non_camel_case_types)] + pub type T_SIGNED = i32; pub const bits: uint = 32; } \ No newline at end of file diff --git a/src/libcore/uint-template/u64.rs b/src/libcore/uint-template/u64.rs index 14860148798..35210eae9a7 100644 --- a/src/libcore/uint-template/u64.rs +++ b/src/libcore/uint-template/u64.rs @@ -12,5 +12,7 @@ mod inst { pub type T = u64; + #[allow(non_camel_case_types)] + pub type T_SIGNED = i64; pub const bits: uint = 64; } \ No newline at end of file diff --git a/src/libcore/uint-template/u8.rs b/src/libcore/uint-template/u8.rs index 3c64eebf761..e273a203213 100644 --- a/src/libcore/uint-template/u8.rs +++ b/src/libcore/uint-template/u8.rs @@ -14,6 +14,8 @@ pub use self::inst::is_ascii; mod inst { pub type T = u8; + #[allow(non_camel_case_types)] + pub type T_SIGNED = i8; pub const bits: uint = 8; // Type-specific functions here. These must be reexported by the diff --git a/src/libcore/uint-template/uint.rs b/src/libcore/uint-template/uint.rs index 4d2da7180ef..f54290f8394 100644 --- a/src/libcore/uint-template/uint.rs +++ b/src/libcore/uint-template/uint.rs @@ -20,6 +20,8 @@ mod inst { use uint; pub type T = uint; + #[allow(non_camel_case_types)] + pub type T_SIGNED = int; #[cfg(target_arch = "x86")] #[cfg(target_arch = "arm")] diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 8b8a4f5a18a..ee30d7939b7 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -209,12 +209,12 @@ pub pure fn build_sized_opt<A>(size: Option<uint>, } /// Produces a mut vector from an immutable vector. -pub pure fn to_mut<T>(v: ~[T]) -> ~[mut T] { +pub pure fn cast_to_mut<T>(v: ~[T]) -> ~[mut T] { unsafe { ::cast::transmute(v) } } /// Produces an immutable vector from a mut vector. -pub pure fn from_mut<T>(v: ~[mut T]) -> ~[T] { +pub pure fn cast_from_mut<T>(v: ~[mut T]) -> ~[T] { unsafe { ::cast::transmute(v) } } @@ -450,51 +450,52 @@ pub pure fn partitioned<T: Copy>(v: &[T], f: fn(&T) -> bool) -> (~[T], ~[T]) { // Mutators /// Removes the first element from a vector and return it -pub fn shift<T>(v: &mut ~[T]) -> T unsafe { +pub fn shift<T>(v: &mut ~[T]) -> T { + unsafe { + assert v.is_not_empty(); - assert v.is_not_empty(); + if v.len() == 1 { return v.pop() } - if v.len() == 1 { return v.pop() } + if v.len() == 2 { + let last = v.pop(); + let first = v.pop(); + v.push(last); + return first; + } - if v.len() == 2 { - let last = v.pop(); - let first = v.pop(); - v.push(last); - return first; - } + let ln = v.len(); + let next_ln = v.len() - 1; - let ln = v.len(); - let next_ln = v.len() - 1; + // Save the last element. We're going to overwrite its position + let mut work_elt = v.pop(); + // We still should have room to work where what last element was + assert capacity(v) >= ln; + // Pretend like we have the original length so we can use + // the vector copy_memory to overwrite the hole we just made + raw::set_len(&mut *v, ln); - // Save the last element. We're going to overwrite its position - let mut work_elt = v.pop(); - // We still should have room to work where what last element was - assert capacity(v) >= ln; - // Pretend like we have the original length so we can use - // the vector copy_memory to overwrite the hole we just made - raw::set_len(&mut *v, ln); + // Memcopy the head element (the one we want) to the location we just + // popped. For the moment it unsafely exists at both the head and last + // positions + let first_slice = view(*v, 0, 1); + let last_slice = mut_view(*v, next_ln, ln); + raw::copy_memory(last_slice, first_slice, 1); - // Memcopy the head element (the one we want) to the location we just - // popped. For the moment it unsafely exists at both the head and last - // positions - let first_slice = view(*v, 0, 1); - let last_slice = mut_view(*v, next_ln, ln); - raw::copy_memory(last_slice, first_slice, 1); + // Memcopy everything to the left one element + let init_slice = mut_view(*v, 0, next_ln); + let tail_slice = view(*v, 1, ln); + raw::copy_memory(init_slice, tail_slice, next_ln); - // Memcopy everything to the left one element - let init_slice = mut_view(*v, 0, next_ln); - let tail_slice = view(*v, 1, ln); - raw::copy_memory(init_slice, tail_slice, next_ln); + // Set the new length. Now the vector is back to normal + raw::set_len(&mut *v, next_ln); - // Set the new length. Now the vector is back to normal - raw::set_len(&mut *v, next_ln); + // Swap out the element we want from the end + let vp = raw::to_mut_ptr(*v); + let vp = ptr::mut_offset(vp, next_ln - 1); + *vp <-> work_elt; - // Swap out the element we want from the end - let vp = raw::to_mut_ptr(*v); - let vp = ptr::mut_offset(vp, next_ln - 1); - *vp <-> work_elt; - - return work_elt; + return work_elt; + } } /// Prepend an element to the vector @@ -532,27 +533,29 @@ pub fn remove<T>(v: &mut ~[T], i: uint) -> T { v.pop() } -pub fn consume<T>(v: ~[T], f: fn(uint, v: T)) unsafe { - let mut v = v; // FIXME(#3488) - - do as_mut_buf(v) |p, ln| { - for uint::range(0, ln) |i| { - // NB: This unsafe operation counts on init writing 0s to the - // holes we create in the vector. That ensures that, if the - // iterator fails then we won't try to clean up the consumed - // elements during unwinding - let mut x = rusti::init(); - let p = ptr::mut_offset(p, i); - x <-> *p; - f(i, x); +pub fn consume<T>(v: ~[T], f: fn(uint, v: T)) { + unsafe { + let mut v = v; // FIXME(#3488) + + do as_mut_buf(v) |p, ln| { + for uint::range(0, ln) |i| { + // NB: This unsafe operation counts on init writing 0s to the + // holes we create in the vector. That ensures that, if the + // iterator fails then we won't try to clean up the consumed + // elements during unwinding + let mut x = rusti::init(); + let p = ptr::mut_offset(p, i); + x <-> *p; + f(i, x); + } } - } - raw::set_len(&mut v, 0); + raw::set_len(&mut v, 0); + } } pub fn consume_mut<T>(v: ~[mut T], f: fn(uint, v: T)) { - consume(vec::from_mut(v), f) + consume(vec::cast_from_mut(v), f) } /// Remove the last element from a vector and return it @@ -666,36 +669,39 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) { * Remove consecutive repeated elements from a vector; if the vector is * sorted, this removes all duplicates. */ -pub fn dedup<T: Eq>(v: &mut ~[T]) unsafe { - if v.len() < 1 { return; } - let mut last_written = 0, next_to_read = 1; - do as_const_buf(*v) |p, ln| { - // We have a mutable reference to v, so we can make arbitrary changes. - // (cf. push and pop) - let p = p as *mut T; - // last_written < next_to_read <= ln - while next_to_read < ln { - // last_written < next_to_read < ln - if *ptr::mut_offset(p, next_to_read) == - *ptr::mut_offset(p, last_written) { - // FIXME #4204 Should be rusti::uninit() - don't need to zero - let mut dropped = rusti::init(); - dropped <-> *ptr::mut_offset(p, next_to_read); - } else { - last_written += 1; - // last_written <= next_to_read < ln - if next_to_read != last_written { - *ptr::mut_offset(p, last_written) <-> - *ptr::mut_offset(p, next_to_read); +pub fn dedup<T: Eq>(v: &mut ~[T]) { + unsafe { + if v.len() < 1 { return; } + let mut last_written = 0, next_to_read = 1; + do as_const_buf(*v) |p, ln| { + // We have a mutable reference to v, so we can make arbitrary + // changes. (cf. push and pop) + let p = p as *mut T; + // last_written < next_to_read <= ln + while next_to_read < ln { + // last_written < next_to_read < ln + if *ptr::mut_offset(p, next_to_read) == + *ptr::mut_offset(p, last_written) { + // FIXME #4204 Should be rusti::uninit() - don't need to + // zero + let mut dropped = rusti::init(); + dropped <-> *ptr::mut_offset(p, next_to_read); + } else { + last_written += 1; + // last_written <= next_to_read < ln + if next_to_read != last_written { + *ptr::mut_offset(p, last_written) <-> + *ptr::mut_offset(p, next_to_read); + } } + // last_written <= next_to_read < ln + next_to_read += 1; + // last_written < next_to_read <= ln } - // last_written <= next_to_read < ln - next_to_read += 1; - // last_written < next_to_read <= ln } + // last_written < next_to_read == ln + raw::set_len(v, last_written + 1); } - // last_written < next_to_read == ln - raw::set_len(v, last_written + 1); } @@ -718,7 +724,7 @@ pub pure fn append_one<T>(lhs: ~[T], x: T) -> ~[T] { #[inline(always)] pub pure fn append_mut<T: Copy>(lhs: ~[mut T], rhs: &[const T]) -> ~[mut T] { - to_mut(append(from_mut(lhs), rhs)) + cast_to_mut(append(cast_from_mut(lhs), rhs)) } /** @@ -1215,7 +1221,9 @@ pub pure fn zip_slice<T: Copy, U: Copy>(v: &[const T], u: &[const U]) let sz = len(v); let mut i = 0u; assert sz == len(u); - while i < sz unsafe { zipped.push((v[i], u[i])); i += 1u; } + while i < sz { + unsafe { zipped.push((v[i], u[i])); i += 1u; } + } zipped } @@ -1454,8 +1462,10 @@ pub pure fn windowed<TT: Copy>(nn: uint, xx: &[TT]) -> ~[~[TT]] { assert 1u <= nn; for vec::eachi (xx) |ii, _x| { let len = vec::len(xx); - if ii+nn <= len unsafe { - ww.push(vec::slice(xx, ii, ii+nn)); + if ii+nn <= len { + unsafe { + ww.push(vec::slice(xx, ii, ii+nn)); + } } } ww @@ -3271,22 +3281,22 @@ mod tests { } #[test] - fn to_mut_no_copy() { + fn cast_to_mut_no_copy() { unsafe { let x = ~[1, 2, 3]; let addr = raw::to_ptr(x); - let x_mut = to_mut(x); + let x_mut = cast_to_mut(x); let addr_mut = raw::to_ptr(x_mut); assert addr == addr_mut; } } #[test] - fn from_mut_no_copy() { + fn cast_from_mut_no_copy() { unsafe { let x = ~[mut 1, 2, 3]; let addr = raw::to_ptr(x); - let x_imm = from_mut(x); + let x_imm = cast_from_mut(x); let addr_imm = raw::to_ptr(x_imm); assert addr == addr_imm; } @@ -3909,10 +3919,12 @@ mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_copy_memory_oob() unsafe { - let a = [mut 1, 2, 3, 4]; - let b = [1, 2, 3, 4, 5]; - raw::copy_memory(a, b, 5); + fn test_copy_memory_oob() { + unsafe { + let a = [mut 1, 2, 3, 4]; + let b = [1, 2, 3, 4, 5]; + raw::copy_memory(a, b, 5); + } } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 723a97795f8..03639b289e7 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -59,12 +59,14 @@ impl output_type : cmp::Eq { pure fn ne(&self, other: &output_type) -> bool { !(*self).eq(other) } } -pub fn llvm_err(sess: Session, +msg: ~str) -> ! unsafe { - let cstr = llvm::LLVMRustGetLastError(); - if cstr == ptr::null() { - sess.fatal(msg); - } else { - sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); +pub fn llvm_err(sess: Session, +msg: ~str) -> ! { + unsafe { + let cstr = llvm::LLVMRustGetLastError(); + if cstr == ptr::null() { + sess.fatal(msg); + } else { + sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); + } } } @@ -121,50 +123,52 @@ pub mod jit { pm: PassManagerRef, m: ModuleRef, opt: c_int, - stacks: bool) unsafe { - let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr()); - - // We need to tell JIT where to resolve all linked - // symbols from. The equivalent of -lstd, -lcore, etc. - // By default the JIT will resolve symbols from the std and - // core linked into rustc. We don't want that, - // incase the user wants to use an older std library. - - let cstore = sess.cstore; - for cstore::get_used_crate_files(cstore).each |cratepath| { - let path = cratepath.to_str(); - - debug!("linking: %s", path); - - let _: () = str::as_c_str( - path, - |buf_t| { - if !llvm::LLVMRustLoadCrate(manager, buf_t) { - llvm_err(sess, ~"Could not link"); - } - debug!("linked: %s", path); - }); - } + stacks: bool) { + unsafe { + let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr()); + + // We need to tell JIT where to resolve all linked + // symbols from. The equivalent of -lstd, -lcore, etc. + // By default the JIT will resolve symbols from the std and + // core linked into rustc. We don't want that, + // incase the user wants to use an older std library. + + let cstore = sess.cstore; + for cstore::get_used_crate_files(cstore).each |cratepath| { + let path = cratepath.to_str(); + + debug!("linking: %s", path); + + let _: () = str::as_c_str( + path, + |buf_t| { + if !llvm::LLVMRustLoadCrate(manager, buf_t) { + llvm_err(sess, ~"Could not link"); + } + debug!("linked: %s", path); + }); + } - // The execute function will return a void pointer - // to the _rust_main function. We can do closure - // magic here to turn it straight into a callable rust - // closure. It will also cleanup the memory manager - // for us. + // The execute function will return a void pointer + // to the _rust_main function. We can do closure + // magic here to turn it straight into a callable rust + // closure. It will also cleanup the memory manager + // for us. - let entry = llvm::LLVMRustExecuteJIT(manager, - pm, m, opt, stacks); + let entry = llvm::LLVMRustExecuteJIT(manager, + pm, m, opt, stacks); - if ptr::is_null(entry) { - llvm_err(sess, ~"Could not JIT"); - } else { - let closure = Closure { - code: entry, - env: ptr::null() - }; - let func: fn(++argv: ~[~str]) = cast::transmute(move closure); + if ptr::is_null(entry) { + llvm_err(sess, ~"Could not JIT"); + } else { + let closure = Closure { + code: entry, + env: ptr::null() + }; + let func: fn(++argv: ~[~str]) = cast::transmute(move closure); - func(~[/*bad*/copy sess.opts.binary]); + func(~[/*bad*/copy sess.opts.binary]); + } } } } @@ -576,8 +580,10 @@ fn build_link_meta(sess: Session, c: &ast::crate, output: &Path, return {name: name, vers: vers, extras_hash: extras_hash}; } -fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str unsafe { - symbol_hasher.result_str() +fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str { + unsafe { + symbol_hasher.result_str() + } } diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 20c962d36ff..d647e8f9a26 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1386,7 +1386,7 @@ fn float_width(llt: TypeRef) -> uint { } } -fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] unsafe { +fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] { unsafe { let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint, 0 as TypeRef); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 46f41b07107..8c9998ee25a 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -201,51 +201,53 @@ fn metadata_matches(extern_metas: ~[@ast::meta_item], } fn get_metadata_section(os: os, - filename: &Path) -> Option<@~[u8]> unsafe { - let mb = str::as_c_str(filename.to_str(), |buf| { - llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf) - }); - if mb as int == 0 { return option::None::<@~[u8]>; } - let of = match mk_object_file(mb) { - option::Some(of) => of, - _ => return option::None::<@~[u8]> - }; - let si = mk_section_iter(of.llof); - while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { - let name_buf = llvm::LLVMGetSectionName(si.llsi); - let name = unsafe { str::raw::from_c_str(name_buf) }; - if name == meta_section_name(os) { - let cbuf = llvm::LLVMGetSectionContents(si.llsi); - let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; - let mut found = None; - unsafe { - let cvbuf: *u8 = cast::reinterpret_cast(&cbuf); - let vlen = vec::len(encoder::metadata_encoding_version); - debug!("checking %u bytes of metadata-version stamp", - vlen); - let minsz = uint::min(vlen, csz); - let mut version_ok = false; - do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| { - version_ok = (buf0 == - encoder::metadata_encoding_version); - } - if !version_ok { return None; } + filename: &Path) -> Option<@~[u8]> { + unsafe { + let mb = str::as_c_str(filename.to_str(), |buf| { + llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf) + }); + if mb as int == 0 { return option::None::<@~[u8]>; } + let of = match mk_object_file(mb) { + option::Some(of) => of, + _ => return option::None::<@~[u8]> + }; + let si = mk_section_iter(of.llof); + while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { + let name_buf = llvm::LLVMGetSectionName(si.llsi); + let name = unsafe { str::raw::from_c_str(name_buf) }; + if name == meta_section_name(os) { + let cbuf = llvm::LLVMGetSectionContents(si.llsi); + let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; + let mut found = None; + unsafe { + let cvbuf: *u8 = cast::reinterpret_cast(&cbuf); + let vlen = vec::len(encoder::metadata_encoding_version); + debug!("checking %u bytes of metadata-version stamp", + vlen); + let minsz = uint::min(vlen, csz); + let mut version_ok = false; + do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| { + version_ok = (buf0 == + encoder::metadata_encoding_version); + } + if !version_ok { return None; } - let cvbuf1 = ptr::offset(cvbuf, vlen); - debug!("inflating %u bytes of compressed metadata", - csz - vlen); - do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| { - let inflated = flate::inflate_bytes(bytes); - found = move Some(@(move inflated)); - } - if found != None { - return found; + let cvbuf1 = ptr::offset(cvbuf, vlen); + debug!("inflating %u bytes of compressed metadata", + csz - vlen); + do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| { + let inflated = flate::inflate_bytes(bytes); + found = move Some(@(move inflated)); + } + if found != None { + return found; + } } } + llvm::LLVMMoveToNextSection(si.llsi); } - llvm::LLVMMoveToNextSection(si.llsi); + return option::None::<@~[u8]>; } - return option::None::<@~[u8]>; } fn meta_section_name(os: os) -> ~str { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 530e63acf57..3b9b0348615 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -295,7 +295,9 @@ fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_int(a + b)), subtract => Ok(const_int(a - b)), mul => Ok(const_int(a * b)), + div if b == 0 => Err(~"divide by zero"), div => Ok(const_int(a / b)), + rem if b == 0 => Err(~"modulo zero"), rem => Ok(const_int(a % b)), and | bitand => Ok(const_int(a & b)), or | bitor => Ok(const_int(a | b)), @@ -315,7 +317,9 @@ fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_uint(a + b)), subtract => Ok(const_uint(a - b)), mul => Ok(const_uint(a * b)), + div if b == 0 => Err(~"divide by zero"), div => Ok(const_uint(a / b)), + rem if b == 0 => Err(~"modulo zero"), rem => Ok(const_uint(a % b)), and | bitand => Ok(const_uint(a & b)), or | bitor => Ok(const_uint(a | b)), diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index dec09a3235c..eb07e286f62 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -661,11 +661,11 @@ fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { tcx: ir.tcx, s: specials, successors: - vec::to_mut( + vec::cast_to_mut( vec::from_elem(ir.num_live_nodes, invalid_node())), users: - vec::to_mut( + vec::cast_to_mut( vec::from_elem(ir.num_live_nodes * ir.num_vars, invalid_users())), loop_scope: DVec(), diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 63ccefbce0e..db266464860 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -985,7 +985,7 @@ fn pick_col(m: &[@Match]) -> uint { _ => 0u } } - let scores = vec::to_mut(vec::from_elem(m[0].pats.len(), 0u)); + let scores = vec::cast_to_mut(vec::from_elem(m[0].pats.len(), 0u)); for vec::each(m) |br| { let mut i = 0u; for vec::each(br.pats) |p| { scores[i] += score(*p); i += 1u; } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index cf3d7c362b7..5b7453ebf4c 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2255,14 +2255,16 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) { val_ty(crate_map)], ccx.int_type); let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty); - let args = if ccx.sess.building_library unsafe { - ~[rust_main, - llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), - llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), - crate_map] - } else unsafe { - ~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map] + let args = unsafe { + if ccx.sess.building_library { + ~[rust_main, + llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), + llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), + crate_map] + } else { + ~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map] + } }; let result = unsafe { diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index c913643ac99..060bef1a44c 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -176,9 +176,11 @@ fn IndirectBr(cx: block, Addr: ValueRef, NumDests: uint) { // This is a really awful way to get a zero-length c-string, but better (and a // lot more efficient) than doing str::as_c_str("", ...) every time. -fn noname() -> *libc::c_char unsafe { - const cnull: uint = 0u; - return cast::reinterpret_cast(&ptr::addr_of(&cnull)); +fn noname() -> *libc::c_char { + unsafe { + const cnull: uint = 0u; + return cast::reinterpret_cast(&ptr::addr_of(&cnull)); + } } fn Invoke(cx: block, Fn: ValueRef, Args: ~[ValueRef], diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs new file mode 100644 index 00000000000..07c12d08e1b --- /dev/null +++ b/src/librustc/middle/trans/cabi.rs @@ -0,0 +1,214 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use lib::llvm::{llvm, TypeRef, ValueRef, Attribute}; +use middle::trans::base::*; +use middle::trans::build::*; +use middle::trans::common::*; + +export ABIInfo, LLVMType, FnType; +export llvm_abi_info; + +trait ABIInfo { + fn compute_info(&self, + atys: &[TypeRef], + rty: TypeRef, + ret_def: bool) -> FnType; +} + +struct LLVMType { + cast: bool, + ty: TypeRef +} + +struct FnType { + arg_tys: ~[LLVMType], + ret_ty: LLVMType, + attrs: ~[Option<Attribute>], + sret: bool +} + +impl FnType { + fn decl_fn(&self, decl: fn(fnty: TypeRef) -> ValueRef) -> ValueRef { + let atys = vec::map(self.arg_tys, |t| t.ty); + let rty = self.ret_ty.ty; + let fnty = T_fn(atys, rty); + let llfn = decl(fnty); + + for vec::eachi(self.attrs) |i, a| { + match *a { + option::Some(attr) => { + unsafe { + let llarg = get_param(llfn, i); + llvm::LLVMAddAttribute(llarg, attr as c_uint); + } + } + _ => () + } + } + return llfn; + } + + fn build_shim_args(&self, bcx: block, + arg_tys: &[TypeRef], + llargbundle: ValueRef) -> ~[ValueRef] { + let mut atys = /*bad*/copy self.arg_tys; + let mut attrs = /*bad*/copy self.attrs; + + let mut llargvals = ~[]; + let mut i = 0u; + let n = vec::len(arg_tys); + + if self.sret { + let llretptr = GEPi(bcx, llargbundle, [0u, n]); + let llretloc = Load(bcx, llretptr); + llargvals = ~[llretloc]; + atys = vec::tail(atys); + attrs = vec::tail(attrs); + } + + while i < n { + let llargval = if atys[i].cast { + let arg_ptr = GEPi(bcx, llargbundle, [0u, i]); + let arg_ptr = BitCast(bcx, arg_ptr, T_ptr(atys[i].ty)); + Load(bcx, arg_ptr) + } else if attrs[i].is_some() { + GEPi(bcx, llargbundle, [0u, i]) + } else { + load_inbounds(bcx, llargbundle, [0u, i]) + }; + llargvals.push(llargval); + i += 1u; + } + + return llargvals; + } + + fn build_shim_ret(&self, bcx: block, + arg_tys: &[TypeRef], ret_def: bool, + llargbundle: ValueRef, llretval: ValueRef) { + for vec::eachi(self.attrs) |i, a| { + match *a { + Some(attr) => { + unsafe { + llvm::LLVMAddInstrAttribute( + llretval, (i + 1u) as c_uint, + attr as c_uint); + } + } + _ => () + } + } + if self.sret || !ret_def { + return; + } + let n = vec::len(arg_tys); + // R** llretptr = &args->r; + let llretptr = GEPi(bcx, llargbundle, [0u, n]); + // R* llretloc = *llretptr; /* (args->r) */ + let llretloc = Load(bcx, llretptr); + if self.ret_ty.cast { + let tmp_ptr = BitCast(bcx, llretloc, T_ptr(self.ret_ty.ty)); + // *args->r = r; + Store(bcx, llretval, tmp_ptr); + } else { + // *args->r = r; + Store(bcx, llretval, llretloc); + }; + } + + fn build_wrap_args(&self, bcx: block, ret_ty: TypeRef, + llwrapfn: ValueRef, llargbundle: ValueRef) { + let mut atys = /*bad*/copy self.arg_tys; + let mut attrs = /*bad*/copy self.attrs; + let mut j = 0u; + let llretptr = if self.sret { + atys = vec::tail(atys); + attrs = vec::tail(attrs); + j = 1u; + get_param(llwrapfn, 0u) + } else if self.ret_ty.cast { + let retptr = alloca(bcx, self.ret_ty.ty); + BitCast(bcx, retptr, T_ptr(ret_ty)) + } else { + alloca(bcx, ret_ty) + }; + + let mut i = 0u; + let n = vec::len(atys); + while i < n { + let mut argval = get_param(llwrapfn, i + j); + if attrs[i].is_some() { + argval = Load(bcx, argval); + store_inbounds(bcx, argval, llargbundle, [0u, i]); + } else if atys[i].cast { + let argptr = GEPi(bcx, llargbundle, [0u, i]); + let argptr = BitCast(bcx, argptr, T_ptr(atys[i].ty)); + Store(bcx, argval, argptr); + } else { + store_inbounds(bcx, argval, llargbundle, [0u, i]); + } + i += 1u; + } + store_inbounds(bcx, llretptr, llargbundle, [0u, n]); + } + + fn build_wrap_ret(&self, bcx: block, + arg_tys: &[TypeRef], ret_def: bool, + llargbundle: ValueRef) { + if self.sret || !ret_def { + RetVoid(bcx); + return; + } + let n = vec::len(arg_tys); + let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]); + let llretval = if self.ret_ty.cast { + let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty)); + Load(bcx, retptr) + } else { + Load(bcx, llretval) + }; + Ret(bcx, llretval); + } +} + +enum LLVM_ABIInfo { LLVM_ABIInfo } + +impl LLVM_ABIInfo: ABIInfo { + fn compute_info(&self, + atys: &[TypeRef], + rty: TypeRef, + _ret_def: bool) -> FnType { + let arg_tys = do atys.map |a| { + LLVMType { cast: false, ty: *a } + }; + let ret_ty = LLVMType { + cast: false, + ty: rty + }; + let attrs = do atys.map |_| { + option::None + }; + let sret = false; + + return FnType { + arg_tys: arg_tys, + ret_ty: ret_ty, + attrs: attrs, + sret: sret + }; + } +} + +fn llvm_abi_info() -> ABIInfo { + return LLVM_ABIInfo as ABIInfo; +} + + diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs new file mode 100644 index 00000000000..7125764e747 --- /dev/null +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -0,0 +1,417 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The classification code for the x86_64 ABI is taken from the clay language +// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp + +use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double}; +use lib::llvm::{Struct, Array, Attribute}; +use lib::llvm::{StructRetAttribute, ByValAttribute}; +use middle::trans::common::*; +use middle::trans::cabi::*; + +export x86_64_abi_info; + +enum x86_64_reg_class { + no_class, + integer_class, + sse_fs_class, + sse_fv_class, + sse_ds_class, + sse_dv_class, + sse_int_class, + sseup_class, + x87_class, + x87up_class, + complex_x87_class, + memory_class +} + +impl x86_64_reg_class : cmp::Eq { + pure fn eq(&self, other: &x86_64_reg_class) -> bool { + ((*self) as uint) == ((*other) as uint) + } + pure fn ne(&self, other: &x86_64_reg_class) -> bool { !(*self).eq(other) } +} + +fn is_sse(++c: x86_64_reg_class) -> bool { + return match c { + sse_fs_class | sse_fv_class | + sse_ds_class | sse_dv_class => true, + _ => false + }; +} + +fn is_ymm(cls: &[x86_64_reg_class]) -> bool { + let len = vec::len(cls); + return (len > 2u && + is_sse(cls[0]) && + cls[1] == sseup_class && + cls[2] == sseup_class) || + (len > 3u && + is_sse(cls[1]) && + cls[2] == sseup_class && + cls[3] == sseup_class); +} + +fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { + fn align(off: uint, ty: TypeRef) -> uint { + let a = ty_align(ty); + return (off + a - 1u) / a * a; + } + + fn struct_tys(ty: TypeRef) -> ~[TypeRef] { + unsafe { + let n = llvm::LLVMCountStructElementTypes(ty); + if (n == 0) { + return ~[]; + } + let mut elts = vec::from_elem(n as uint, ptr::null()); + llvm::LLVMGetStructElementTypes(ty, + ptr::to_mut_unsafe_ptr(&mut elts[0])); + return elts; + } + } + + fn ty_align(ty: TypeRef) -> uint { + unsafe { + return match llvm::LLVMGetTypeKind(ty) { + Integer => { + ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8 + } + Pointer => 8, + Float => 4, + Double => 8, + Struct => { + do vec::foldl(1, struct_tys(ty)) |a, t| { + uint::max(a, ty_align(*t)) + } + } + Array => { + let elt = llvm::LLVMGetElementType(ty); + ty_align(elt) + } + _ => fail ~"ty_size: unhandled type" + }; + } + } + + fn ty_size(ty: TypeRef) -> uint { + unsafe { + return match llvm::LLVMGetTypeKind(ty) { + Integer => { + ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8 + } + Pointer => 8, + Float => 4, + Double => 8, + Struct => { + let size = do vec::foldl(0, struct_tys(ty)) |s, t| { + align(s, *t) + ty_size(*t) + }; + align(size, ty) + } + Array => { + let len = llvm::LLVMGetArrayLength(ty) as uint; + let elt = llvm::LLVMGetElementType(ty); + let eltsz = ty_size(elt); + len * eltsz + } + _ => fail ~"ty_size: unhandled type" + }; + } + } + + fn all_mem(cls: &[mut x86_64_reg_class]) { + for uint::range(0, cls.len()) |i| { + cls[i] = memory_class; + } + } + + fn unify(cls: &[mut x86_64_reg_class], + i: uint, + newv: x86_64_reg_class) { + if cls[i] == newv { + return; + } else if cls[i] == no_class { + cls[i] = newv; + } else if newv == no_class { + return; + } else if cls[i] == memory_class || newv == memory_class { + cls[i] = memory_class; + } else if cls[i] == integer_class || newv == integer_class { + cls[i] = integer_class; + } else if cls[i] == x87_class || + cls[i] == x87up_class || + cls[i] == complex_x87_class || + newv == x87_class || + newv == x87up_class || + newv == complex_x87_class { + cls[i] = memory_class; + } else { + cls[i] = newv; + } + } + + fn classify_struct(tys: &[TypeRef], + cls: &[mut x86_64_reg_class], i: uint, + off: uint) { + let mut field_off = off; + for vec::each(tys) |ty| { + field_off = align(field_off, *ty); + classify(*ty, cls, i, field_off); + field_off += ty_size(*ty); + } + } + + fn classify(ty: TypeRef, + cls: &[mut x86_64_reg_class], ix: uint, + off: uint) { + unsafe { + let t_align = ty_align(ty); + let t_size = ty_size(ty); + + let misalign = off % t_align; + if misalign != 0u { + let mut i = off / 8u; + let e = (off + t_size + 7u) / 8u; + while i < e { + unify(cls, ix + i, memory_class); + i += 1u; + } + return; + } + + match llvm::LLVMGetTypeKind(ty) as int { + 8 /* integer */ | + 12 /* pointer */ => { + unify(cls, ix + off / 8u, integer_class); + } + 2 /* float */ => { + if off % 8u == 4u { + unify(cls, ix + off / 8u, sse_fv_class); + } else { + unify(cls, ix + off / 8u, sse_fs_class); + } + } + 3 /* double */ => { + unify(cls, ix + off / 8u, sse_ds_class); + } + 10 /* struct */ => { + classify_struct(struct_tys(ty), cls, ix, off); + } + 11 /* array */ => { + let elt = llvm::LLVMGetElementType(ty); + let eltsz = ty_size(elt); + let len = llvm::LLVMGetArrayLength(ty) as uint; + let mut i = 0u; + while i < len { + classify(elt, cls, ix, off + i * eltsz); + i += 1u; + } + } + _ => fail ~"classify: unhandled type" + } + } + } + + fn fixup(ty: TypeRef, cls: &[mut x86_64_reg_class]) { + unsafe { + let mut i = 0u; + let llty = llvm::LLVMGetTypeKind(ty) as int; + let e = vec::len(cls); + if vec::len(cls) > 2u && + (llty == 10 /* struct */ || + llty == 11 /* array */) { + if is_sse(cls[i]) { + i += 1u; + while i < e { + if cls[i] != sseup_class { + all_mem(cls); + return; + } + i += 1u; + } + } else { + all_mem(cls); + return + } + } else { + while i < e { + if cls[i] == memory_class { + all_mem(cls); + return; + } + if cls[i] == x87up_class { + // for darwin + // cls[i] = sse_ds_class; + all_mem(cls); + return; + } + if cls[i] == sseup_class { + cls[i] = sse_int_class; + } else if is_sse(cls[i]) { + i += 1; + while cls[i] == sseup_class { i += 1u; } + } else if cls[i] == x87_class { + i += 1; + while cls[i] == x87up_class { i += 1u; } + } else { + i += 1; + } + } + } + } + } + + let words = (ty_size(ty) + 7) / 8; + let cls = vec::cast_to_mut(vec::from_elem(words, no_class)); + if words > 4 { + all_mem(cls); + return vec::cast_from_mut(move cls); + } + classify(ty, cls, 0, 0); + fixup(ty, cls); + return vec::cast_from_mut(move cls); +} + +fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef { + fn llvec_len(cls: &[x86_64_reg_class]) -> uint { + let mut len = 1u; + for vec::each(cls) |c| { + if *c != sseup_class { + break; + } + len += 1u; + } + return len; + } + + unsafe { + let mut tys = ~[]; + let mut i = 0u; + let e = vec::len(cls); + while i < e { + match cls[i] { + integer_class => { + tys.push(T_i64()); + } + sse_fv_class => { + let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u; + let vec_ty = llvm::LLVMVectorType(T_f32(), + vec_len as c_uint); + tys.push(vec_ty); + i += vec_len; + loop; + } + sse_fs_class => { + tys.push(T_f32()); + } + sse_ds_class => { + tys.push(T_f64()); + } + _ => fail ~"llregtype: unhandled class" + } + i += 1u; + } + return T_struct(tys); + } +} + +fn x86_64_tys(atys: &[TypeRef], + rty: TypeRef, + ret_def: bool) -> FnType { + fn is_reg_ty(ty: TypeRef) -> bool { + unsafe { + return match llvm::LLVMGetTypeKind(ty) as int { + 8 /* integer */ | + 12 /* pointer */ | + 2 /* float */ | + 3 /* double */ => true, + _ => false + }; + } + } + + fn is_pass_byval(cls: &[x86_64_reg_class]) -> bool { + return cls.len() > 0 && + (cls[0] == memory_class || + cls[0] == x87_class || + cls[0] == complex_x87_class); + } + + fn is_ret_bysret(cls: &[x86_64_reg_class]) -> bool { + return cls.len() > 0 && cls[0] == memory_class; + } + + fn x86_64_ty(ty: TypeRef, + is_mem_cls: fn(cls: &[x86_64_reg_class]) -> bool, + attr: Attribute) -> (LLVMType, Option<Attribute>) { + let mut cast = false; + let mut ty_attr = option::None; + let mut llty = ty; + if !is_reg_ty(ty) { + let cls = classify_ty(ty); + if is_mem_cls(cls) { + llty = T_ptr(ty); + ty_attr = option::Some(attr); + } else { + cast = true; + llty = llreg_ty(cls); + } + } + return (LLVMType { cast: cast, ty: llty }, ty_attr); + } + + let mut arg_tys = ~[]; + let mut attrs = ~[]; + for vec::each(atys) |t| { + let (ty, attr) = x86_64_ty(*t, is_pass_byval, ByValAttribute); + arg_tys.push(ty); + attrs.push(attr); + } + let mut (ret_ty, ret_attr) = x86_64_ty(rty, is_ret_bysret, + StructRetAttribute); + let sret = ret_attr.is_some(); + if sret { + arg_tys = vec::append(~[ret_ty], arg_tys); + ret_ty = LLVMType { + cast: false, + ty: T_void() + }; + attrs = vec::append(~[ret_attr], attrs); + } else if !ret_def { + ret_ty = LLVMType { + cast: false, + ty: T_void() + }; + } + return FnType { + arg_tys: arg_tys, + ret_ty: ret_ty, + attrs: attrs, + sret: sret + }; +} + +enum X86_64_ABIInfo { X86_64_ABIInfo } + +impl X86_64_ABIInfo: ABIInfo { + fn compute_info(&self, + atys: &[TypeRef], + rty: TypeRef, + ret_def: bool) -> FnType { + return x86_64_tys(atys, rty, ret_def); + } +} + +fn x86_64_abi_info() -> ABIInfo { + return X86_64_ABIInfo as ABIInfo; +} diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index e5f2f25e67c..468baa1d8a7 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -660,7 +660,7 @@ fn val_str(tn: type_names, v: ValueRef) -> @str { } // Returns the nth element of the given LLVM structure type. -fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe { +fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef { unsafe { let elt_count = llvm::LLVMCountStructElementTypes(llstructty) as uint; assert (n < elt_count); @@ -832,10 +832,12 @@ fn T_size_t(targ_cfg: @session::config) -> TypeRef { return T_int(targ_cfg); } -fn T_fn(inputs: ~[TypeRef], output: TypeRef) -> TypeRef unsafe { - return llvm::LLVMFunctionType(output, to_ptr(inputs), - inputs.len() as c_uint, - False); +fn T_fn(inputs: ~[TypeRef], output: TypeRef) -> TypeRef { + unsafe { + return llvm::LLVMFunctionType(output, to_ptr(inputs), + inputs.len() as c_uint, + False); + } } fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef { @@ -854,7 +856,7 @@ fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef { } } -fn T_struct(elts: ~[TypeRef]) -> TypeRef unsafe { +fn T_struct(elts: ~[TypeRef]) -> TypeRef { unsafe { return llvm::LLVMStructType(to_ptr(elts), elts.len() as c_uint, @@ -869,7 +871,7 @@ fn T_named_struct(name: ~str) -> TypeRef { } } -fn set_struct_body(t: TypeRef, elts: ~[TypeRef]) unsafe { +fn set_struct_body(t: TypeRef, elts: ~[TypeRef]) { unsafe { llvm::LLVMStructSetBody(t, to_ptr(elts), @@ -908,7 +910,7 @@ fn T_task(targ_cfg: @session::config) -> TypeRef { return t; } -fn T_tydesc_field(cx: @crate_ctxt, field: uint) -> TypeRef unsafe { +fn T_tydesc_field(cx: @crate_ctxt, field: uint) -> TypeRef { // Bit of a kludge: pick the fn typeref out of the tydesc.. unsafe { @@ -1188,7 +1190,7 @@ fn C_postr(s: ~str) -> ValueRef { } } -fn C_zero_byte_arr(size: uint) -> ValueRef unsafe { +fn C_zero_byte_arr(size: uint) -> ValueRef { unsafe { let mut i = 0u; let mut elts: ~[ValueRef] = ~[]; @@ -1207,6 +1209,14 @@ fn C_struct(elts: &[ValueRef]) -> ValueRef { } } +fn C_packed_struct(elts: &[ValueRef]) -> ValueRef { + unsafe { + do vec::as_imm_buf(elts) |ptr, len| { + llvm::LLVMConstStruct(ptr, len as c_uint, True) + } + } +} + fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef { unsafe { do vec::as_imm_buf(elts) |ptr, len| { @@ -1215,14 +1225,14 @@ fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef { } } -fn C_array(ty: TypeRef, elts: ~[ValueRef]) -> ValueRef unsafe { +fn C_array(ty: TypeRef, elts: ~[ValueRef]) -> ValueRef { unsafe { return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts), elts.len() as c_uint); } } -fn C_bytes(bytes: ~[u8]) -> ValueRef unsafe { +fn C_bytes(bytes: ~[u8]) -> ValueRef { unsafe { return llvm::LLVMConstString( cast::reinterpret_cast(&vec::raw::to_ptr(bytes)), @@ -1230,7 +1240,7 @@ fn C_bytes(bytes: ~[u8]) -> ValueRef unsafe { } } -fn C_bytes_plus_null(bytes: ~[u8]) -> ValueRef unsafe { +fn C_bytes_plus_null(bytes: ~[u8]) -> ValueRef { unsafe { return llvm::LLVMConstString( cast::reinterpret_cast(&vec::raw::to_ptr(bytes)), diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 11d18706b90..01533e16283 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -455,15 +455,14 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { let discrim = base::get_discrim_val(cx, e.span, tid, vid); let c_args = C_struct(args.map(|a| const_expr(cx, *a))); - let fields = if !degen { - ~[discrim, c_args] + // FIXME (#1645): enum body alignment is generaly wrong. + if !degen { + C_packed_struct(~[discrim, c_args]) } else if size == 0 { - ~[discrim] + C_struct(~[discrim]) } else { - ~[c_args] - }; - - C_struct(fields) + C_struct(~[c_args]) + } } _ => cx.sess.span_bug(e.span, ~"expected a struct def") } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 668c676b18c..6b368555637 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -86,7 +86,7 @@ fn lli64(val: int) -> ValueRef { fn lli1(bval: bool) -> ValueRef { C_bool(bval) } -fn llmdnode(elems: ~[ValueRef]) -> ValueRef unsafe { +fn llmdnode(elems: ~[ValueRef]) -> ValueRef { unsafe { llvm::LLVMMDNode(vec::raw::to_ptr(elems), vec::len(elems) as libc::c_uint) @@ -95,8 +95,10 @@ fn llmdnode(elems: ~[ValueRef]) -> ValueRef unsafe { fn llunused() -> ValueRef { lli32(0x0) } -fn llnull() -> ValueRef unsafe { - cast::reinterpret_cast(&ptr::null::<ValueRef>()) +fn llnull() -> ValueRef { + unsafe { + cast::reinterpret_cast(&ptr::null::<ValueRef>()) + } } fn add_named_metadata(cx: @crate_ctxt, name: ~str, val: ValueRef) { @@ -154,68 +156,75 @@ enum debug_metadata { retval_metadata(@metadata<retval_md>), } -fn cast_safely<T: Copy, U>(val: T) -> U unsafe { - let val2 = val; - return cast::transmute(move val2); +fn cast_safely<T: Copy, U>(val: T) -> U { + unsafe { + let val2 = val; + return cast::transmute(move val2); + } } -fn md_from_metadata<T>(val: debug_metadata) -> T unsafe { - match val { - file_metadata(md) => cast_safely(md), - compile_unit_metadata(md) => cast_safely(md), - subprogram_metadata(md) => cast_safely(md), - local_var_metadata(md) => cast_safely(md), - tydesc_metadata(md) => cast_safely(md), - block_metadata(md) => cast_safely(md), - argument_metadata(md) => cast_safely(md), - retval_metadata(md) => cast_safely(md) +fn md_from_metadata<T>(val: debug_metadata) -> T { + unsafe { + match val { + file_metadata(md) => cast_safely(md), + compile_unit_metadata(md) => cast_safely(md), + subprogram_metadata(md) => cast_safely(md), + local_var_metadata(md) => cast_safely(md), + tydesc_metadata(md) => cast_safely(md), + block_metadata(md) => cast_safely(md), + argument_metadata(md) => cast_safely(md), + retval_metadata(md) => cast_safely(md) + } } } fn cached_metadata<T: Copy>(cache: metadata_cache, mdtag: int, - eq: fn(md: T) -> bool) -> Option<T> unsafe { - if cache.contains_key(mdtag) { - let items = cache.get(mdtag); - for items.each |item| { - let md: T = md_from_metadata::<T>(*item); - if eq(md) { - return option::Some(md); + eq: fn(md: T) -> bool) -> Option<T> { + unsafe { + if cache.contains_key(mdtag) { + let items = cache.get(mdtag); + for items.each |item| { + let md: T = md_from_metadata::<T>(*item); + if eq(md) { + return option::Some(md); + } } } + return option::None; } - return option::None; } -fn create_compile_unit(cx: @crate_ctxt) - -> @metadata<compile_unit_md> unsafe { - let cache = get_cache(cx); - let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; - let tg = CompileUnitTag; - match cached_metadata::<@metadata<compile_unit_md>>(cache, tg, - |md| md.data.name == crate_name) { - option::Some(md) => return md, - option::None => () - } - - let (_, work_dir) = get_file_path_and_dir(cx.sess.working_dir.to_str(), - crate_name); - let unit_metadata = ~[lltag(tg), - llunused(), - lli32(DW_LANG_RUST), - llstr(copy crate_name), - llstr(work_dir), - llstr(env!("CFG_VERSION")), - lli1(true), // deprecated: main compile unit - lli1(cx.sess.opts.optimize != session::No), - llstr(~""), // flags (???) - lli32(0) // runtime version (???) - ]; - let unit_node = llmdnode(unit_metadata); - add_named_metadata(cx, ~"llvm.dbg.cu", unit_node); - let mdval = @{node: unit_node, data: {name: crate_name}}; - update_cache(cache, tg, compile_unit_metadata(mdval)); +fn create_compile_unit(cx: @crate_ctxt) -> @metadata<compile_unit_md> { + unsafe { + let cache = get_cache(cx); + let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; + let tg = CompileUnitTag; + match cached_metadata::<@metadata<compile_unit_md>>(cache, tg, + |md| md.data.name == crate_name) { + option::Some(md) => return md, + option::None => () + } - return mdval; + let (_, work_dir) = get_file_path_and_dir( + cx.sess.working_dir.to_str(), crate_name); + let unit_metadata = ~[lltag(tg), + llunused(), + lli32(DW_LANG_RUST), + llstr(copy crate_name), + llstr(work_dir), + llstr(env!("CFG_VERSION")), + lli1(true), // deprecated: main compile unit + lli1(cx.sess.opts.optimize != session::No), + llstr(~""), // flags (???) + lli32(0) // runtime version (???) + ]; + let unit_node = llmdnode(unit_metadata); + add_named_metadata(cx, ~"llvm.dbg.cu", unit_node); + let mdval = @{node: unit_node, data: {name: crate_name}}; + update_cache(cache, tg, compile_unit_metadata(mdval)); + + return mdval; + } } fn get_cache(cx: @crate_ctxt) -> metadata_cache { @@ -646,94 +655,99 @@ fn create_var(type_tag: int, context: ValueRef, +name: ~str, file: ValueRef, } fn create_local_var(bcx: block, local: @ast::local) - -> @metadata<local_var_md> unsafe { - let cx = bcx.ccx(); - let cache = get_cache(cx); - let tg = AutoVariableTag; - match cached_metadata::<@metadata<local_var_md>>( - cache, tg, |md| md.data.id == local.node.id) { - option::Some(md) => return md, - option::None => () - } - - let name = match local.node.pat.node { - ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth), - // FIXME this should be handled (#2533) - _ => fail ~"no single variable name for local" - }; - let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); - let ty = node_id_type(bcx, local.node.id); - let tymd = create_ty(cx, ty, local.node.ty); - let filemd = create_file(cx, /*bad*/copy loc.file.name); - let context = match bcx.parent { - None => create_function(bcx.fcx).node, - Some(_) => create_block(bcx).node - }; - let mdnode = create_var(tg, context, cx.sess.str_of(name), filemd.node, - loc.line as int, tymd.node); - let mdval = @{node: mdnode, data: {id: local.node.id}}; - update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); - - let llptr = match bcx.fcx.lllocals.find(local.node.id) { - option::Some(local_mem(v)) => v, - option::Some(_) => { - bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ - something weird"); - } - option::None => { - match bcx.fcx.lllocals.get(local.node.pat.id) { - local_imm(v) => v, - _ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ - something weird") + -> @metadata<local_var_md> { + unsafe { + let cx = bcx.ccx(); + let cache = get_cache(cx); + let tg = AutoVariableTag; + match cached_metadata::<@metadata<local_var_md>>( + cache, tg, |md| md.data.id == local.node.id) { + option::Some(md) => return md, + option::None => () } - } - }; - let declargs = ~[llmdnode(~[llptr]), mdnode]; - trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"), - declargs); - return mdval; -} -fn create_arg(bcx: block, arg: ast::arg, sp: span) - -> Option<@metadata<argument_md>> unsafe { - let fcx = bcx.fcx, cx = fcx.ccx; - let cache = get_cache(cx); - let tg = ArgVariableTag; - match cached_metadata::<@metadata<argument_md>>( - cache, ArgVariableTag, |md| md.data.id == arg.id) { - option::Some(md) => return Some(md), - option::None => () + let name = match local.node.pat.node { + ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth), + // FIXME this should be handled (#2533) + _ => fail ~"no single variable name for local" + }; + let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); + let ty = node_id_type(bcx, local.node.id); + let tymd = create_ty(cx, ty, local.node.ty); + let filemd = create_file(cx, /*bad*/copy loc.file.name); + let context = match bcx.parent { + None => create_function(bcx.fcx).node, + Some(_) => create_block(bcx).node + }; + let mdnode = create_var(tg, context, cx.sess.str_of(name), + filemd.node, loc.line as int, tymd.node); + let mdval = @{node: mdnode, data: {id: local.node.id}}; + update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); + + let llptr = match bcx.fcx.lllocals.find(local.node.id) { + option::Some(local_mem(v)) => v, + option::Some(_) => { + bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ + something weird"); + } + option::None => { + match bcx.fcx.lllocals.get(local.node.pat.id) { + local_imm(v) => v, + _ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ + something weird") + } + } + }; + let declargs = ~[llmdnode(~[llptr]), mdnode]; + trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"), + declargs); + return mdval; } +} - let loc = cx.sess.codemap.lookup_char_pos(sp.lo); - let ty = node_id_type(bcx, arg.id); - let tymd = create_ty(cx, ty, arg.ty); - let filemd = create_file(cx, /*bad*/copy loc.file.name); - let context = create_function(bcx.fcx); - - match arg.pat.node { - ast::pat_ident(_, path, _) => { - // XXX: This is wrong; it should work for multiple bindings. - let mdnode = create_var(tg, - context.node, - cx.sess.str_of(path.idents.last()), - filemd.node, - loc.line as int, - tymd.node); - - let mdval = @{node: mdnode, data: {id: arg.id}}; - update_cache(cache, tg, argument_metadata(mdval)); - - let llptr = match fcx.llargs.get(arg.id) { - local_mem(v) | local_imm(v) => v, - }; - let declargs = ~[llmdnode(~[llptr]), mdnode]; - trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"), - declargs); - return Some(mdval); +fn create_arg(bcx: block, arg: ast::arg, sp: span) + -> Option<@metadata<argument_md>> { + unsafe { + let fcx = bcx.fcx, cx = fcx.ccx; + let cache = get_cache(cx); + let tg = ArgVariableTag; + match cached_metadata::<@metadata<argument_md>>( + cache, ArgVariableTag, |md| md.data.id == arg.id) { + option::Some(md) => return Some(md), + option::None => () } - _ => { - return None; + + let loc = cx.sess.codemap.lookup_char_pos(sp.lo); + let ty = node_id_type(bcx, arg.id); + let tymd = create_ty(cx, ty, arg.ty); + let filemd = create_file(cx, /*bad*/copy loc.file.name); + let context = create_function(bcx.fcx); + + match arg.pat.node { + ast::pat_ident(_, path, _) => { + // XXX: This is wrong; it should work for multiple bindings. + let mdnode = create_var(tg, + context.node, + cx.sess.str_of(path.idents.last()), + filemd.node, + loc.line as int, + tymd.node); + + let mdval = @{node: mdnode, data: {id: arg.id}}; + update_cache(cache, tg, argument_metadata(mdval)); + + let llptr = match fcx.llargs.get(arg.id) { + local_mem(v) | local_imm(v) => v, + }; + let declargs = ~[llmdnode(~[llptr]), mdnode]; + trans::build::Call(bcx, + cx.intrinsics.get(~"llvm.dbg.declare"), + declargs); + return Some(mdval); + } + _ => { + return None; + } } } } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 4c373e0d217..51d44f33a81 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// The classification code for the x86_64 ABI is taken from the clay language -// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp - use core::prelude::*; use back::{link, abi}; @@ -22,6 +19,8 @@ use lib::llvm::{StructRetAttribute, ByValAttribute}; use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double}; use lib; use middle::trans::base::*; +use middle::trans::cabi; +use middle::trans::cabi_x86_64::*; use middle::trans::build::*; use middle::trans::callee::*; use middle::trans::common::*; @@ -44,417 +43,11 @@ use syntax::parse::token::special_idents; export link_name, trans_foreign_mod, register_foreign_fn, trans_foreign_fn, trans_intrinsic; -enum x86_64_reg_class { - no_class, - integer_class, - sse_fs_class, - sse_fv_class, - sse_ds_class, - sse_dv_class, - sse_int_class, - sseup_class, - x87_class, - x87up_class, - complex_x87_class, - memory_class -} - -impl x86_64_reg_class : cmp::Eq { - pure fn eq(&self, other: &x86_64_reg_class) -> bool { - ((*self) as uint) == ((*other) as uint) - } - pure fn ne(&self, other: &x86_64_reg_class) -> bool { !(*self).eq(other) } -} - -fn is_sse(++c: x86_64_reg_class) -> bool { - return match c { - sse_fs_class | sse_fv_class | - sse_ds_class | sse_dv_class => true, - _ => false - }; -} - -fn is_ymm(cls: &[x86_64_reg_class]) -> bool { - let len = vec::len(cls); - return (len > 2u && - is_sse(cls[0]) && - cls[1] == sseup_class && - cls[2] == sseup_class) || - (len > 3u && - is_sse(cls[1]) && - cls[2] == sseup_class && - cls[3] == sseup_class); -} - -fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { - fn align(off: uint, ty: TypeRef) -> uint { - let a = ty_align(ty); - return (off + a - 1u) / a * a; - } - - fn struct_tys(ty: TypeRef) -> ~[TypeRef] { - unsafe { - let n = llvm::LLVMCountStructElementTypes(ty); - if (n == 0) { - return ~[]; - } - let mut elts = vec::from_elem(n as uint, ptr::null()); - llvm::LLVMGetStructElementTypes(ty, - ptr::to_mut_unsafe_ptr(&mut elts[0])); - return elts; - } - } - - fn ty_align(ty: TypeRef) -> uint { - unsafe { - return match llvm::LLVMGetTypeKind(ty) { - Integer => { - ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8 - } - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - do vec::foldl(1, struct_tys(ty)) |a, t| { - uint::max(a, ty_align(*t)) - } - } - Array => { - let elt = llvm::LLVMGetElementType(ty); - ty_align(elt) - } - _ => fail ~"ty_size: unhandled type" - }; - } - } - - fn ty_size(ty: TypeRef) -> uint { - unsafe { - return match llvm::LLVMGetTypeKind(ty) { - Integer => { - ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8 - } - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - let size = do vec::foldl(0, struct_tys(ty)) |s, t| { - align(s, *t) + ty_size(*t) - }; - align(size, ty) - } - Array => { - let len = llvm::LLVMGetArrayLength(ty) as uint; - let elt = llvm::LLVMGetElementType(ty); - let eltsz = ty_size(elt); - len * eltsz - } - _ => fail ~"ty_size: unhandled type" - }; - } - } - - fn all_mem(cls: &[mut x86_64_reg_class]) { - for uint::range(0, cls.len()) |i| { - cls[i] = memory_class; - } - } - - fn unify(cls: &[mut x86_64_reg_class], - i: uint, - newv: x86_64_reg_class) { - if cls[i] == newv { - return; - } else if cls[i] == no_class { - cls[i] = newv; - } else if newv == no_class { - return; - } else if cls[i] == memory_class || newv == memory_class { - cls[i] = memory_class; - } else if cls[i] == integer_class || newv == integer_class { - cls[i] = integer_class; - } else if cls[i] == x87_class || - cls[i] == x87up_class || - cls[i] == complex_x87_class || - newv == x87_class || - newv == x87up_class || - newv == complex_x87_class { - cls[i] = memory_class; - } else { - cls[i] = newv; - } - } - - fn classify_struct(tys: &[TypeRef], - cls: &[mut x86_64_reg_class], i: uint, - off: uint) { - let mut field_off = off; - for vec::each(tys) |ty| { - field_off = align(field_off, *ty); - classify(*ty, cls, i, field_off); - field_off += ty_size(*ty); - } - } - - fn classify(ty: TypeRef, - cls: &[mut x86_64_reg_class], ix: uint, - off: uint) { - unsafe { - let t_align = ty_align(ty); - let t_size = ty_size(ty); - - let misalign = off % t_align; - if misalign != 0u { - let mut i = off / 8u; - let e = (off + t_size + 7u) / 8u; - while i < e { - unify(cls, ix + i, memory_class); - i += 1u; - } - return; - } - - match llvm::LLVMGetTypeKind(ty) as int { - 8 /* integer */ | - 12 /* pointer */ => { - unify(cls, ix + off / 8u, integer_class); - } - 2 /* float */ => { - if off % 8u == 4u { - unify(cls, ix + off / 8u, sse_fv_class); - } else { - unify(cls, ix + off / 8u, sse_fs_class); - } - } - 3 /* double */ => { - unify(cls, ix + off / 8u, sse_ds_class); - } - 10 /* struct */ => { - classify_struct(struct_tys(ty), cls, ix, off); - } - 11 /* array */ => { - let elt = llvm::LLVMGetElementType(ty); - let eltsz = ty_size(elt); - let len = llvm::LLVMGetArrayLength(ty) as uint; - let mut i = 0u; - while i < len { - classify(elt, cls, ix, off + i * eltsz); - i += 1u; - } - } - _ => fail ~"classify: unhandled type" - } - } - } - - fn fixup(ty: TypeRef, cls: &[mut x86_64_reg_class]) { - unsafe { - let mut i = 0u; - let llty = llvm::LLVMGetTypeKind(ty) as int; - let e = vec::len(cls); - if vec::len(cls) > 2u && - (llty == 10 /* struct */ || - llty == 11 /* array */) { - if is_sse(cls[i]) { - i += 1u; - while i < e { - if cls[i] != sseup_class { - all_mem(cls); - return; - } - i += 1u; - } - } else { - all_mem(cls); - return - } - } else { - while i < e { - if cls[i] == memory_class { - all_mem(cls); - return; - } - if cls[i] == x87up_class { - // for darwin - // cls[i] = sse_ds_class; - all_mem(cls); - return; - } - if cls[i] == sseup_class { - cls[i] = sse_int_class; - } else if is_sse(cls[i]) { - i += 1; - while cls[i] == sseup_class { i += 1u; } - } else if cls[i] == x87_class { - i += 1; - while cls[i] == x87up_class { i += 1u; } - } else { - i += 1; - } - } - } - } - } - - let words = (ty_size(ty) + 7) / 8; - let cls = vec::to_mut(vec::from_elem(words, no_class)); - if words > 4 { - all_mem(cls); - return vec::from_mut(move cls); - } - classify(ty, cls, 0, 0); - fixup(ty, cls); - return vec::from_mut(move cls); -} - -fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef { - fn llvec_len(cls: &[x86_64_reg_class]) -> uint { - let mut len = 1u; - for vec::each(cls) |c| { - if *c != sseup_class { - break; - } - len += 1u; - } - return len; - } - - unsafe { - let mut tys = ~[]; - let mut i = 0u; - let e = vec::len(cls); - while i < e { - match cls[i] { - integer_class => { - tys.push(T_i64()); - } - sse_fv_class => { - let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u; - let vec_ty = llvm::LLVMVectorType(T_f32(), - vec_len as c_uint); - tys.push(vec_ty); - i += vec_len; - loop; - } - sse_fs_class => { - tys.push(T_f32()); - } - sse_ds_class => { - tys.push(T_f64()); - } - _ => fail ~"llregtype: unhandled class" - } - i += 1u; - } - return T_struct(tys); - } -} - -type x86_64_llty = { - cast: bool, - ty: TypeRef -}; - -type x86_64_tys = { - arg_tys: ~[x86_64_llty], - ret_ty: x86_64_llty, - attrs: ~[Option<Attribute>], - sret: bool -}; - -fn x86_64_tys(atys: &[TypeRef], - rty: TypeRef, - ret_def: bool) -> x86_64_tys { - fn is_reg_ty(ty: TypeRef) -> bool { - unsafe { - return match llvm::LLVMGetTypeKind(ty) as int { - 8 /* integer */ | - 12 /* pointer */ | - 2 /* float */ | - 3 /* double */ => true, - _ => false - }; - } - } - - fn is_pass_byval(cls: &[x86_64_reg_class]) -> bool { - return cls.len() > 0 && - (cls[0] == memory_class || - cls[0] == x87_class || - cls[0] == complex_x87_class); - } - - fn is_ret_bysret(cls: &[x86_64_reg_class]) -> bool { - return cls.len() > 0 && cls[0] == memory_class; - } - - fn x86_64_ty(ty: TypeRef, - is_mem_cls: fn(cls: &[x86_64_reg_class]) -> bool, - attr: Attribute) -> (x86_64_llty, Option<Attribute>) { - let mut cast = false; - let mut ty_attr = option::None; - let mut llty = ty; - if !is_reg_ty(ty) { - let cls = classify_ty(ty); - if is_mem_cls(cls) { - llty = T_ptr(ty); - ty_attr = option::Some(attr); - } else { - cast = true; - llty = llreg_ty(cls); - } - } - return ({ cast: cast, ty: llty }, ty_attr); - } - - let mut arg_tys = ~[]; - let mut attrs = ~[]; - for vec::each(atys) |t| { - let (ty, attr) = x86_64_ty(*t, is_pass_byval, ByValAttribute); - arg_tys.push(ty); - attrs.push(attr); - } - let mut (ret_ty, ret_attr) = x86_64_ty(rty, is_ret_bysret, - StructRetAttribute); - let sret = ret_attr.is_some(); - if sret { - arg_tys = vec::append(~[ret_ty], arg_tys); - ret_ty = { cast: false, - ty: T_void() - }; - attrs = vec::append(~[ret_attr], attrs); - } else if !ret_def { - ret_ty = { cast: false, - ty: T_void() - }; - } - return { - arg_tys: arg_tys, - ret_ty: ret_ty, - attrs: attrs, - sret: sret - }; -} - -fn decl_x86_64_fn(tys: x86_64_tys, - decl: fn(fnty: TypeRef) -> ValueRef) -> ValueRef { - let atys = vec::map(tys.arg_tys, |t| t.ty); - let rty = tys.ret_ty.ty; - let fnty = T_fn(atys, rty); - let llfn = decl(fnty); - - for vec::eachi(tys.attrs) |i, a| { - match *a { - option::Some(attr) => { - unsafe { - let llarg = get_param(llfn, i); - llvm::LLVMAddAttribute(llarg, attr as c_uint); - } - } - _ => () - } +fn abi_info(arch: session::arch) -> cabi::ABIInfo { + return match arch { + arch_x86_64 => x86_64_abi_info(), + _ => cabi::llvm_abi_info() } - return llfn; } fn link_name(ccx: @crate_ctxt, i: @ast::foreign_item) -> ~str { @@ -470,7 +63,7 @@ type c_stack_tys = { ret_def: bool, bundle_ty: TypeRef, shim_fn_ty: TypeRef, - x86_64_tys: Option<x86_64_tys> + fn_ty: cabi::FnType }; fn c_arg_and_ret_lltys(ccx: @crate_ctxt, @@ -493,20 +86,15 @@ fn c_stack_tys(ccx: @crate_ctxt, // XXX: Bad copy. let bundle_ty = T_struct(vec::append_one(copy llargtys, T_ptr(llretty))); let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); - let x86_64 = if ccx.sess.targ_cfg.arch == arch_x86_64 { - option::Some(x86_64_tys(llargtys, llretty, ret_def)) - } else if ccx.sess.targ_cfg.arch == arch_arm { - option::Some(x86_64_tys(llargtys, llretty, ret_def)) - } else { - option::None - }; + let fn_ty = abi_info(ccx.sess.targ_cfg.arch). + compute_info(llargtys, llretty, ret_def); return @{ arg_tys: llargtys, ret_ty: llretty, ret_def: ret_def, bundle_ty: bundle_ty, shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_void()), - x86_64_tys: x86_64 + fn_ty: fn_ty }; } @@ -633,92 +221,14 @@ fn trans_foreign_mod(ccx: @crate_ctxt, fn build_args(bcx: block, tys: @c_stack_tys, llargbundle: ValueRef) -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::shim::build_args"); - let mut llargvals = ~[]; - let mut i = 0u; - let n = vec::len(tys.arg_tys); - - match tys.x86_64_tys { - Some(ref x86_64) => { - let mut atys = /*bad*/copy (*x86_64).arg_tys; - let mut attrs = /*bad*/copy (*x86_64).attrs; - if (*x86_64).sret { - let llretptr = GEPi(bcx, llargbundle, [0u, n]); - let llretloc = Load(bcx, llretptr); - llargvals = ~[llretloc]; - atys = vec::tail(atys); - attrs = vec::tail(attrs); - } - while i < n { - let llargval = if atys[i].cast { - let arg_ptr = GEPi(bcx, llargbundle, [0u, i]); - let arg_ptr = BitCast(bcx, arg_ptr, - T_ptr(atys[i].ty)); - Load(bcx, arg_ptr) - } else if attrs[i].is_some() { - GEPi(bcx, llargbundle, [0u, i]) - } else { - load_inbounds(bcx, llargbundle, [0u, i]) - }; - llargvals.push(llargval); - i += 1u; - } - } - _ => { - while i < n { - let llargval = load_inbounds(bcx, llargbundle, - [0u, i]); - llargvals.push(llargval); - i += 1u; - } - } - } - return llargvals; + return tys.fn_ty.build_shim_args(bcx, tys.arg_tys, llargbundle); } fn build_ret(bcx: block, tys: @c_stack_tys, llargbundle: ValueRef, llretval: ValueRef) { let _icx = bcx.insn_ctxt("foreign::shim::build_ret"); - match tys.x86_64_tys { - Some(ref x86_64) => { - for vec::eachi((*x86_64).attrs) |i, a| { - match *a { - Some(attr) => { - unsafe { - llvm::LLVMAddInstrAttribute( - llretval, (i + 1u) as c_uint, - attr as c_uint); - } - } - _ => () - } - } - if (*x86_64).sret || !tys.ret_def { - return; - } - let n = vec::len(tys.arg_tys); - let llretptr = GEPi(bcx, llargbundle, [0u, n]); - let llretloc = Load(bcx, llretptr); - if (*x86_64).ret_ty.cast { - let tmp_ptr = BitCast(bcx, - llretloc, - T_ptr((*x86_64).ret_ty.ty)); - Store(bcx, llretval, tmp_ptr); - } else { - Store(bcx, llretval, llretloc); - }; - } - _ => { - if tys.ret_def { - let n = vec::len(tys.arg_tys); - // R** llretptr = &args->r; - let llretptr = GEPi(bcx, llargbundle, [0u, n]); - // R* llretloc = *llretptr; /* (args->r) */ - let llretloc = Load(bcx, llretptr); - // *args->r = r; - Store(bcx, llretval, llretloc); - } - } - } + tys.fn_ty.build_shim_ret(bcx, tys.arg_tys, tys.ret_def, + llargbundle, llretval); } let lname = link_name(ccx, foreign_item); @@ -732,16 +242,8 @@ fn trans_foreign_mod(ccx: @crate_ctxt, fn base_fn(ccx: @crate_ctxt, +lname: ~str, tys: @c_stack_tys, cc: lib::llvm::CallConv) -> ValueRef { // Declare the "prototype" for the base function F: - match tys.x86_64_tys { - Some(ref x86_64) => { - do decl_x86_64_fn((*x86_64)) |fnty| { - decl_fn(ccx.llmod, /*bad*/copy lname, cc, fnty) - } - } - _ => { - let llbasefnty = T_fn(/*bad*/copy tys.arg_tys, tys.ret_ty); - decl_fn(ccx.llmod, lname, cc, llbasefnty) - } + do tys.fn_ty.decl_fn |fnty| { + decl_fn(ccx.llmod, /*bad*/copy lname, cc, fnty) } } @@ -1383,84 +885,15 @@ fn trans_foreign_fn(ccx: @crate_ctxt, +path: ast_map::path, fn build_args(bcx: block, tys: @c_stack_tys, llwrapfn: ValueRef, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); - match tys.x86_64_tys { - option::Some(ref x86_64) => { - let mut atys = /*bad*/copy (*x86_64).arg_tys; - let mut attrs = /*bad*/copy (*x86_64).attrs; - let mut j = 0u; - let llretptr = if (*x86_64).sret { - atys = vec::tail(atys); - attrs = vec::tail(attrs); - j = 1u; - get_param(llwrapfn, 0u) - } else if (*x86_64).ret_ty.cast { - let retptr = alloca(bcx, (*x86_64).ret_ty.ty); - BitCast(bcx, retptr, T_ptr(tys.ret_ty)) - } else { - alloca(bcx, tys.ret_ty) - }; - - let mut i = 0u; - let n = vec::len(atys); - while i < n { - let mut argval = get_param(llwrapfn, i + j); - if attrs[i].is_some() { - argval = Load(bcx, argval); - store_inbounds(bcx, argval, llargbundle, - [0u, i]); - } else if atys[i].cast { - let argptr = GEPi(bcx, llargbundle, [0u, i]); - let argptr = BitCast(bcx, argptr, - T_ptr(atys[i].ty)); - Store(bcx, argval, argptr); - } else { - store_inbounds(bcx, argval, llargbundle, - [0u, i]); - } - i += 1u; - } - store_inbounds(bcx, llretptr, llargbundle, [0u, n]); - } - _ => { - let llretptr = alloca(bcx, tys.ret_ty); - let n = vec::len(tys.arg_tys); - for uint::range(0u, n) |i| { - let llargval = get_param(llwrapfn, i); - store_inbounds(bcx, llargval, llargbundle, - [0u, i]); - }; - store_inbounds(bcx, llretptr, llargbundle, [0u, n]); - } - } + tys.fn_ty.build_wrap_args(bcx, tys.ret_ty, + llwrapfn, llargbundle); } fn build_ret(bcx: block, tys: @c_stack_tys, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_ret"); - match tys.x86_64_tys { - option::Some(ref x86_64) => { - if (*x86_64).sret || !tys.ret_def { - RetVoid(bcx); - return; - } - let n = vec::len(tys.arg_tys); - let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]); - let llretval = if (*x86_64).ret_ty.cast { - let retptr = BitCast(bcx, llretval, - T_ptr((*x86_64).ret_ty.ty)); - Load(bcx, retptr) - } else { - Load(bcx, llretval) - }; - Ret(bcx, llretval); - } - _ => { - let n = vec::len(tys.arg_tys); - let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]); - let llretval = Load(bcx, llretval); - Ret(bcx, llretval); - } - } + tys.fn_ty.build_wrap_ret(bcx, tys.arg_tys, tys.ret_def, + llargbundle); } build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, @@ -1487,25 +920,12 @@ fn register_foreign_fn(ccx: @crate_ctxt, let _icx = ccx.insn_ctxt("foreign::register_foreign_fn"); let t = ty::node_id_to_type(ccx.tcx, node_id); let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, node_id); - return if ccx.sess.targ_cfg.arch == arch_x86_64 { - let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); - let x86_64 = x86_64_tys(llargtys, llretty, ret_def); - do decl_x86_64_fn(x86_64) |fnty| { - register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs, - t, lib::llvm::CCallConv, fnty) - } - } else if ccx.sess.targ_cfg.arch == arch_arm { - let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); - let x86_64 = x86_64_tys(llargtys, llretty, ret_def); - do decl_x86_64_fn(x86_64) |fnty| { - register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs, - t, lib::llvm::CCallConv, fnty) - } - - } else { - let llfty = T_fn(llargtys, llretty); - register_fn_fuller(ccx, sp, path, node_id, attrs, - t, lib::llvm::CCallConv, llfty) + let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); + let fn_ty = abi_info(ccx.sess.targ_cfg.arch). + compute_info(llargtys, llretty, ret_def); + do fn_ty.decl_fn |fnty| { + register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs, + t, lib::llvm::CCallConv, fnty) } } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 8c34069df42..ba1901f215c 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -68,7 +68,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) // Conservatively assume full use for recursive loops ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u)); - let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))}; + let cx = {ccx: ccx, uses: vec::cast_to_mut(vec::from_elem(n_tps, 0u))}; match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty { ty::ty_fn(ref fn_ty) => { for vec::each(fn_ty.sig.inputs) |arg| { @@ -84,7 +84,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) } if fn_id_loc.crate != local_crate { - let uses = vec::from_mut(copy cx.uses); + let uses = vec::cast_from_mut(copy cx.uses); ccx.type_use_cache.insert(fn_id, copy uses); return uses; } @@ -167,7 +167,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) ccx.tcx.sess.parse_sess.interner))); } } - let uses = vec::from_mut(copy cx.uses); + let uses = vec::cast_from_mut(copy cx.uses); // XXX: Bad copy, use @vec instead? ccx.type_use_cache.insert(fn_id, copy uses); uses diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b5870059c67..5607e55d490 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -498,11 +498,13 @@ type t_box = @{sty: sty, enum t_opaque {} type t = *t_opaque; -pure fn get(t: t) -> t_box unsafe { - let t2 = cast::reinterpret_cast::<t, t_box>(&t); - let t3 = t2; - cast::forget(move t2); - t3 +pure fn get(t: t) -> t_box { + unsafe { + let t2 = cast::reinterpret_cast::<t, t_box>(&t); + let t3 = t2; + cast::forget(move t2); + t3 + } } pure fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5899ac04586..6f2f56846c8 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3024,7 +3024,7 @@ fn check_bounds_are_used(ccx: @crate_ctxt, // make a vector of booleans initially false, set to true when used if tps.len() == 0u { return; } - let tps_used = vec::to_mut(vec::from_elem(tps.len(), false)); + let tps_used = vec::cast_to_mut(vec::from_elem(tps.len(), false)); ty::walk_regions_and_ty( ccx.tcx, ty, diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index edbe271b900..98f3c0f8b08 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -633,12 +633,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { let (_, provided_methods) = split_trait_methods(/*bad*/copy *trait_methods); let {bounds, _} = mk_substs(ccx, /*bad*/copy *tps, rp); - let _cms = convert_methods(ccx, provided_methods, rp, bounds); - // FIXME (#2616): something like this, when we start having - // trait inheritance? - // for trait_ref.each |t| { - // check_methods_against_trait(ccx, tps, rp, selfty, *t, cms); - // } + let _ = convert_methods(ccx, provided_methods, rp, bounds); } ast::item_struct(struct_def, tps) => { // Write the class type diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 4e101eb5bb7..818c6eb04ea 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -86,6 +86,10 @@ mod middle { #[legacy_exports] mod meth; #[legacy_exports] + mod cabi; + #[legacy_exports] + mod cabi_x86_64; + #[legacy_exports] mod foreign; #[legacy_exports] mod reflect; diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 288163accfe..57b338f4aa1 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -13,7 +13,7 @@ use core::ops; use core::prelude::*; use core::uint; -use core::vec::{to_mut, from_elem}; +use core::vec::{cast_to_mut, from_elem}; use core::vec; struct SmallBitv { @@ -141,9 +141,11 @@ impl BigBitv { let w0 = self.storage[i] & mask; let w1 = b.storage[i] & mask; let w = op(w0, w1) & mask; - if w0 != w unsafe { - changed = true; - self.storage[i] = w; + if w0 != w { + unsafe { + changed = true; + self.storage[i] = w; + } } true } @@ -231,7 +233,7 @@ pub fn Bitv (nbits: uint, init: bool) -> Bitv { let nelems = nbits/uint_bits + if nbits % uint_bits == 0 {0} else {1}; let elem = if init {!0} else {0}; - let s = to_mut(from_elem(nelems, elem)); + let s = cast_to_mut(from_elem(nelems, elem)); Big(~BigBitv(move s)) }; Bitv {rep: move rep, nbits: nbits} @@ -516,7 +518,7 @@ impl Bitv: Clone { Bitv{nbits: self.nbits, rep: Small(~SmallBitv{bits: b.bits})} } Big(ref b) => { - let st = to_mut(from_elem(self.nbits / uint_bits + 1, 0)); + let st = cast_to_mut(from_elem(self.nbits / uint_bits + 1, 0)); let len = st.len(); for uint::range(0, len) |i| { st[i] = b.storage[i]; }; Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: move st})} diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index 93eb2095c5e..e3cc6797abf 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -219,126 +219,128 @@ pub type Result = result::Result<Matches, Fail_>; * `opt_str`, etc. to interrogate results. Returns `err(Fail_)` on failure. * Use <fail_str> to get an error message. */ -pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe { - let n_opts = opts.len(); - fn f(_x: uint) -> ~[Optval] { return ~[]; } - let vals = vec::to_mut(vec::from_fn(n_opts, f)); - let mut free: ~[~str] = ~[]; - let l = args.len(); - let mut i = 0; - while i < l { - let cur = args[i]; - let curlen = cur.len(); - if !is_arg(cur) { - free.push(cur); - } else if cur == ~"--" { - let mut j = i + 1; - while j < l { free.push(args[j]); j += 1; } - break; - } else { - let mut names; - let mut i_arg = None; - if cur[1] == '-' as u8 { - let tail = str::slice(cur, 2, curlen); - let tail_eq = str::splitn_char(tail, '=', 1); - if tail_eq.len() <= 1 { - names = ~[Long(tail)]; - } else { - names = - ~[Long(tail_eq[0])]; - i_arg = Some(tail_eq[1]); - } +pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { + unsafe { + let n_opts = opts.len(); + fn f(_x: uint) -> ~[Optval] { return ~[]; } + let vals = vec::cast_to_mut(vec::from_fn(n_opts, f)); + let mut free: ~[~str] = ~[]; + let l = args.len(); + let mut i = 0; + while i < l { + let cur = args[i]; + let curlen = cur.len(); + if !is_arg(cur) { + free.push(cur); + } else if cur == ~"--" { + let mut j = i + 1; + while j < l { free.push(args[j]); j += 1; } + break; } else { - let mut j = 1; - let mut last_valid_opt_id = None; - names = ~[]; - while j < curlen { - let range = str::char_range_at(cur, j); - let opt = Short(range.ch); - - /* In a series of potential options (eg. -aheJ), if we see - one which takes an argument, we assume all subsequent - characters make up the argument. This allows options - such as -L/usr/local/lib/foo to be interpreted - correctly - */ - - match find_opt(opts, opt) { - Some(id) => last_valid_opt_id = Some(id), - None => { - let arg_follows = - last_valid_opt_id.is_some() && - match opts[last_valid_opt_id.get()] - .hasarg { - - Yes | Maybe => true, - No => false - }; - if arg_follows && j < curlen { - i_arg = Some(cur.slice(j, curlen)); - break; - } else { - last_valid_opt_id = None; + let mut names; + let mut i_arg = None; + if cur[1] == '-' as u8 { + let tail = str::slice(cur, 2, curlen); + let tail_eq = str::splitn_char(tail, '=', 1); + if tail_eq.len() <= 1 { + names = ~[Long(tail)]; + } else { + names = + ~[Long(tail_eq[0])]; + i_arg = Some(tail_eq[1]); + } + } else { + let mut j = 1; + let mut last_valid_opt_id = None; + names = ~[]; + while j < curlen { + let range = str::char_range_at(cur, j); + let opt = Short(range.ch); + + /* In a series of potential options (eg. -aheJ), if we + see one which takes an argument, we assume all + subsequent characters make up the argument. This + allows options such as -L/usr/local/lib/foo to be + interpreted correctly + */ + + match find_opt(opts, opt) { + Some(id) => last_valid_opt_id = Some(id), + None => { + let arg_follows = + last_valid_opt_id.is_some() && + match opts[last_valid_opt_id.get()] + .hasarg { + + Yes | Maybe => true, + No => false + }; + if arg_follows && j < curlen { + i_arg = Some(cur.slice(j, curlen)); + break; + } else { + last_valid_opt_id = None; + } + } } - } + names.push(opt); + j = range.next; } - names.push(opt); - j = range.next; } - } - let mut name_pos = 0; - for names.each() |nm| { - name_pos += 1; - let optid = match find_opt(opts, *nm) { - Some(id) => id, - None => return Err(UnrecognizedOption(name_str(nm))) - }; - match opts[optid].hasarg { - No => { - if !i_arg.is_none() { - return Err(UnexpectedArgument(name_str(nm))); - } - vals[optid].push(Given); - } - Maybe => { - if !i_arg.is_none() { - vals[optid].push(Val(i_arg.get())); - } else if name_pos < names.len() || - i + 1 == l || is_arg(args[i + 1]) { + let mut name_pos = 0; + for names.each() |nm| { + name_pos += 1; + let optid = match find_opt(opts, *nm) { + Some(id) => id, + None => return Err(UnrecognizedOption(name_str(nm))) + }; + match opts[optid].hasarg { + No => { + if !i_arg.is_none() { + return Err(UnexpectedArgument(name_str(nm))); + } vals[optid].push(Given); - } else { i += 1; vals[optid].push(Val(args[i])); } - } - Yes => { - if !i_arg.is_none() { - vals[optid].push(Val(i_arg.get())); - } else if i + 1 == l { - return Err(ArgumentMissing(name_str(nm))); - } else { i += 1; vals[optid].push(Val(args[i])); } - } + } + Maybe => { + if !i_arg.is_none() { + vals[optid].push(Val(i_arg.get())); + } else if name_pos < names.len() || + i + 1 == l || is_arg(args[i + 1]) { + vals[optid].push(Given); + } else { i += 1; vals[optid].push(Val(args[i])); } + } + Yes => { + if !i_arg.is_none() { + vals[optid].push(Val(i_arg.get())); + } else if i + 1 == l { + return Err(ArgumentMissing(name_str(nm))); + } else { i += 1; vals[optid].push(Val(args[i])); } + } + } } } + i += 1; } - i += 1; - } - i = 0u; - while i < n_opts { - let n = vals[i].len(); - let occ = opts[i].occur; - if occ == Req { - if n == 0 { - return Err(OptionMissing(name_str(&(opts[i].name)))); + i = 0u; + while i < n_opts { + let n = vals[i].len(); + let occ = opts[i].occur; + if occ == Req { + if n == 0 { + return Err(OptionMissing(name_str(&(opts[i].name)))); + } } - } - if occ != Multi { - if n > 1 { - return Err(OptionDuplicated(name_str(&(opts[i].name)))); + if occ != Multi { + if n > 1 { + return Err(OptionDuplicated(name_str(&(opts[i].name)))); + } } + i += 1; } - i += 1; + return Ok(Matches {opts: vec::from_slice(opts), + vals: vec::cast_from_mut(move vals), + free: free}); } - return Ok(Matches {opts: vec::from_slice(opts), - vals: vec::from_mut(move vals), - free: free}); } fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] { diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 58f580bde51..ed3dbb48b2a 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -337,9 +337,11 @@ pub fn to_writer(wr: io::Writer, json: &Json) { } /// Encodes a json value into a string -pub pure fn to_str(json: &Json) -> ~str unsafe { - // ugh, should be safe - io::with_str_writer(|wr| to_writer(wr, json)) +pub pure fn to_str(json: &Json) -> ~str { + unsafe { + // ugh, should be safe + io::with_str_writer(|wr| to_writer(wr, json)) + } } /// Encodes a json value into a io::writer diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 5a64fec3763..4c05dd154ca 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -434,9 +434,11 @@ pub mod chained { } impl<K:Eq IterBytes Hash Copy ToStr, V: ToStr Copy> T<K, V>: ToStr { - pure fn to_str() -> ~str unsafe { - // Meh -- this should be safe - do io::with_str_writer |wr| { self.to_writer(wr) } + pure fn to_str() -> ~str { + unsafe { + // Meh -- this should be safe + do io::with_str_writer |wr| { self.to_writer(wr) } + } } } @@ -449,7 +451,7 @@ pub mod chained { } fn chains<K,V>(nchains: uint) -> ~[mut Option<@Entry<K,V>>] { - vec::to_mut(vec::from_elem(nchains, None)) + vec::cast_to_mut(vec::from_elem(nchains, None)) } pub fn mk<K:Eq IterBytes Hash, V: Copy>() -> T<K,V> { diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs index d10533008d9..06b6aca6895 100644 --- a/src/libstd/md4.rs +++ b/src/libstd/md4.rs @@ -47,7 +47,7 @@ pub pure fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { let mut i = 0u; let e = vec::len(msg); - let x = vec::to_mut(vec::from_elem(16u, 0u32)); + let x = vec::cast_to_mut(vec::from_elem(16u, 0u32)); while i < e { let aa = a, bb = b, cc = c, dd = d; diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index fad583a668b..d273138ed3d 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -117,32 +117,36 @@ enum IpGetAddrErr { pub fn get_addr(node: &str, iotask: iotask) -> result::Result<~[IpAddr], IpGetAddrErr> { do oldcomm::listen |output_ch| { - do str::as_buf(node) |node_ptr, len| unsafe { - log(debug, fmt!("slice len %?", len)); - let handle = create_uv_getaddrinfo_t(); - let handle_ptr = ptr::addr_of(&handle); - let handle_data: GetAddrData = { - output_ch: output_ch - }; - let handle_data_ptr = ptr::addr_of(&handle_data); - do interact(iotask) |loop_ptr| unsafe { - let result = uv_getaddrinfo( - loop_ptr, - handle_ptr, - get_addr_cb, - node_ptr, - ptr::null(), - ptr::null()); - match result { - 0i32 => { - set_data_for_req(handle_ptr, handle_data_ptr); - } - _ => { - output_ch.send(result::Err(GetAddrUnknownError)); - } - } - }; - output_ch.recv() + do str::as_buf(node) |node_ptr, len| { + unsafe { + log(debug, fmt!("slice len %?", len)); + let handle = create_uv_getaddrinfo_t(); + let handle_ptr = ptr::addr_of(&handle); + let handle_data: GetAddrData = { + output_ch: output_ch + }; + let handle_data_ptr = ptr::addr_of(&handle_data); + do interact(iotask) |loop_ptr| { + unsafe { + let result = uv_getaddrinfo( + loop_ptr, + handle_ptr, + get_addr_cb, + node_ptr, + ptr::null(), + ptr::null()); + match result { + 0i32 => { + set_data_for_req(handle_ptr, handle_data_ptr); + } + _ => { + output_ch.send(result::Err(GetAddrUnknownError)); + } + } + } + }; + output_ch.recv() + } } } } @@ -300,62 +304,64 @@ type GetAddrData = { }; extern fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, - res: *addrinfo) unsafe { - log(debug, ~"in get_addr_cb"); - let handle_data = get_data_for_req(handle) as - *GetAddrData; - if status == 0i32 { - if res != (ptr::null::<addrinfo>()) { - let mut out_vec = ~[]; - log(debug, fmt!("initial addrinfo: %?", res)); - let mut curr_addr = res; - loop { - let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) { - Ipv4(copy(( - *ll::addrinfo_as_sockaddr_in(curr_addr)))) - } - else if ll::is_ipv6_addrinfo(curr_addr) { - Ipv6(copy(( - *ll::addrinfo_as_sockaddr_in6(curr_addr)))) - } - else { - log(debug, ~"curr_addr is not of family AF_INET or "+ - ~"AF_INET6. Error."); - (*handle_data).output_ch.send( - result::Err(GetAddrUnknownError)); - break; - }; - out_vec.push(move new_ip_addr); + res: *addrinfo) { + unsafe { + log(debug, ~"in get_addr_cb"); + let handle_data = get_data_for_req(handle) as + *GetAddrData; + if status == 0i32 { + if res != (ptr::null::<addrinfo>()) { + let mut out_vec = ~[]; + log(debug, fmt!("initial addrinfo: %?", res)); + let mut curr_addr = res; + loop { + let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) { + Ipv4(copy(( + *ll::addrinfo_as_sockaddr_in(curr_addr)))) + } + else if ll::is_ipv6_addrinfo(curr_addr) { + Ipv6(copy(( + *ll::addrinfo_as_sockaddr_in6(curr_addr)))) + } + else { + log(debug, ~"curr_addr is not of family AF_INET or "+ + ~"AF_INET6. Error."); + (*handle_data).output_ch.send( + result::Err(GetAddrUnknownError)); + break; + }; + out_vec.push(move new_ip_addr); - let next_addr = ll::get_next_addrinfo(curr_addr); - if next_addr == ptr::null::<addrinfo>() as *addrinfo { - log(debug, ~"null next_addr encountered. no mas"); - break; - } - else { - curr_addr = next_addr; - log(debug, fmt!("next_addr addrinfo: %?", curr_addr)); + let next_addr = ll::get_next_addrinfo(curr_addr); + if next_addr == ptr::null::<addrinfo>() as *addrinfo { + log(debug, ~"null next_addr encountered. no mas"); + break; + } + else { + curr_addr = next_addr; + log(debug, fmt!("next_addr addrinfo: %?", curr_addr)); + } } + log(debug, fmt!("successful process addrinfo result, len: %?", + vec::len(out_vec))); + (*handle_data).output_ch.send(result::Ok(move out_vec)); + } + else { + log(debug, ~"addrinfo pointer is NULL"); + (*handle_data).output_ch.send( + result::Err(GetAddrUnknownError)); } - log(debug, fmt!("successful process addrinfo result, len: %?", - vec::len(out_vec))); - (*handle_data).output_ch.send(result::Ok(move out_vec)); } else { - log(debug, ~"addrinfo pointer is NULL"); + log(debug, ~"status != 0 error in get_addr_cb"); (*handle_data).output_ch.send( result::Err(GetAddrUnknownError)); } + if res != (ptr::null::<addrinfo>()) { + uv_freeaddrinfo(res); + } + log(debug, ~"leaving get_addr_cb"); } - else { - log(debug, ~"status != 0 error in get_addr_cb"); - (*handle_data).output_ch.send( - result::Err(GetAddrUnknownError)); - } - if res != (ptr::null::<addrinfo>()) { - uv_freeaddrinfo(res); - } - log(debug, ~"leaving get_addr_cb"); } #[cfg(test)] diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 847962c1773..aeb0c2cb613 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -143,124 +143,129 @@ pub enum TcpConnectErrData { */ pub fn connect(input_ip: ip::IpAddr, port: uint, iotask: IoTask) - -> result::Result<TcpSocket, TcpConnectErrData> unsafe { - let result_po = oldcomm::Port::<ConnAttempt>(); - let closed_signal_po = oldcomm::Port::<()>(); - let conn_data = { - result_ch: oldcomm::Chan(&result_po), - closed_signal_ch: oldcomm::Chan(&closed_signal_po) - }; - let conn_data_ptr = ptr::addr_of(&conn_data); - let reader_po = oldcomm::Port::<result::Result<~[u8], TcpErrData>>(); - let stream_handle_ptr = malloc_uv_tcp_t(); - *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t(); - let socket_data = @{ - reader_po: reader_po, - reader_ch: oldcomm::Chan(&reader_po), - stream_handle_ptr: stream_handle_ptr, - connect_req: uv::ll::connect_t(), - write_req: uv::ll::write_t(), - ipv6: match input_ip { - ip::Ipv4(_) => { false } - ip::Ipv6(_) => { true } - }, - iotask: iotask - }; - let socket_data_ptr = ptr::addr_of(&(*socket_data)); - log(debug, fmt!("tcp_connect result_ch %?", conn_data.result_ch)); - // get an unsafe representation of our stream_handle_ptr that - // we can send into the interact cb to be handled in libuv.. - log(debug, fmt!("stream_handle_ptr outside interact %?", - stream_handle_ptr)); - do iotask::interact(iotask) |move input_ip, loop_ptr| unsafe { - log(debug, ~"in interact cb for tcp client connect.."); - log(debug, fmt!("stream_handle_ptr in interact %?", + -> result::Result<TcpSocket, TcpConnectErrData> { + unsafe { + let result_po = oldcomm::Port::<ConnAttempt>(); + let closed_signal_po = oldcomm::Port::<()>(); + let conn_data = { + result_ch: oldcomm::Chan(&result_po), + closed_signal_ch: oldcomm::Chan(&closed_signal_po) + }; + let conn_data_ptr = ptr::addr_of(&conn_data); + let reader_po = oldcomm::Port::<result::Result<~[u8], TcpErrData>>(); + let stream_handle_ptr = malloc_uv_tcp_t(); + *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t(); + let socket_data = @{ + reader_po: reader_po, + reader_ch: oldcomm::Chan(&reader_po), + stream_handle_ptr: stream_handle_ptr, + connect_req: uv::ll::connect_t(), + write_req: uv::ll::write_t(), + ipv6: match input_ip { + ip::Ipv4(_) => { false } + ip::Ipv6(_) => { true } + }, + iotask: iotask + }; + let socket_data_ptr = ptr::addr_of(&(*socket_data)); + log(debug, fmt!("tcp_connect result_ch %?", conn_data.result_ch)); + // get an unsafe representation of our stream_handle_ptr that + // we can send into the interact cb to be handled in libuv.. + log(debug, fmt!("stream_handle_ptr outside interact %?", stream_handle_ptr)); - match uv::ll::tcp_init( loop_ptr, stream_handle_ptr) { - 0i32 => { - log(debug, ~"tcp_init successful"); - log(debug, ~"dealing w/ ipv4 connection.."); - let connect_req_ptr = - ptr::addr_of(&((*socket_data_ptr).connect_req)); - let addr_str = ip::format_addr(&input_ip); - let connect_result = match input_ip { - ip::Ipv4(ref addr) => { - // have to "recreate" the sockaddr_in/6 - // since the ip_addr discards the port - // info.. should probably add an additional - // rust type that actually is closer to - // what the libuv API expects (ip str + port num) - log(debug, fmt!("addr: %?", addr)); - let in_addr = uv::ll::ip4_addr(addr_str, port as int); - uv::ll::tcp_connect( - connect_req_ptr, - stream_handle_ptr, - ptr::addr_of(&in_addr), - tcp_connect_on_connect_cb) - } - ip::Ipv6(ref addr) => { - log(debug, fmt!("addr: %?", addr)); - let in_addr = uv::ll::ip6_addr(addr_str, port as int); - uv::ll::tcp_connect6( - connect_req_ptr, - stream_handle_ptr, - ptr::addr_of(&in_addr), - tcp_connect_on_connect_cb) - } - }; - match connect_result { - 0i32 => { - log(debug, ~"tcp_connect successful"); - // reusable data that we'll have for the - // duration.. - uv::ll::set_data_for_uv_handle(stream_handle_ptr, - socket_data_ptr as - *libc::c_void); - // just so the connect_cb can send the - // outcome.. - uv::ll::set_data_for_req(connect_req_ptr, - conn_data_ptr); - log(debug, ~"leaving tcp_connect interact cb..."); - // let tcp_connect_on_connect_cb send on - // the result_ch, now.. - } - _ => { - // immediate connect failure.. probably a garbage - // ip or somesuch - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send((*conn_data_ptr).result_ch, - ConnFailure(err_data.to_tcp_err())); - uv::ll::set_data_for_uv_handle(stream_handle_ptr, - conn_data_ptr); - uv::ll::close(stream_handle_ptr, stream_error_close_cb); - } + do iotask::interact(iotask) |move input_ip, loop_ptr| { + unsafe { + log(debug, ~"in interact cb for tcp client connect.."); + log(debug, fmt!("stream_handle_ptr in interact %?", + stream_handle_ptr)); + match uv::ll::tcp_init( loop_ptr, stream_handle_ptr) { + 0i32 => { + log(debug, ~"tcp_init successful"); + log(debug, ~"dealing w/ ipv4 connection.."); + let connect_req_ptr = + ptr::addr_of(&((*socket_data_ptr).connect_req)); + let addr_str = ip::format_addr(&input_ip); + let connect_result = match input_ip { + ip::Ipv4(ref addr) => { + // have to "recreate" the sockaddr_in/6 + // since the ip_addr discards the port + // info.. should probably add an additional + // rust type that actually is closer to + // what the libuv API expects (ip str + port num) + log(debug, fmt!("addr: %?", addr)); + let in_addr = uv::ll::ip4_addr(addr_str, port as int); + uv::ll::tcp_connect( + connect_req_ptr, + stream_handle_ptr, + ptr::addr_of(&in_addr), + tcp_connect_on_connect_cb) + } + ip::Ipv6(ref addr) => { + log(debug, fmt!("addr: %?", addr)); + let in_addr = uv::ll::ip6_addr(addr_str, port as int); + uv::ll::tcp_connect6( + connect_req_ptr, + stream_handle_ptr, + ptr::addr_of(&in_addr), + tcp_connect_on_connect_cb) + } + }; + match connect_result { + 0i32 => { + log(debug, ~"tcp_connect successful"); + // reusable data that we'll have for the + // duration.. + uv::ll::set_data_for_uv_handle(stream_handle_ptr, + socket_data_ptr as + *libc::c_void); + // just so the connect_cb can send the + // outcome.. + uv::ll::set_data_for_req(connect_req_ptr, + conn_data_ptr); + log(debug, ~"leaving tcp_connect interact cb..."); + // let tcp_connect_on_connect_cb send on + // the result_ch, now.. + } + _ => { + // immediate connect failure.. probably a garbage + // ip or somesuch + let err_data = uv::ll::get_last_err_data(loop_ptr); + oldcomm::send((*conn_data_ptr).result_ch, + ConnFailure(err_data.to_tcp_err())); + uv::ll::set_data_for_uv_handle(stream_handle_ptr, + conn_data_ptr); + uv::ll::close(stream_handle_ptr, + stream_error_close_cb); + } + } + } + _ => { + // failure to create a tcp handle + let err_data = uv::ll::get_last_err_data(loop_ptr); + oldcomm::send((*conn_data_ptr).result_ch, + ConnFailure(err_data.to_tcp_err())); + } + } } - } - _ => { - // failure to create a tcp handle - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send((*conn_data_ptr).result_ch, - ConnFailure(err_data.to_tcp_err())); + }; + match oldcomm::recv(result_po) { + ConnSuccess => { + log(debug, ~"tcp::connect - received success on result_po"); + result::Ok(TcpSocket(socket_data)) + } + ConnFailure(ref err_data) => { + oldcomm::recv(closed_signal_po); + log(debug, ~"tcp::connect - received failure on result_po"); + // still have to free the malloc'd stream handle.. + rustrt::rust_uv_current_kernel_free(stream_handle_ptr + as *libc::c_void); + let tcp_conn_err = match err_data.err_name { + ~"ECONNREFUSED" => ConnectionRefused, + _ => GenericConnectErr(err_data.err_name, err_data.err_msg) + }; + result::Err(tcp_conn_err) } } - }; - match oldcomm::recv(result_po) { - ConnSuccess => { - log(debug, ~"tcp::connect - received success on result_po"); - result::Ok(TcpSocket(socket_data)) - } - ConnFailure(ref err_data) => { - oldcomm::recv(closed_signal_po); - log(debug, ~"tcp::connect - received failure on result_po"); - // still have to free the malloc'd stream handle.. - rustrt::rust_uv_current_kernel_free(stream_handle_ptr - as *libc::c_void); - let tcp_conn_err = match err_data.err_name { - ~"ECONNREFUSED" => ConnectionRefused, - _ => GenericConnectErr(err_data.err_name, err_data.err_msg) - }; - result::Err(tcp_conn_err) - } } } @@ -279,9 +284,11 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, * `tcp_err_data` value as the `err` variant */ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) - -> result::Result<(), TcpErrData> unsafe { - let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); - write_common_impl(socket_data_ptr, raw_write_data) + -> result::Result<(), TcpErrData> { + unsafe { + let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); + write_common_impl(socket_data_ptr, raw_write_data) + } } /** @@ -316,11 +323,13 @@ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) * value as the `err` variant */ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8]) - -> future::Future<result::Result<(), TcpErrData>> unsafe { - let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); - do future_spawn { - let data_copy = copy(raw_write_data); - write_common_impl(socket_data_ptr, data_copy) + -> future::Future<result::Result<(), TcpErrData>> { + unsafe { + let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); + do future_spawn { + let data_copy = copy(raw_write_data); + write_common_impl(socket_data_ptr, data_copy) + } } } @@ -341,9 +350,11 @@ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8]) */ pub fn read_start(sock: &TcpSocket) -> result::Result<oldcomm::Port< - result::Result<~[u8], TcpErrData>>, TcpErrData> unsafe { - let socket_data = ptr::addr_of(&(*(sock.socket_data))); - read_start_common_impl(socket_data) + result::Result<~[u8], TcpErrData>>, TcpErrData> { + unsafe { + let socket_data = ptr::addr_of(&(*(sock.socket_data))); + read_start_common_impl(socket_data) + } } /** @@ -355,10 +366,13 @@ pub fn read_start(sock: &TcpSocket) */ pub fn read_stop(sock: &TcpSocket, read_port: oldcomm::Port<result::Result<~[u8], TcpErrData>>) -> - result::Result<(), TcpErrData> unsafe { - log(debug, fmt!("taking the read_port out of commission %?", read_port)); - let socket_data = ptr::addr_of(&(*sock.socket_data)); - read_stop_common_impl(socket_data) + result::Result<(), TcpErrData> { + unsafe { + log(debug, + fmt!("taking the read_port out of commission %?", read_port)); + let socket_data = ptr::addr_of(&(*sock.socket_data)); + read_stop_common_impl(socket_data) + } } /** @@ -489,73 +503,74 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint) * as the `err` variant of a `result`. */ pub fn accept(new_conn: TcpNewConnection) - -> result::Result<TcpSocket, TcpErrData> unsafe { - - match new_conn{ - NewTcpConn(server_handle_ptr) => { - let server_data_ptr = uv::ll::get_data_for_uv_handle( - server_handle_ptr) as *TcpListenFcData; - let reader_po = oldcomm::Port(); - let iotask = (*server_data_ptr).iotask; - let stream_handle_ptr = malloc_uv_tcp_t(); - *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t(); - let client_socket_data = @{ - reader_po: reader_po, - reader_ch: oldcomm::Chan(&reader_po), - stream_handle_ptr : stream_handle_ptr, - connect_req : uv::ll::connect_t(), - write_req : uv::ll::write_t(), - ipv6: (*server_data_ptr).ipv6, - iotask : iotask - }; - let client_socket_data_ptr = ptr::addr_of(&(*client_socket_data)); - let client_stream_handle_ptr = - (*client_socket_data_ptr).stream_handle_ptr; - - let result_po = oldcomm::Port::<Option<TcpErrData>>(); - let result_ch = oldcomm::Chan(&result_po); - - // UNSAFE LIBUV INTERACTION BEGIN - // .. normally this happens within the context of - // a call to uv::hl::interact.. but we're breaking - // the rules here because this always has to be - // called within the context of a listen() new_connect_cb - // callback (or it will likely fail and drown your cat) - log(debug, ~"in interact cb for tcp::accept"); - let loop_ptr = uv::ll::get_loop_for_uv_handle( - server_handle_ptr); - match uv::ll::tcp_init(loop_ptr, client_stream_handle_ptr) { - 0i32 => { - log(debug, ~"uv_tcp_init successful for client stream"); - match uv::ll::accept( - server_handle_ptr as *libc::c_void, - client_stream_handle_ptr as *libc::c_void) { + -> result::Result<TcpSocket, TcpErrData> { + unsafe { + match new_conn { + NewTcpConn(server_handle_ptr) => { + let server_data_ptr = uv::ll::get_data_for_uv_handle( + server_handle_ptr) as *TcpListenFcData; + let reader_po = oldcomm::Port(); + let iotask = (*server_data_ptr).iotask; + let stream_handle_ptr = malloc_uv_tcp_t(); + *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t(); + let client_socket_data = @{ + reader_po: reader_po, + reader_ch: oldcomm::Chan(&reader_po), + stream_handle_ptr : stream_handle_ptr, + connect_req : uv::ll::connect_t(), + write_req : uv::ll::write_t(), + ipv6: (*server_data_ptr).ipv6, + iotask : iotask + }; + let client_socket_data_ptr = ptr::addr_of(&(*client_socket_data)); + let client_stream_handle_ptr = + (*client_socket_data_ptr).stream_handle_ptr; + + let result_po = oldcomm::Port::<Option<TcpErrData>>(); + let result_ch = oldcomm::Chan(&result_po); + + // UNSAFE LIBUV INTERACTION BEGIN + // .. normally this happens within the context of + // a call to uv::hl::interact.. but we're breaking + // the rules here because this always has to be + // called within the context of a listen() new_connect_cb + // callback (or it will likely fail and drown your cat) + log(debug, ~"in interact cb for tcp::accept"); + let loop_ptr = uv::ll::get_loop_for_uv_handle( + server_handle_ptr); + match uv::ll::tcp_init(loop_ptr, client_stream_handle_ptr) { 0i32 => { - log(debug, ~"successfully accepted client connection"); - uv::ll::set_data_for_uv_handle(client_stream_handle_ptr, - client_socket_data_ptr - as *libc::c_void); - oldcomm::send(result_ch, None); + log(debug, ~"uv_tcp_init successful for client stream"); + match uv::ll::accept( + server_handle_ptr as *libc::c_void, + client_stream_handle_ptr as *libc::c_void) { + 0i32 => { + log(debug, ~"successfully accepted client connection"); + uv::ll::set_data_for_uv_handle(client_stream_handle_ptr, + client_socket_data_ptr + as *libc::c_void); + oldcomm::send(result_ch, None); + } + _ => { + log(debug, ~"failed to accept client conn"); + oldcomm::send(result_ch, Some( + uv::ll::get_last_err_data(loop_ptr).to_tcp_err())); + } + } } _ => { - log(debug, ~"failed to accept client conn"); + log(debug, ~"failed to init client stream"); oldcomm::send(result_ch, Some( uv::ll::get_last_err_data(loop_ptr).to_tcp_err())); } } - } - _ => { - log(debug, ~"failed to init client stream"); - oldcomm::send(result_ch, Some( - uv::ll::get_last_err_data(loop_ptr).to_tcp_err())); + // UNSAFE LIBUV INTERACTION END + match oldcomm::recv(result_po) { + Some(copy err_data) => result::Err(err_data), + None => result::Ok(TcpSocket(client_socket_data)) + } } } - // UNSAFE LIBUV INTERACTION END - match oldcomm::recv(result_po) { - Some(copy err_data) => result::Err(err_data), - None => result::Ok(TcpSocket(client_socket_data)) - } - } } } @@ -592,16 +607,21 @@ pub fn listen(host_ip: ip::IpAddr, port: uint, backlog: uint, on_establish_cb: fn~(oldcomm::Chan<Option<TcpErrData>>), new_connect_cb: fn~(TcpNewConnection, oldcomm::Chan<Option<TcpErrData>>)) - -> result::Result<(), TcpListenErrData> unsafe { - do listen_common(move host_ip, port, backlog, iotask, - move on_establish_cb) - // on_connect_cb - |move new_connect_cb, handle| unsafe { - let server_data_ptr = uv::ll::get_data_for_uv_handle(handle) - as *TcpListenFcData; - let new_conn = NewTcpConn(handle); - let kill_ch = (*server_data_ptr).kill_ch; - new_connect_cb(new_conn, kill_ch); + -> result::Result<(), TcpListenErrData> { + unsafe { + do listen_common(move host_ip, port, backlog, iotask, + move on_establish_cb) + // on_connect_cb + |move new_connect_cb, handle| { + unsafe { + let server_data_ptr = + uv::ll::get_data_for_uv_handle(handle) + as *TcpListenFcData; + let new_conn = NewTcpConn(handle); + let kill_ch = (*server_data_ptr).kill_ch; + new_connect_cb(new_conn, kill_ch); + } + } } } @@ -609,129 +629,143 @@ fn listen_common(host_ip: ip::IpAddr, port: uint, backlog: uint, iotask: IoTask, on_establish_cb: fn~(oldcomm::Chan<Option<TcpErrData>>), on_connect_cb: fn~(*uv::ll::uv_tcp_t)) - -> result::Result<(), TcpListenErrData> unsafe { - let stream_closed_po = oldcomm::Port::<()>(); - let kill_po = oldcomm::Port::<Option<TcpErrData>>(); - let kill_ch = oldcomm::Chan(&kill_po); - let server_stream = uv::ll::tcp_t(); - let server_stream_ptr = ptr::addr_of(&server_stream); - let server_data = { - server_stream_ptr: server_stream_ptr, - stream_closed_ch: oldcomm::Chan(&stream_closed_po), - kill_ch: kill_ch, - on_connect_cb: move on_connect_cb, - iotask: iotask, - ipv6: match &host_ip { - &ip::Ipv4(_) => { false } - &ip::Ipv6(_) => { true } - }, - mut active: true - }; - let server_data_ptr = ptr::addr_of(&server_data); - - let setup_result = do oldcomm::listen |setup_ch| { - // this is to address a compiler warning about - // an implicit copy.. it seems that double nested - // will defeat a move sigil, as is done to the host_ip - // arg above.. this same pattern works w/o complaint in - // tcp::connect (because the iotask::interact cb isn't - // nested within a core::comm::listen block) - let loc_ip = copy(host_ip); - do iotask::interact(iotask) |move loc_ip, loop_ptr| unsafe { - match uv::ll::tcp_init(loop_ptr, server_stream_ptr) { - 0i32 => { - uv::ll::set_data_for_uv_handle( - server_stream_ptr, - server_data_ptr); - let addr_str = ip::format_addr(&loc_ip); - let bind_result = match loc_ip { - ip::Ipv4(ref addr) => { - log(debug, fmt!("addr: %?", addr)); - let in_addr = uv::ll::ip4_addr(addr_str, port as int); - uv::ll::tcp_bind(server_stream_ptr, - ptr::addr_of(&in_addr)) - } - ip::Ipv6(ref addr) => { - log(debug, fmt!("addr: %?", addr)); - let in_addr = uv::ll::ip6_addr(addr_str, port as int); - uv::ll::tcp_bind6(server_stream_ptr, - ptr::addr_of(&in_addr)) - } - }; - match bind_result { - 0i32 => { - match uv::ll::listen(server_stream_ptr, - backlog as libc::c_int, - tcp_lfc_on_connection_cb) { - 0i32 => oldcomm::send(setup_ch, None), + -> result::Result<(), TcpListenErrData> { + unsafe { + let stream_closed_po = oldcomm::Port::<()>(); + let kill_po = oldcomm::Port::<Option<TcpErrData>>(); + let kill_ch = oldcomm::Chan(&kill_po); + let server_stream = uv::ll::tcp_t(); + let server_stream_ptr = ptr::addr_of(&server_stream); + let server_data = { + server_stream_ptr: server_stream_ptr, + stream_closed_ch: oldcomm::Chan(&stream_closed_po), + kill_ch: kill_ch, + on_connect_cb: move on_connect_cb, + iotask: iotask, + ipv6: match &host_ip { + &ip::Ipv4(_) => { false } + &ip::Ipv6(_) => { true } + }, + mut active: true + }; + let server_data_ptr = ptr::addr_of(&server_data); + + let setup_result = do oldcomm::listen |setup_ch| { + // this is to address a compiler warning about + // an implicit copy.. it seems that double nested + // will defeat a move sigil, as is done to the host_ip + // arg above.. this same pattern works w/o complaint in + // tcp::connect (because the iotask::interact cb isn't + // nested within a core::comm::listen block) + let loc_ip = copy(host_ip); + do iotask::interact(iotask) |move loc_ip, loop_ptr| { + unsafe { + match uv::ll::tcp_init(loop_ptr, server_stream_ptr) { + 0i32 => { + uv::ll::set_data_for_uv_handle( + server_stream_ptr, + server_data_ptr); + let addr_str = ip::format_addr(&loc_ip); + let bind_result = match loc_ip { + ip::Ipv4(ref addr) => { + log(debug, fmt!("addr: %?", addr)); + let in_addr = uv::ll::ip4_addr(addr_str, + port as int); + uv::ll::tcp_bind(server_stream_ptr, + ptr::addr_of(&in_addr)) + } + ip::Ipv6(ref addr) => { + log(debug, fmt!("addr: %?", addr)); + let in_addr = uv::ll::ip6_addr(addr_str, + port as int); + uv::ll::tcp_bind6(server_stream_ptr, + ptr::addr_of(&in_addr)) + } + }; + match bind_result { + 0i32 => { + match uv::ll::listen(server_stream_ptr, + backlog as libc::c_int, + tcp_lfc_on_connection_cb) { + 0i32 => oldcomm::send(setup_ch, None), + _ => { + log(debug, ~"failure to uv_listen()"); + let err_data = uv::ll::get_last_err_data( + loop_ptr); + oldcomm::send(setup_ch, Some(err_data)); + } + } + } + _ => { + log(debug, ~"failure to uv_tcp_bind"); + let err_data = uv::ll::get_last_err_data( + loop_ptr); + oldcomm::send(setup_ch, Some(err_data)); + } + } + } _ => { - log(debug, ~"failure to uv_listen()"); + log(debug, ~"failure to uv_tcp_init"); let err_data = uv::ll::get_last_err_data(loop_ptr); oldcomm::send(setup_ch, Some(err_data)); } } - } - _ => { - log(debug, ~"failure to uv_tcp_bind"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send(setup_ch, Some(err_data)); - } + }; + } + setup_ch.recv() + }; + match setup_result { + Some(ref err_data) => { + do iotask::interact(iotask) |loop_ptr| { + unsafe { + log(debug, + fmt!("tcp::listen post-kill recv hl interact %?", + loop_ptr)); + (*server_data_ptr).active = false; + uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); } + }; + stream_closed_po.recv(); + match err_data.err_name { + ~"EACCES" => { + log(debug, ~"Got EACCES error"); + result::Err(AccessDenied) + } + ~"EADDRINUSE" => { + log(debug, ~"Got EADDRINUSE error"); + result::Err(AddressInUse) } _ => { - log(debug, ~"failure to uv_tcp_init"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send(setup_ch, Some(err_data)); + log(debug, fmt!("Got '%s' '%s' libuv error", + err_data.err_name, err_data.err_msg)); + result::Err( + GenericListenErr(err_data.err_name, err_data.err_msg)) } } - }; - setup_ch.recv() - }; - match setup_result { - Some(ref err_data) => { - do iotask::interact(iotask) |loop_ptr| unsafe { - log(debug, fmt!("tcp::listen post-kill recv hl interact %?", - loop_ptr)); - (*server_data_ptr).active = false; - uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); - }; - stream_closed_po.recv(); - match err_data.err_name { - ~"EACCES" => { - log(debug, ~"Got EACCES error"); - result::Err(AccessDenied) } - ~"EADDRINUSE" => { - log(debug, ~"Got EADDRINUSE error"); - result::Err(AddressInUse) - } - _ => { - log(debug, fmt!("Got '%s' '%s' libuv error", - err_data.err_name, err_data.err_msg)); - result::Err( - GenericListenErr(err_data.err_name, err_data.err_msg)) + None => { + on_establish_cb(kill_ch); + let kill_result = oldcomm::recv(kill_po); + do iotask::interact(iotask) |loop_ptr| { + unsafe { + log(debug, + fmt!("tcp::listen post-kill recv hl interact %?", + loop_ptr)); + (*server_data_ptr).active = false; + uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); + } + }; + stream_closed_po.recv(); + match kill_result { + // some failure post bind/listen + Some(ref err_data) => result::Err(GenericListenErr( + err_data.err_name, + err_data.err_msg)), + // clean exit + None => result::Ok(()) + } } } - } - None => { - on_establish_cb(kill_ch); - let kill_result = oldcomm::recv(kill_po); - do iotask::interact(iotask) |loop_ptr| unsafe { - log(debug, fmt!("tcp::listen post-kill recv hl interact %?", - loop_ptr)); - (*server_data_ptr).active = false; - uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); - }; - stream_closed_po.recv(); - match kill_result { - // some failure post bind/listen - Some(ref err_data) => result::Err(GenericListenErr( - err_data.err_name, - err_data.err_msg)), - // clean exit - None => result::Ok(()) - } - } } } @@ -859,15 +893,20 @@ impl TcpSocketBuf: io::Reader { /// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket` impl TcpSocketBuf: io::Writer { - pub fn write(&self, data: &[const u8]) unsafe { - let socket_data_ptr = - ptr::addr_of(&(*((*(self.data)).sock).socket_data)); - let w_result = write_common_impl(socket_data_ptr, - vec::slice(data, 0, vec::len(data))); - if w_result.is_err() { - let err_data = w_result.get_err(); - log(debug, fmt!("ERROR sock_buf as io::writer.writer err: %? %?", - err_data.err_name, err_data.err_msg)); + pub fn write(&self, data: &[const u8]) { + unsafe { + let socket_data_ptr = + ptr::addr_of(&(*((*(self.data)).sock).socket_data)); + let w_result = write_common_impl(socket_data_ptr, + vec::slice(data, + 0, + vec::len(data))); + if w_result.is_err() { + let err_data = w_result.get_err(); + log(debug, + fmt!("ERROR sock_buf as io::writer.writer err: %? %?", + err_data.err_name, err_data.err_msg)); + } } } fn seek(&self, dist: int, seek: io::SeekStyle) { @@ -887,122 +926,140 @@ impl TcpSocketBuf: io::Writer { // INTERNAL API -fn tear_down_socket_data(socket_data: @TcpSocketData) unsafe { - let closed_po = oldcomm::Port::<()>(); - let closed_ch = oldcomm::Chan(&closed_po); - let close_data = { - closed_ch: closed_ch - }; - let close_data_ptr = ptr::addr_of(&close_data); - let stream_handle_ptr = (*socket_data).stream_handle_ptr; - do iotask::interact((*socket_data).iotask) |loop_ptr| unsafe { - log(debug, fmt!("interact dtor for tcp_socket stream %? loop %?", - stream_handle_ptr, loop_ptr)); - uv::ll::set_data_for_uv_handle(stream_handle_ptr, - close_data_ptr); - uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); - }; - oldcomm::recv(closed_po); - //the line below will most likely crash - //log(debug, fmt!("about to free socket_data at %?", socket_data)); - rustrt::rust_uv_current_kernel_free(stream_handle_ptr - as *libc::c_void); - log(debug, ~"exiting dtor for tcp_socket"); +fn tear_down_socket_data(socket_data: @TcpSocketData) { + unsafe { + let closed_po = oldcomm::Port::<()>(); + let closed_ch = oldcomm::Chan(&closed_po); + let close_data = { + closed_ch: closed_ch + }; + let close_data_ptr = ptr::addr_of(&close_data); + let stream_handle_ptr = (*socket_data).stream_handle_ptr; + do iotask::interact((*socket_data).iotask) |loop_ptr| { + unsafe { + log(debug, + fmt!("interact dtor for tcp_socket stream %? loop %?", + stream_handle_ptr, loop_ptr)); + uv::ll::set_data_for_uv_handle(stream_handle_ptr, + close_data_ptr); + uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); + } + }; + oldcomm::recv(closed_po); + //the line below will most likely crash + //log(debug, fmt!("about to free socket_data at %?", socket_data)); + rustrt::rust_uv_current_kernel_free(stream_handle_ptr + as *libc::c_void); + log(debug, ~"exiting dtor for tcp_socket"); + } } // shared implementation for tcp::read fn read_common_impl(socket_data: *TcpSocketData, timeout_msecs: uint) - -> result::Result<~[u8],TcpErrData> unsafe { - use timer; - - log(debug, ~"starting tcp::read"); - let iotask = (*socket_data).iotask; - let rs_result = read_start_common_impl(socket_data); - if result::is_err(&rs_result) { - let err_data = result::get_err(&rs_result); - result::Err(err_data) - } - else { - log(debug, ~"tcp::read before recv_timeout"); - let read_result = if timeout_msecs > 0u { - timer::recv_timeout( - iotask, timeout_msecs, result::get(&rs_result)) - } else { - Some(oldcomm::recv(result::get(&rs_result))) - }; - log(debug, ~"tcp::read after recv_timeout"); - match move read_result { - None => { - log(debug, ~"tcp::read: timed out.."); - let err_data = { - err_name: ~"TIMEOUT", - err_msg: ~"req timed out" - }; - read_stop_common_impl(socket_data); + -> result::Result<~[u8],TcpErrData> { + unsafe { + use timer; + + log(debug, ~"starting tcp::read"); + let iotask = (*socket_data).iotask; + let rs_result = read_start_common_impl(socket_data); + if result::is_err(&rs_result) { + let err_data = result::get_err(&rs_result); result::Err(err_data) - } - Some(move data_result) => { - log(debug, ~"tcp::read got data"); - read_stop_common_impl(socket_data); - data_result - } + } + else { + log(debug, ~"tcp::read before recv_timeout"); + let read_result = if timeout_msecs > 0u { + timer::recv_timeout( + iotask, timeout_msecs, result::get(&rs_result)) + } else { + Some(oldcomm::recv(result::get(&rs_result))) + }; + log(debug, ~"tcp::read after recv_timeout"); + match move read_result { + None => { + log(debug, ~"tcp::read: timed out.."); + let err_data = { + err_name: ~"TIMEOUT", + err_msg: ~"req timed out" + }; + read_stop_common_impl(socket_data); + result::Err(err_data) + } + Some(move data_result) => { + log(debug, ~"tcp::read got data"); + read_stop_common_impl(socket_data); + data_result + } + } } } } // shared impl for read_stop fn read_stop_common_impl(socket_data: *TcpSocketData) -> - result::Result<(), TcpErrData> unsafe { - let stream_handle_ptr = (*socket_data).stream_handle_ptr; - let stop_po = oldcomm::Port::<Option<TcpErrData>>(); - let stop_ch = oldcomm::Chan(&stop_po); - do iotask::interact((*socket_data).iotask) |loop_ptr| unsafe { - log(debug, ~"in interact cb for tcp::read_stop"); - match uv::ll::read_stop(stream_handle_ptr as *uv::ll::uv_stream_t) { - 0i32 => { - log(debug, ~"successfully called uv_read_stop"); - oldcomm::send(stop_ch, None); - } - _ => { - log(debug, ~"failure in calling uv_read_stop"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send(stop_ch, Some(err_data.to_tcp_err())); - } + result::Result<(), TcpErrData> { + unsafe { + let stream_handle_ptr = (*socket_data).stream_handle_ptr; + let stop_po = oldcomm::Port::<Option<TcpErrData>>(); + let stop_ch = oldcomm::Chan(&stop_po); + do iotask::interact((*socket_data).iotask) |loop_ptr| { + unsafe { + log(debug, ~"in interact cb for tcp::read_stop"); + match uv::ll::read_stop(stream_handle_ptr as + *uv::ll::uv_stream_t) { + 0i32 => { + log(debug, ~"successfully called uv_read_stop"); + oldcomm::send(stop_ch, None); + } + _ => { + log(debug, ~"failure in calling uv_read_stop"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + oldcomm::send(stop_ch, Some(err_data.to_tcp_err())); + } + } + } + }; + match oldcomm::recv(stop_po) { + Some(ref err_data) => result::Err(err_data.to_tcp_err()), + None => result::Ok(()) } - }; - match oldcomm::recv(stop_po) { - Some(ref err_data) => result::Err(err_data.to_tcp_err()), - None => result::Ok(()) } } // shared impl for read_start fn read_start_common_impl(socket_data: *TcpSocketData) -> result::Result<oldcomm::Port< - result::Result<~[u8], TcpErrData>>, TcpErrData> unsafe { - let stream_handle_ptr = (*socket_data).stream_handle_ptr; - let start_po = oldcomm::Port::<Option<uv::ll::uv_err_data>>(); - let start_ch = oldcomm::Chan(&start_po); - log(debug, ~"in tcp::read_start before interact loop"); - do iotask::interact((*socket_data).iotask) |loop_ptr| unsafe { - log(debug, fmt!("in tcp::read_start interact cb %?", loop_ptr)); - match uv::ll::read_start(stream_handle_ptr as *uv::ll::uv_stream_t, - on_alloc_cb, - on_tcp_read_cb) { - 0i32 => { - log(debug, ~"success doing uv_read_start"); - oldcomm::send(start_ch, None); - } - _ => { - log(debug, ~"error attempting uv_read_start"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send(start_ch, Some(err_data)); - } + result::Result<~[u8], TcpErrData>>, TcpErrData> { + unsafe { + let stream_handle_ptr = (*socket_data).stream_handle_ptr; + let start_po = oldcomm::Port::<Option<uv::ll::uv_err_data>>(); + let start_ch = oldcomm::Chan(&start_po); + log(debug, ~"in tcp::read_start before interact loop"); + do iotask::interact((*socket_data).iotask) |loop_ptr| { + unsafe { + log(debug, + fmt!("in tcp::read_start interact cb %?", loop_ptr)); + match uv::ll::read_start(stream_handle_ptr as + *uv::ll::uv_stream_t, + on_alloc_cb, + on_tcp_read_cb) { + 0i32 => { + log(debug, ~"success doing uv_read_start"); + oldcomm::send(start_ch, None); + } + _ => { + log(debug, ~"error attempting uv_read_start"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + oldcomm::send(start_ch, Some(err_data)); + } + } + } + }; + match oldcomm::recv(start_po) { + Some(ref err_data) => result::Err(err_data.to_tcp_err()), + None => result::Ok((*socket_data).reader_po) } - }; - match oldcomm::recv(start_po) { - Some(ref err_data) => result::Err(err_data.to_tcp_err()), - None => result::Ok((*socket_data).reader_po) } } @@ -1011,44 +1068,49 @@ fn read_start_common_impl(socket_data: *TcpSocketData) // shared implementation used by write and write_future fn write_common_impl(socket_data_ptr: *TcpSocketData, raw_write_data: ~[u8]) - -> result::Result<(), TcpErrData> unsafe { - let write_req_ptr = ptr::addr_of(&((*socket_data_ptr).write_req)); - let stream_handle_ptr = - (*socket_data_ptr).stream_handle_ptr; - let write_buf_vec = ~[ uv::ll::buf_init( - vec::raw::to_ptr(raw_write_data), - vec::len(raw_write_data)) ]; - let write_buf_vec_ptr = ptr::addr_of(&write_buf_vec); - let result_po = oldcomm::Port::<TcpWriteResult>(); - let write_data = { - result_ch: oldcomm::Chan(&result_po) - }; - let write_data_ptr = ptr::addr_of(&write_data); - do iotask::interact((*socket_data_ptr).iotask) |loop_ptr| unsafe { - log(debug, fmt!("in interact cb for tcp::write %?", loop_ptr)); - match uv::ll::write(write_req_ptr, - stream_handle_ptr, - write_buf_vec_ptr, - tcp_write_complete_cb) { - 0i32 => { - log(debug, ~"uv_write() invoked successfully"); - uv::ll::set_data_for_req(write_req_ptr, write_data_ptr); - } - _ => { - log(debug, ~"error invoking uv_write()"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - oldcomm::send((*write_data_ptr).result_ch, - TcpWriteError(err_data.to_tcp_err())); - } + -> result::Result<(), TcpErrData> { + unsafe { + let write_req_ptr = ptr::addr_of(&((*socket_data_ptr).write_req)); + let stream_handle_ptr = + (*socket_data_ptr).stream_handle_ptr; + let write_buf_vec = ~[ uv::ll::buf_init( + vec::raw::to_ptr(raw_write_data), + vec::len(raw_write_data)) ]; + let write_buf_vec_ptr = ptr::addr_of(&write_buf_vec); + let result_po = oldcomm::Port::<TcpWriteResult>(); + let write_data = { + result_ch: oldcomm::Chan(&result_po) + }; + let write_data_ptr = ptr::addr_of(&write_data); + do iotask::interact((*socket_data_ptr).iotask) |loop_ptr| { + unsafe { + log(debug, fmt!("in interact cb for tcp::write %?", + loop_ptr)); + match uv::ll::write(write_req_ptr, + stream_handle_ptr, + write_buf_vec_ptr, + tcp_write_complete_cb) { + 0i32 => { + log(debug, ~"uv_write() invoked successfully"); + uv::ll::set_data_for_req(write_req_ptr, write_data_ptr); + } + _ => { + log(debug, ~"error invoking uv_write()"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + oldcomm::send((*write_data_ptr).result_ch, + TcpWriteError(err_data.to_tcp_err())); + } + } + } + }; + // FIXME (#2656): Instead of passing unsafe pointers to local data, + // and waiting here for the write to complete, we should transfer + // ownership of everything to the I/O task and let it deal with the + // aftermath, so we don't have to sit here blocking. + match oldcomm::recv(result_po) { + TcpWriteSuccess => result::Ok(()), + TcpWriteError(ref err_data) => result::Err(err_data.to_tcp_err()) } - }; - // FIXME (#2656): Instead of passing unsafe pointers to local data, - // and waiting here for the write to complete, we should transfer - // ownership of everything to the I/O task and let it deal with the - // aftermath, so we don't have to sit here blocking. - match oldcomm::recv(result_po) { - TcpWriteSuccess => result::Ok(()), - TcpWriteError(ref err_data) => result::Err(err_data.to_tcp_err()) } } @@ -1066,34 +1128,40 @@ type TcpListenFcData = { mut active: bool }; -extern fn tcp_lfc_close_cb(handle: *uv::ll::uv_tcp_t) unsafe { - let server_data_ptr = uv::ll::get_data_for_uv_handle( - handle) as *TcpListenFcData; - oldcomm::send((*server_data_ptr).stream_closed_ch, ()); +extern fn tcp_lfc_close_cb(handle: *uv::ll::uv_tcp_t) { + unsafe { + let server_data_ptr = uv::ll::get_data_for_uv_handle( + handle) as *TcpListenFcData; + oldcomm::send((*server_data_ptr).stream_closed_ch, ()); + } } extern fn tcp_lfc_on_connection_cb(handle: *uv::ll::uv_tcp_t, - status: libc::c_int) unsafe { - let server_data_ptr = uv::ll::get_data_for_uv_handle(handle) - as *TcpListenFcData; - let kill_ch = (*server_data_ptr).kill_ch; - if (*server_data_ptr).active { - match status { - 0i32 => ((*server_data_ptr).on_connect_cb)(handle), - _ => { - let loop_ptr = uv::ll::get_loop_for_uv_handle(handle); - oldcomm::send(kill_ch, - Some(uv::ll::get_last_err_data(loop_ptr) - .to_tcp_err())); - (*server_data_ptr).active = false; - } + status: libc::c_int) { + unsafe { + let server_data_ptr = uv::ll::get_data_for_uv_handle(handle) + as *TcpListenFcData; + let kill_ch = (*server_data_ptr).kill_ch; + if (*server_data_ptr).active { + match status { + 0i32 => ((*server_data_ptr).on_connect_cb)(handle), + _ => { + let loop_ptr = uv::ll::get_loop_for_uv_handle(handle); + oldcomm::send(kill_ch, + Some(uv::ll::get_last_err_data(loop_ptr) + .to_tcp_err())); + (*server_data_ptr).active = false; + } + } } } } -fn malloc_uv_tcp_t() -> *uv::ll::uv_tcp_t unsafe { - rustrt::rust_uv_current_kernel_malloc( - rustrt::rust_uv_helper_uv_tcp_t_size()) as *uv::ll::uv_tcp_t +fn malloc_uv_tcp_t() -> *uv::ll::uv_tcp_t { + unsafe { + rustrt::rust_uv_current_kernel_malloc( + rustrt::rust_uv_helper_uv_tcp_t_size()) as *uv::ll::uv_tcp_t + } } enum TcpConnectResult { @@ -1129,76 +1197,84 @@ impl uv::ll::uv_err_data: ToTcpErr { extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t, nread: libc::ssize_t, - ++buf: uv::ll::uv_buf_t) unsafe { - log(debug, fmt!("entering on_tcp_read_cb stream: %? nread: %?", - stream, nread)); - let loop_ptr = uv::ll::get_loop_for_uv_handle(stream); - let socket_data_ptr = uv::ll::get_data_for_uv_handle(stream) - as *TcpSocketData; - match nread as int { - // incoming err.. probably eof - -1 => { - let err_data = uv::ll::get_last_err_data(loop_ptr).to_tcp_err(); - log(debug, fmt!("on_tcp_read_cb: incoming err.. name %? msg %?", - err_data.err_name, err_data.err_msg)); - let reader_ch = (*socket_data_ptr).reader_ch; - oldcomm::send(reader_ch, result::Err(err_data)); - } - // do nothing .. unneeded buf - 0 => (), - // have data - _ => { - // we have data - log(debug, fmt!("tcp on_read_cb nread: %d", nread as int)); - let reader_ch = (*socket_data_ptr).reader_ch; - let buf_base = uv::ll::get_base_from_buf(buf); - let new_bytes = vec::from_buf(buf_base, nread as uint); - oldcomm::send(reader_ch, result::Ok(new_bytes)); - } + ++buf: uv::ll::uv_buf_t) { + unsafe { + log(debug, fmt!("entering on_tcp_read_cb stream: %? nread: %?", + stream, nread)); + let loop_ptr = uv::ll::get_loop_for_uv_handle(stream); + let socket_data_ptr = uv::ll::get_data_for_uv_handle(stream) + as *TcpSocketData; + match nread as int { + // incoming err.. probably eof + -1 => { + let err_data = uv::ll::get_last_err_data(loop_ptr).to_tcp_err(); + log(debug, fmt!("on_tcp_read_cb: incoming err.. name %? msg %?", + err_data.err_name, err_data.err_msg)); + let reader_ch = (*socket_data_ptr).reader_ch; + oldcomm::send(reader_ch, result::Err(err_data)); + } + // do nothing .. unneeded buf + 0 => (), + // have data + _ => { + // we have data + log(debug, fmt!("tcp on_read_cb nread: %d", nread as int)); + let reader_ch = (*socket_data_ptr).reader_ch; + let buf_base = uv::ll::get_base_from_buf(buf); + let new_bytes = vec::from_buf(buf_base, nread as uint); + oldcomm::send(reader_ch, result::Ok(new_bytes)); + } + } + uv::ll::free_base_of_buf(buf); + log(debug, ~"exiting on_tcp_read_cb"); } - uv::ll::free_base_of_buf(buf); - log(debug, ~"exiting on_tcp_read_cb"); } extern fn on_alloc_cb(handle: *libc::c_void, suggested_size: size_t) - -> uv::ll::uv_buf_t unsafe { - log(debug, ~"tcp read on_alloc_cb!"); - let char_ptr = uv::ll::malloc_buf_base_of(suggested_size); - log(debug, fmt!("tcp read on_alloc_cb h: %? char_ptr: %u sugsize: %u", - handle, - char_ptr as uint, - suggested_size as uint)); - uv::ll::buf_init(char_ptr, suggested_size as uint) + -> uv::ll::uv_buf_t { + unsafe { + log(debug, ~"tcp read on_alloc_cb!"); + let char_ptr = uv::ll::malloc_buf_base_of(suggested_size); + log(debug, fmt!("tcp read on_alloc_cb h: %? char_ptr: %u sugsize: %u", + handle, + char_ptr as uint, + suggested_size as uint)); + uv::ll::buf_init(char_ptr, suggested_size as uint) + } } type TcpSocketCloseData = { closed_ch: oldcomm::Chan<()> }; -extern fn tcp_socket_dtor_close_cb(handle: *uv::ll::uv_tcp_t) unsafe { - let data = uv::ll::get_data_for_uv_handle(handle) - as *TcpSocketCloseData; - let closed_ch = (*data).closed_ch; - oldcomm::send(closed_ch, ()); - log(debug, ~"tcp_socket_dtor_close_cb exiting.."); +extern fn tcp_socket_dtor_close_cb(handle: *uv::ll::uv_tcp_t) { + unsafe { + let data = uv::ll::get_data_for_uv_handle(handle) + as *TcpSocketCloseData; + let closed_ch = (*data).closed_ch; + oldcomm::send(closed_ch, ()); + log(debug, ~"tcp_socket_dtor_close_cb exiting.."); + } } extern fn tcp_write_complete_cb(write_req: *uv::ll::uv_write_t, - status: libc::c_int) unsafe { - let write_data_ptr = uv::ll::get_data_for_req(write_req) - as *WriteReqData; - if status == 0i32 { - log(debug, ~"successful write complete"); - oldcomm::send((*write_data_ptr).result_ch, TcpWriteSuccess); - } else { - let stream_handle_ptr = uv::ll::get_stream_handle_from_write_req( - write_req); - let loop_ptr = uv::ll::get_loop_for_uv_handle(stream_handle_ptr); - let err_data = uv::ll::get_last_err_data(loop_ptr); - log(debug, ~"failure to write"); - oldcomm::send((*write_data_ptr).result_ch, - TcpWriteError(err_data)); + status: libc::c_int) { + unsafe { + let write_data_ptr = uv::ll::get_data_for_req(write_req) + as *WriteReqData; + if status == 0i32 { + log(debug, ~"successful write complete"); + oldcomm::send((*write_data_ptr).result_ch, TcpWriteSuccess); + } else { + let stream_handle_ptr = uv::ll::get_stream_handle_from_write_req( + write_req); + let loop_ptr = uv::ll::get_loop_for_uv_handle(stream_handle_ptr); + let err_data = uv::ll::get_last_err_data(loop_ptr); + log(debug, ~"failure to write"); + oldcomm::send((*write_data_ptr).result_ch, + TcpWriteError(err_data)); + } } } @@ -1211,43 +1287,49 @@ type ConnectReqData = { closed_signal_ch: oldcomm::Chan<()> }; -extern fn stream_error_close_cb(handle: *uv::ll::uv_tcp_t) unsafe { - let data = uv::ll::get_data_for_uv_handle(handle) as - *ConnectReqData; - oldcomm::send((*data).closed_signal_ch, ()); - log(debug, fmt!("exiting steam_error_close_cb for %?", handle)); +extern fn stream_error_close_cb(handle: *uv::ll::uv_tcp_t) { + unsafe { + let data = uv::ll::get_data_for_uv_handle(handle) as + *ConnectReqData; + oldcomm::send((*data).closed_signal_ch, ()); + log(debug, fmt!("exiting steam_error_close_cb for %?", handle)); + } } -extern fn tcp_connect_close_cb(handle: *uv::ll::uv_tcp_t) unsafe { - log(debug, fmt!("closed client tcp handle %?", handle)); +extern fn tcp_connect_close_cb(handle: *uv::ll::uv_tcp_t) { + unsafe { + log(debug, fmt!("closed client tcp handle %?", handle)); + } } extern fn tcp_connect_on_connect_cb(connect_req_ptr: *uv::ll::uv_connect_t, - status: libc::c_int) unsafe { - let conn_data_ptr = (uv::ll::get_data_for_req(connect_req_ptr) - as *ConnectReqData); - let result_ch = (*conn_data_ptr).result_ch; - log(debug, fmt!("tcp_connect result_ch %?", result_ch)); - let tcp_stream_ptr = - uv::ll::get_stream_handle_from_connect_req(connect_req_ptr); - match status { - 0i32 => { - log(debug, ~"successful tcp connection!"); - oldcomm::send(result_ch, ConnSuccess); - } - _ => { - log(debug, ~"error in tcp_connect_on_connect_cb"); - let loop_ptr = uv::ll::get_loop_for_uv_handle(tcp_stream_ptr); - let err_data = uv::ll::get_last_err_data(loop_ptr); - log(debug, fmt!("err_data %? %?", err_data.err_name, - err_data.err_msg)); - oldcomm::send(result_ch, ConnFailure(err_data)); - uv::ll::set_data_for_uv_handle(tcp_stream_ptr, - conn_data_ptr); - uv::ll::close(tcp_stream_ptr, stream_error_close_cb); - } + status: libc::c_int) { + unsafe { + let conn_data_ptr = (uv::ll::get_data_for_req(connect_req_ptr) + as *ConnectReqData); + let result_ch = (*conn_data_ptr).result_ch; + log(debug, fmt!("tcp_connect result_ch %?", result_ch)); + let tcp_stream_ptr = + uv::ll::get_stream_handle_from_connect_req(connect_req_ptr); + match status { + 0i32 => { + log(debug, ~"successful tcp connection!"); + oldcomm::send(result_ch, ConnSuccess); + } + _ => { + log(debug, ~"error in tcp_connect_on_connect_cb"); + let loop_ptr = uv::ll::get_loop_for_uv_handle(tcp_stream_ptr); + let err_data = uv::ll::get_last_err_data(loop_ptr); + log(debug, fmt!("err_data %? %?", err_data.err_name, + err_data.err_msg)); + oldcomm::send(result_ch, ConnFailure(err_data)); + uv::ll::set_data_for_uv_handle(tcp_stream_ptr, + conn_data_ptr); + uv::ll::close(tcp_stream_ptr, stream_error_close_cb); + } + } + log(debug, ~"leaving tcp_connect_on_connect_cb"); } - log(debug, ~"leaving tcp_connect_on_connect_cb"); } enum ConnAttempt { @@ -1298,25 +1380,35 @@ pub mod test { use net::tcp::test::*; #[test] - fn test_gl_tcp_server_and_client_ipv4() unsafe { - use net::tcp::test::tcp_ipv4_server_and_client_test::*; - impl_gl_tcp_ipv4_server_and_client(); + fn test_gl_tcp_server_and_client_ipv4() { + unsafe { + use net::tcp::test::tcp_ipv4_server_and_client_test::*; + impl_gl_tcp_ipv4_server_and_client(); + } } #[test] - fn test_gl_tcp_get_peer_addr() unsafe { - impl_gl_tcp_ipv4_get_peer_addr(); + fn test_gl_tcp_get_peer_addr() { + unsafe { + impl_gl_tcp_ipv4_get_peer_addr(); + } } #[test] - fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { - impl_gl_tcp_ipv4_client_error_connection_refused(); + fn test_gl_tcp_ipv4_client_error_connection_refused() { + unsafe { + impl_gl_tcp_ipv4_client_error_connection_refused(); + } } #[test] - fn test_gl_tcp_server_address_in_use() unsafe { - impl_gl_tcp_ipv4_server_address_in_use(); + fn test_gl_tcp_server_address_in_use() { + unsafe { + impl_gl_tcp_ipv4_server_address_in_use(); + } } #[test] - fn test_gl_tcp_server_access_denied() unsafe { - impl_gl_tcp_ipv4_server_access_denied(); + fn test_gl_tcp_server_access_denied() { + unsafe { + impl_gl_tcp_ipv4_server_access_denied(); + } } // Strange failure on Windows. --pcwalton #[test] @@ -1336,29 +1428,39 @@ pub mod test { #[test] #[ignore(cfg(target_os = "linux"))] - fn test_gl_tcp_server_and_client_ipv4() unsafe { - impl_gl_tcp_ipv4_server_and_client(); + fn test_gl_tcp_server_and_client_ipv4() { + unsafe { + impl_gl_tcp_ipv4_server_and_client(); + } } #[test] #[ignore(cfg(target_os = "linux"))] - fn test_gl_tcp_get_peer_addr() unsafe { - impl_gl_tcp_ipv4_get_peer_addr(); + fn test_gl_tcp_get_peer_addr() { + unsafe { + impl_gl_tcp_ipv4_get_peer_addr(); + } } #[test] #[ignore(cfg(target_os = "linux"))] - fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { - impl_gl_tcp_ipv4_client_error_connection_refused(); + fn test_gl_tcp_ipv4_client_error_connection_refused() { + unsafe { + impl_gl_tcp_ipv4_client_error_connection_refused(); + } } #[test] #[ignore(cfg(target_os = "linux"))] - fn test_gl_tcp_server_address_in_use() unsafe { - impl_gl_tcp_ipv4_server_address_in_use(); + fn test_gl_tcp_server_address_in_use() { + unsafe { + impl_gl_tcp_ipv4_server_address_in_use(); + } } #[test] #[ignore(cfg(target_os = "linux"))] #[ignore(cfg(windows), reason = "deadlocking bots")] - fn test_gl_tcp_server_access_denied() unsafe { - impl_gl_tcp_ipv4_server_access_denied(); + fn test_gl_tcp_server_access_denied() { + unsafe { + impl_gl_tcp_ipv4_server_access_denied(); + } } #[test] #[ignore(cfg(target_os = "linux"))] diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index b7e62f44882..0e352c78611 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -355,20 +355,22 @@ pure fn query_from_str(rawquery: &str) -> Query { return query; } -pub pure fn query_to_str(query: &Query) -> ~str unsafe { - // FIXME(#3722): unsafe only because decode_inner does (string) IO - let mut strvec = ~[]; - for query.each |kv| { - match kv { - &(ref k, ref v) => { - strvec.push(fmt!("%s=%s", - encode_component(*k), - encode_component(*v)) - ); +pub pure fn query_to_str(query: &Query) -> ~str { + unsafe { + // FIXME(#3722): unsafe only because decode_inner does (string) IO + let mut strvec = ~[]; + for query.each |kv| { + match kv { + &(ref k, ref v) => { + strvec.push(fmt!("%s=%s", + encode_component(*k), + encode_component(*v)) + ); + } } } + return str::connect(strvec, ~"&"); } - return str::connect(strvec, ~"&"); } // returns the scheme and the rest of the url, or a parsing error diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index ee78fafb60b..b5b30599d48 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -131,41 +131,46 @@ impl <T: Ord> PriorityQueue<T> { // vector over the junk element. This reduces the constant factor // compared to using swaps, which involves twice as many moves. - priv fn siftup(&mut self, start: uint, pos: uint) unsafe { - let mut pos = pos; - let new = move *addr_of(&self.data[pos]); - - while pos > start { - let parent = (pos - 1) >> 1; - if new > self.data[parent] { - rusti::move_val_init(&mut self.data[pos], - move *addr_of(&self.data[parent])); - pos = parent; - loop + priv fn siftup(&mut self, start: uint, pos: uint) { + unsafe { + let mut pos = pos; + let new = move *addr_of(&self.data[pos]); + + while pos > start { + let parent = (pos - 1) >> 1; + if new > self.data[parent] { + rusti::move_val_init(&mut self.data[pos], + move *addr_of(&self.data[parent])); + pos = parent; + loop + } + break } - break + rusti::move_val_init(&mut self.data[pos], move new); } - rusti::move_val_init(&mut self.data[pos], move new); } - priv fn siftdown_range(&mut self, pos: uint, end: uint) unsafe { - let mut pos = pos; - let start = pos; - let new = move *addr_of(&self.data[pos]); - - let mut child = 2 * pos + 1; - while child < end { - let right = child + 1; - if right < end && !(self.data[child] > self.data[right]) { - child = right; + priv fn siftdown_range(&mut self, pos: uint, end: uint) { + unsafe { + let mut pos = pos; + let start = pos; + let new = move *addr_of(&self.data[pos]); + + let mut child = 2 * pos + 1; + while child < end { + let right = child + 1; + if right < end && !(self.data[child] > self.data[right]) { + child = right; + } + rusti::move_val_init(&mut self.data[pos], + move *addr_of(&self.data[child])); + pos = child; + child = 2 * pos + 1; } - rusti::move_val_init(&mut self.data[pos], - move *addr_of(&self.data[child])); - pos = child; - child = 2 * pos + 1; + + rusti::move_val_init(&mut self.data[pos], move new); + self.siftup(start, pos); } - rusti::move_val_init(&mut self.data[pos], move new); - self.siftup(start, pos); } priv fn siftdown(&mut self, pos: uint) { diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs index 70c7161b4cf..aa8f77d4cd2 100644 --- a/src/libstd/rl.rs +++ b/src/libstd/rl.rs @@ -55,11 +55,13 @@ pub unsafe fn load_history(file: ~str) -> bool { /// Print out a prompt and then wait for input and return it pub unsafe fn read(prompt: ~str) -> Option<~str> { - do str::as_c_str(prompt) |buf| unsafe { - let line = rustrt::linenoise(buf); + do str::as_c_str(prompt) |buf| { + unsafe { + let line = rustrt::linenoise(buf); - if line.is_null() { None } - else { Some(str::raw::from_c_str(line)) } + if line.is_null() { None } + else { Some(str::raw::from_c_str(line)) } + } } } @@ -68,18 +70,23 @@ pub type CompletionCb = fn~(~str, fn(~str)); fn complete_key(_v: @CompletionCb) {} /// Bind to the main completion callback -pub unsafe fn complete(cb: CompletionCb) unsafe { - task::local_data::local_data_set(complete_key, @(move cb)); +pub unsafe fn complete(cb: CompletionCb) { + unsafe { + task::local_data::local_data_set(complete_key, @(move cb)); - extern fn callback(line: *c_char, completions: *()) unsafe { - let cb = copy *task::local_data::local_data_get(complete_key).get(); + extern fn callback(line: *c_char, completions: *()) { + unsafe { + let cb = copy *task::local_data::local_data_get(complete_key) + .get(); - do cb(str::raw::from_c_str(line)) |suggestion| { - do str::as_c_str(suggestion) |buf| { - rustrt::linenoiseAddCompletion(completions, buf); + do cb(str::raw::from_c_str(line)) |suggestion| { + do str::as_c_str(suggestion) |buf| { + rustrt::linenoiseAddCompletion(completions, buf); + } + } } } - } - rustrt::linenoiseSetCompletionCallback(callback); + rustrt::linenoiseSetCompletionCallback(callback); + } } diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index d478970ca9f..c469824f48d 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -176,7 +176,7 @@ pub fn concat(v: ~[Rope]) -> Rope { //Copy `v` into a mut vector let mut len = vec::len(v); if len == 0u { return node::Empty; } - let ropes = vec::to_mut(vec::from_elem(len, v[0])); + let ropes = vec::cast_to_mut(vec::from_elem(len, v[0])); for uint::range(1u, len) |i| { ropes[i] = v[i]; } @@ -720,7 +720,7 @@ pub mod node { //Firstly, split `str` in slices of hint_max_leaf_char_len let mut leaves = uint::div_ceil(char_len, hint_max_leaf_char_len); //Number of leaves - let nodes = vec::to_mut(vec::from_elem(leaves, candidate)); + let nodes = vec::cast_to_mut(vec::from_elem(leaves, candidate)); let mut i = 0u; let mut offset = byte_start; @@ -831,28 +831,30 @@ pub mod node { return forest[0]; } - pub fn serialize_node(node: @Node) -> ~str unsafe { - let mut buf = vec::to_mut(vec::from_elem(byte_len(node), 0u8)); - let mut offset = 0u;//Current position in the buffer - let it = leaf_iterator::start(node); - loop { - match (leaf_iterator::next(&it)) { - option::None => break, - option::Some(x) => { - //FIXME (#2744): Replace with memcpy or something similar - let mut local_buf: ~[u8] = - cast::reinterpret_cast(&*x.content); - let mut i = x.byte_offset; - while i < x.byte_len { - buf[offset] = local_buf[i]; - offset += 1u; - i += 1u; + pub fn serialize_node(node: @Node) -> ~str { + unsafe { + let mut buf = vec::cast_to_mut(vec::from_elem(byte_len(node), 0)); + let mut offset = 0u;//Current position in the buffer + let it = leaf_iterator::start(node); + loop { + match (leaf_iterator::next(&it)) { + option::None => break, + option::Some(x) => { + //FIXME (#2744): Replace with memcpy or something similar + let mut local_buf: ~[u8] = + cast::reinterpret_cast(&*x.content); + let mut i = x.byte_offset; + while i < x.byte_len { + buf[offset] = local_buf[i]; + offset += 1u; + i += 1u; + } + cast::forget(move local_buf); + } } - cast::forget(move local_buf); - } } + return cast::transmute(move buf); } - return cast::transmute(move buf); } /** @@ -862,17 +864,19 @@ pub mod node { * * This function executes in linear time. */ - pub fn flatten(node: @Node) -> @Node unsafe { - match (*node) { - Leaf(_) => return node, - Concat(ref x) => { - return @Leaf({ - byte_offset: 0u, - byte_len: x.byte_len, - char_len: x.char_len, - content: @serialize_node(node) - }) - } + pub fn flatten(node: @Node) -> @Node { + unsafe { + match (*node) { + Leaf(_) => return node, + Concat(ref x) => { + return @Leaf({ + byte_offset: 0u, + byte_len: x.byte_len, + char_len: x.char_len, + content: @serialize_node(node) + }) + } + } } } @@ -1158,7 +1162,8 @@ pub mod node { } pub fn start(node: @Node) -> T { - let stack = vec::to_mut(vec::from_elem(height(node)+1u, node)); + let stack = vec::cast_to_mut( + vec::from_elem(height(node)+1u, node)); return { stack: move stack, mut stackpos: 0 @@ -1283,17 +1288,19 @@ mod tests { node::Empty => return ~"", node::Content(x) => { let str = @mut ~""; - fn aux(str: @mut ~str, node: @node::Node) unsafe { - match (*node) { - node::Leaf(x) => { - *str += str::slice( - *x.content, x.byte_offset, - x.byte_offset + x.byte_len); - } - node::Concat(ref x) => { - aux(str, x.left); - aux(str, x.right); - } + fn aux(str: @mut ~str, node: @node::Node) { + unsafe { + match (*node) { + node::Leaf(x) => { + *str += str::slice( + *x.content, x.byte_offset, + x.byte_offset + x.byte_len); + } + node::Concat(ref x) => { + aux(str, x.left); + aux(str, x.right); + } + } } } aux(str, x); diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index 2fb12460498..7a524eb7985 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -259,13 +259,13 @@ pub fn sha1() -> Sha1 { } } let st = { - h: vec::to_mut(vec::from_elem(digest_buf_len, 0u32)), + h: vec::cast_to_mut(vec::from_elem(digest_buf_len, 0u32)), mut len_low: 0u32, mut len_high: 0u32, - msg_block: vec::to_mut(vec::from_elem(msg_block_len, 0u8)), + msg_block: vec::cast_to_mut(vec::from_elem(msg_block_len, 0u8)), mut msg_block_idx: 0u, mut computed: false, - work_buf: @vec::to_mut(vec::from_elem(work_buf_len, 0u32)) + work_buf: @vec::cast_to_mut(vec::from_elem(work_buf_len, 0u32)) }; let sh = (move st) as Sha1; sh.reset(); @@ -282,97 +282,99 @@ mod tests { use core::vec; #[test] - fn test() unsafe { - type Test = {input: ~str, output: ~[u8]}; + fn test() { + unsafe { + type Test = {input: ~str, output: ~[u8]}; - fn a_million_letter_a() -> ~str { - let mut i = 0; - let mut rs = ~""; - while i < 100000 { - str::push_str(&mut rs, ~"aaaaaaaaaa"); - i += 1; + fn a_million_letter_a() -> ~str { + let mut i = 0; + let mut rs = ~""; + while i < 100000 { + str::push_str(&mut rs, ~"aaaaaaaaaa"); + i += 1; + } + return rs; } - return rs; - } - // Test messages from FIPS 180-1 + // Test messages from FIPS 180-1 - let fips_180_1_tests: ~[Test] = - ~[{input: ~"abc", - output: - ~[0xA9u8, 0x99u8, 0x3Eu8, 0x36u8, - 0x47u8, 0x06u8, 0x81u8, 0x6Au8, - 0xBAu8, 0x3Eu8, 0x25u8, 0x71u8, - 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8, - 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8]}, - {input: - ~"abcdbcdecdefdefgefghfghighij" + - ~"hijkijkljklmklmnlmnomnopnopq", - output: - ~[0x84u8, 0x98u8, 0x3Eu8, 0x44u8, - 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8, - 0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8, - 0xF9u8, 0x51u8, 0x29u8, 0xE5u8, - 0xE5u8, 0x46u8, 0x70u8, 0xF1u8]}, - {input: a_million_letter_a(), - output: - ~[0x34u8, 0xAAu8, 0x97u8, 0x3Cu8, - 0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8, - 0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8, - 0xDBu8, 0xADu8, 0x27u8, 0x31u8, - 0x65u8, 0x34u8, 0x01u8, 0x6Fu8]}]; - // Examples from wikipedia + let fips_180_1_tests: ~[Test] = + ~[{input: ~"abc", + output: + ~[0xA9u8, 0x99u8, 0x3Eu8, 0x36u8, + 0x47u8, 0x06u8, 0x81u8, 0x6Au8, + 0xBAu8, 0x3Eu8, 0x25u8, 0x71u8, + 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8, + 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8]}, + {input: + ~"abcdbcdecdefdefgefghfghighij" + + ~"hijkijkljklmklmnlmnomnopnopq", + output: + ~[0x84u8, 0x98u8, 0x3Eu8, 0x44u8, + 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8, + 0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8, + 0xF9u8, 0x51u8, 0x29u8, 0xE5u8, + 0xE5u8, 0x46u8, 0x70u8, 0xF1u8]}, + {input: a_million_letter_a(), + output: + ~[0x34u8, 0xAAu8, 0x97u8, 0x3Cu8, + 0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8, + 0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8, + 0xDBu8, 0xADu8, 0x27u8, 0x31u8, + 0x65u8, 0x34u8, 0x01u8, 0x6Fu8]}]; + // Examples from wikipedia - let wikipedia_tests: ~[Test] = - ~[{input: ~"The quick brown fox jumps over the lazy dog", - output: - ~[0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8, - 0x7au8, 0x2du8, 0x28u8, 0xfcu8, - 0xedu8, 0x84u8, 0x9eu8, 0xe1u8, - 0xbbu8, 0x76u8, 0xe7u8, 0x39u8, - 0x1bu8, 0x93u8, 0xebu8, 0x12u8]}, - {input: ~"The quick brown fox jumps over the lazy cog", - output: - ~[0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8, - 0xd2u8, 0x5eu8, 0x1bu8, 0x3au8, - 0xfau8, 0xd3u8, 0xe8u8, 0x5au8, - 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8, - 0x10u8, 0x0du8, 0xb4u8, 0xb3u8]}]; - let tests = fips_180_1_tests + wikipedia_tests; - fn check_vec_eq(v0: ~[u8], v1: ~[u8]) { - assert (vec::len::<u8>(v0) == vec::len::<u8>(v1)); - let len = vec::len::<u8>(v0); - let mut i = 0u; - while i < len { - let a = v0[i]; - let b = v1[i]; - assert (a == b); - i += 1u; + let wikipedia_tests: ~[Test] = + ~[{input: ~"The quick brown fox jumps over the lazy dog", + output: + ~[0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8, + 0x7au8, 0x2du8, 0x28u8, 0xfcu8, + 0xedu8, 0x84u8, 0x9eu8, 0xe1u8, + 0xbbu8, 0x76u8, 0xe7u8, 0x39u8, + 0x1bu8, 0x93u8, 0xebu8, 0x12u8]}, + {input: ~"The quick brown fox jumps over the lazy cog", + output: + ~[0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8, + 0xd2u8, 0x5eu8, 0x1bu8, 0x3au8, + 0xfau8, 0xd3u8, 0xe8u8, 0x5au8, + 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8, + 0x10u8, 0x0du8, 0xb4u8, 0xb3u8]}]; + let tests = fips_180_1_tests + wikipedia_tests; + fn check_vec_eq(v0: ~[u8], v1: ~[u8]) { + assert (vec::len::<u8>(v0) == vec::len::<u8>(v1)); + let len = vec::len::<u8>(v0); + let mut i = 0u; + while i < len { + let a = v0[i]; + let b = v1[i]; + assert (a == b); + i += 1u; + } } - } - // Test that it works when accepting the message all at once + // Test that it works when accepting the message all at once - let sh = sha1::sha1(); - for vec::each(tests) |t| { - sh.input_str(t.input); - let out = sh.result(); - check_vec_eq(t.output, out); - sh.reset(); - } + let sh = sha1::sha1(); + for vec::each(tests) |t| { + sh.input_str(t.input); + let out = sh.result(); + check_vec_eq(t.output, out); + sh.reset(); + } - // Test that it works when accepting the message in pieces - for vec::each(tests) |t| { - let len = str::len(t.input); - let mut left = len; - while left > 0u { - let take = (left + 1u) / 2u; - sh.input_str(str::slice(t.input, len - left, - take + len - left)); - left = left - take; + // Test that it works when accepting the message in pieces + for vec::each(tests) |t| { + let len = str::len(t.input); + let mut left = len; + while left > 0u { + let take = (left + 1u) / 2u; + sh.input_str(str::slice(t.input, len - left, + take + len - left)); + left = left - take; + } + let out = sh.result(); + check_vec_eq(t.output, out); + sh.reset(); } - let out = sh.result(); - check_vec_eq(t.output, out); - sh.reset(); } } diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index d83568ddd94..cce3dc725da 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -457,7 +457,7 @@ impl<T: Copy Ord> MergeState<T> { base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; - let tmp = vec::to_mut(vec::slice(array, base1, base1+len1)); + let tmp = vec::cast_to_mut(vec::slice(array, base1, base1+len1)); let mut c1 = 0; let mut c2 = base2; @@ -560,7 +560,7 @@ impl<T: Copy Ord> MergeState<T> { base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; - let tmp = vec::to_mut(vec::slice(array, base2, base2+len2)); + let tmp = vec::cast_to_mut(vec::slice(array, base2, base2+len2)); let mut c1 = base1 + len1 - 1; let mut c2 = len2 - 1; @@ -816,7 +816,7 @@ mod test_qsort { do quick_sort(names) |x, y| { int::le(*x, *y) }; - let immut_names = vec::from_mut(move names); + let immut_names = vec::cast_from_mut(move names); let pairs = vec::zip_slice(expected, immut_names); for vec::each(pairs) |p| { @@ -1025,7 +1025,7 @@ mod big_tests { let res = do vec::from_fn(num) |i| { arr[i % size] }; - vec::to_mut(move res) + vec::cast_to_mut(move res) } fn makeRange(n: uint) -> ~[uint] { @@ -1051,7 +1051,7 @@ mod big_tests { let arr = do vec::from_fn(n) |_i| { rng.gen_float() }; - let arr = vec::to_mut(move arr); + let arr = vec::cast_to_mut(move arr); tim_sort(arr); // *sort isSorted(arr); @@ -1123,7 +1123,7 @@ mod big_tests { let arr = do vec::from_fn(n) |_i| { @rng.gen_float() }; - let arr = vec::to_mut(move arr); + let arr = vec::cast_to_mut(move arr); tim_sort(arr); // *sort isSorted(arr); diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index f12114bfd8e..03ef98d09c5 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -97,7 +97,7 @@ fn new_sem_and_signal(count: int, num_condvars: uint) for num_condvars.times { queues.push(new_waitqueue()); } - new_sem(count, vec::to_mut(move queues)) + new_sem(count, vec::cast_to_mut(move queues)) } #[doc(hidden)] diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index 18c623c2bd8..f8147c532e6 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -49,26 +49,28 @@ pub fn delayed_send<T: Owned>(iotask: IoTask, let timer_done_ch_ptr = ptr::addr_of(&timer_done_ch); let timer = uv::ll::timer_t(); let timer_ptr = ptr::addr_of(&timer); - do iotask::interact(iotask) |loop_ptr| unsafe { - let init_result = uv::ll::timer_init(loop_ptr, timer_ptr); - if (init_result == 0i32) { - let start_result = uv::ll::timer_start( - timer_ptr, delayed_send_cb, msecs, 0u); - if (start_result == 0i32) { - uv::ll::set_data_for_uv_handle( - timer_ptr, - timer_done_ch_ptr as *libc::c_void); - } - else { + do iotask::interact(iotask) |loop_ptr| { + unsafe { + let init_result = uv::ll::timer_init(loop_ptr, timer_ptr); + if (init_result == 0i32) { + let start_result = uv::ll::timer_start( + timer_ptr, delayed_send_cb, msecs, 0u); + if (start_result == 0i32) { + uv::ll::set_data_for_uv_handle( + timer_ptr, + timer_done_ch_ptr as *libc::c_void); + } else { + let error_msg = uv::ll::get_last_err_info( + loop_ptr); + fail ~"timer::delayed_send() start failed: " + + error_msg; + } + } else { let error_msg = uv::ll::get_last_err_info(loop_ptr); - fail ~"timer::delayed_send() start failed: " + + fail ~"timer::delayed_send() init failed: " + error_msg; } } - else { - let error_msg = uv::ll::get_last_err_info(loop_ptr); - fail ~"timer::delayed_send() init failed: "+error_msg; - } }; // delayed_send_cb has been processed by libuv oldcomm::recv(timer_done_po); @@ -138,27 +140,31 @@ pub fn recv_timeout<T: Copy Owned>(iotask: IoTask, // INTERNAL API extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t, - status: libc::c_int) unsafe { - log(debug, fmt!("delayed_send_cb handle %? status %?", handle, status)); - let timer_done_ch = - *(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>); - let stop_result = uv::ll::timer_stop(handle); - if (stop_result == 0i32) { - oldcomm::send(timer_done_ch, ()); - uv::ll::close(handle, delayed_send_close_cb); - } - else { - let loop_ptr = uv::ll::get_loop_for_uv_handle(handle); - let error_msg = uv::ll::get_last_err_info(loop_ptr); - fail ~"timer::sleep() init failed: "+error_msg; + status: libc::c_int) { + unsafe { + log(debug, + fmt!("delayed_send_cb handle %? status %?", handle, status)); + let timer_done_ch = + *(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>); + let stop_result = uv::ll::timer_stop(handle); + if (stop_result == 0i32) { + oldcomm::send(timer_done_ch, ()); + uv::ll::close(handle, delayed_send_close_cb); + } else { + let loop_ptr = uv::ll::get_loop_for_uv_handle(handle); + let error_msg = uv::ll::get_last_err_info(loop_ptr); + fail ~"timer::sleep() init failed: "+error_msg; + } } } -extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) unsafe { - log(debug, fmt!("delayed_send_close_cb handle %?", handle)); - let timer_done_ch = - *(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>); - oldcomm::send(timer_done_ch, ()); +extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) { + unsafe { + log(debug, fmt!("delayed_send_close_cb handle %?", handle)); + let timer_done_ch = + *(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>); + oldcomm::send(timer_done_ch, ()); + } } #[cfg(test)] diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index fd2dab0dadc..95397254171 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -51,14 +51,16 @@ impl <K: Eq Ord, V: Eq> TreeMap<K, V>: Eq { } else { let mut x = self.iter(); let mut y = other.iter(); - for self.len().times unsafe { // unsafe as a purity workaround - // ICE: x.next() != y.next() + for self.len().times { + unsafe { // unsafe as a purity workaround + // ICE: x.next() != y.next() - let (x1, x2) = x.next().unwrap(); - let (y1, y2) = y.next().unwrap(); + let (x1, x2) = x.next().unwrap(); + let (y1, y2) = y.next().unwrap(); - if x1 != y1 || x2 != y2 { - return false + if x1 != y1 || x2 != y2 { + return false + } } } true diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs index 276cb9cab64..3a2c3b7c135 100644 --- a/src/libstd/uv_global_loop.rs +++ b/src/libstd/uv_global_loop.rs @@ -47,55 +47,59 @@ pub fn get() -> IoTask { } #[doc(hidden)] -fn get_monitor_task_gl() -> IoTask unsafe { - - let monitor_loop_chan_ptr = rustrt::rust_uv_get_kernel_global_chan_ptr(); - - debug!("ENTERING global_loop::get() loop chan: %?", - monitor_loop_chan_ptr); - - debug!("before priv::chan_from_global_ptr"); - type MonChan = Chan<IoTask>; - - let monitor_ch = - do chan_from_global_ptr::<MonChan>(monitor_loop_chan_ptr, - || { - task::task().sched_mode - (task::SingleThreaded) - .unlinked() - }) |msg_po| unsafe { - debug!("global monitor task starting"); - - // As a weak task the runtime will notify us when to exit - do weaken_task() |weak_exit_po| { - debug!("global monitor task is now weak"); - let hl_loop = spawn_loop(); - loop { - debug!("in outer_loop..."); - match select2(weak_exit_po, msg_po) { - Left(weak_exit) => { - // all normal tasks have ended, tell the - // libuv loop to tear_down, then exit - debug!("weak_exit_po recv'd msg: %?", weak_exit); - iotask::exit(hl_loop); - break; - } - Right(fetch_ch) => { - debug!("hl_loop req recv'd: %?", fetch_ch); - fetch_ch.send(hl_loop); - } - } +fn get_monitor_task_gl() -> IoTask { + unsafe { + let monitor_loop_chan_ptr = + rustrt::rust_uv_get_kernel_global_chan_ptr(); + + debug!("ENTERING global_loop::get() loop chan: %?", + monitor_loop_chan_ptr); + + debug!("before priv::chan_from_global_ptr"); + type MonChan = Chan<IoTask>; + + let monitor_ch = + do chan_from_global_ptr::<MonChan>(monitor_loop_chan_ptr, + || { + task::task().sched_mode + (task::SingleThreaded) + .unlinked() + }) |msg_po| { + unsafe { + debug!("global monitor task starting"); + + // As a weak task the runtime will notify us when to exit + do weaken_task() |weak_exit_po| { + debug!("global monitor task is now weak"); + let hl_loop = spawn_loop(); + loop { + debug!("in outer_loop..."); + match select2(weak_exit_po, msg_po) { + Left(weak_exit) => { + // all normal tasks have ended, tell the + // libuv loop to tear_down, then exit + debug!("weak_exit_po recv'd msg: %?", weak_exit); + iotask::exit(hl_loop); + break; + } + Right(fetch_ch) => { + debug!("hl_loop req recv'd: %?", fetch_ch); + fetch_ch.send(hl_loop); + } + } + } + debug!("global monitor task is leaving weakend state"); + }; + debug!("global monitor task exiting"); } - debug!("global monitor task is leaving weakend state"); }; - debug!("global monitor task exiting"); - }; - // once we have a chan to the monitor loop, we ask it for - // the libuv loop's async handle - do listen |fetch_ch| { - monitor_ch.send(fetch_ch); - fetch_ch.recv() + // once we have a chan to the monitor loop, we ask it for + // the libuv loop's async handle + do listen |fetch_ch| { + monitor_ch.send(fetch_ch); + fetch_ch.recv() + } } } @@ -135,91 +139,107 @@ mod test { use core::ptr; use core::task; - extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) unsafe { - let exit_ch_ptr = ll::get_data_for_uv_handle( - timer_ptr as *libc::c_void) as *oldcomm::Chan<bool>; - let exit_ch = *exit_ch_ptr; - oldcomm::send(exit_ch, true); - log(debug, fmt!("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?", - exit_ch_ptr)); + extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) { + unsafe { + let exit_ch_ptr = ll::get_data_for_uv_handle( + timer_ptr as *libc::c_void) as *oldcomm::Chan<bool>; + let exit_ch = *exit_ch_ptr; + oldcomm::send(exit_ch, true); + log(debug, + fmt!("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?", + exit_ch_ptr)); + } } extern fn simple_timer_cb(timer_ptr: *ll::uv_timer_t, - _status: libc::c_int) unsafe { - log(debug, ~"in simple timer cb"); - ll::timer_stop(timer_ptr); - let hl_loop = get_gl(); - do iotask::interact(hl_loop) |_loop_ptr| unsafe { - log(debug, ~"closing timer"); - ll::close(timer_ptr, simple_timer_close_cb); - log(debug, ~"about to deref exit_ch_ptr"); - log(debug, ~"after msg sent on deref'd exit_ch"); - }; - log(debug, ~"exiting simple timer cb"); + _status: libc::c_int) { + unsafe { + log(debug, ~"in simple timer cb"); + ll::timer_stop(timer_ptr); + let hl_loop = get_gl(); + do iotask::interact(hl_loop) |_loop_ptr| { + unsafe { + log(debug, ~"closing timer"); + ll::close(timer_ptr, simple_timer_close_cb); + log(debug, ~"about to deref exit_ch_ptr"); + log(debug, ~"after msg sent on deref'd exit_ch"); + } + }; + log(debug, ~"exiting simple timer cb"); + } } - fn impl_uv_hl_simple_timer(iotask: IoTask) unsafe { - let exit_po = oldcomm::Port::<bool>(); - let exit_ch = oldcomm::Chan(&exit_po); - let exit_ch_ptr = ptr::addr_of(&exit_ch); - log(debug, fmt!("EXIT_CH_PTR newly created exit_ch_ptr: %?", - exit_ch_ptr)); - let timer_handle = ll::timer_t(); - let timer_ptr = ptr::addr_of(&timer_handle); - do iotask::interact(iotask) |loop_ptr| unsafe { - log(debug, ~"user code inside interact loop!!!"); - let init_status = ll::timer_init(loop_ptr, timer_ptr); - if(init_status == 0i32) { - ll::set_data_for_uv_handle( - timer_ptr as *libc::c_void, - exit_ch_ptr as *libc::c_void); - let start_status = ll::timer_start(timer_ptr, simple_timer_cb, - 1u, 0u); - if(start_status == 0i32) { - } - else { - fail ~"failure on ll::timer_start()"; + fn impl_uv_hl_simple_timer(iotask: IoTask) { + unsafe { + let exit_po = oldcomm::Port::<bool>(); + let exit_ch = oldcomm::Chan(&exit_po); + let exit_ch_ptr = ptr::addr_of(&exit_ch); + log(debug, fmt!("EXIT_CH_PTR newly created exit_ch_ptr: %?", + exit_ch_ptr)); + let timer_handle = ll::timer_t(); + let timer_ptr = ptr::addr_of(&timer_handle); + do iotask::interact(iotask) |loop_ptr| { + unsafe { + log(debug, ~"user code inside interact loop!!!"); + let init_status = ll::timer_init(loop_ptr, timer_ptr); + if(init_status == 0i32) { + ll::set_data_for_uv_handle( + timer_ptr as *libc::c_void, + exit_ch_ptr as *libc::c_void); + let start_status = ll::timer_start(timer_ptr, + simple_timer_cb, + 1u, + 0u); + if start_status != 0 { + fail ~"failure on ll::timer_start()"; + } + } else { + fail ~"failure on ll::timer_init()"; + } } - } - else { - fail ~"failure on ll::timer_init()"; - } - }; - oldcomm::recv(exit_po); - log(debug, ~"global_loop timer test: msg recv on exit_po, done.."); + }; + oldcomm::recv(exit_po); + log(debug, + ~"global_loop timer test: msg recv on exit_po, done.."); + } } #[test] - fn test_gl_uv_global_loop_high_level_global_timer() unsafe { - let hl_loop = get_gl(); - let exit_po = oldcomm::Port::<()>(); - let exit_ch = oldcomm::Chan(&exit_po); - task::spawn_sched(task::ManualThreads(1u), || { + fn test_gl_uv_global_loop_high_level_global_timer() { + unsafe { + let hl_loop = get_gl(); + let exit_po = oldcomm::Port::<()>(); + let exit_ch = oldcomm::Chan(&exit_po); + task::spawn_sched(task::ManualThreads(1u), || { + impl_uv_hl_simple_timer(hl_loop); + oldcomm::send(exit_ch, ()); + }); impl_uv_hl_simple_timer(hl_loop); - oldcomm::send(exit_ch, ()); - }); - impl_uv_hl_simple_timer(hl_loop); - oldcomm::recv(exit_po); + oldcomm::recv(exit_po); + } } // keeping this test ignored until some kind of stress-test-harness // is set up for the build bots #[test] #[ignore] - fn test_stress_gl_uv_global_loop_high_level_global_timer() unsafe { - let hl_loop = get_gl(); - let exit_po = oldcomm::Port::<()>(); - let exit_ch = oldcomm::Chan(&exit_po); - let cycles = 5000u; - for iter::repeat(cycles) { - task::spawn_sched(task::ManualThreads(1u), || { - impl_uv_hl_simple_timer(hl_loop); - oldcomm::send(exit_ch, ()); - }); - }; - for iter::repeat(cycles) { - oldcomm::recv(exit_po); - }; - log(debug, ~"test_stress_gl_uv_global_loop_high_level_global_timer"+ - ~" exiting sucessfully!"); + fn test_stress_gl_uv_global_loop_high_level_global_timer() { + unsafe { + let hl_loop = get_gl(); + let exit_po = oldcomm::Port::<()>(); + let exit_ch = oldcomm::Chan(&exit_po); + let cycles = 5000u; + for iter::repeat(cycles) { + task::spawn_sched(task::ManualThreads(1u), || { + impl_uv_hl_simple_timer(hl_loop); + oldcomm::send(exit_ch, ()); + }); + }; + for iter::repeat(cycles) { + oldcomm::recv(exit_po); + }; + log(debug, + ~"test_stress_gl_uv_global_loop_high_level_global_timer"+ + ~" exiting sucessfully!"); + } } } diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs index 409d73c2539..667708cfb3f 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libstd/uv_iotask.rs @@ -83,8 +83,10 @@ pub unsafe fn interact(iotask: IoTask, * async handle and do a sanity check to make sure that all other handles are * closed, causing a failure otherwise. */ -pub fn exit(iotask: IoTask) unsafe { - send_msg(iotask, TeardownLoop); +pub fn exit(iotask: IoTask) { + unsafe { + send_msg(iotask, TeardownLoop); + } } @@ -96,38 +98,39 @@ enum IoTaskMsg { } /// Run the loop and begin handling messages -fn run_loop(iotask_ch: Chan<IoTask>) unsafe { - - let loop_ptr = ll::loop_new(); - - // set up the special async handle we'll use to allow multi-task - // communication with this loop - let async = ll::async_t(); - let async_handle = addr_of(&async); - - // associate the async handle with the loop - ll::async_init(loop_ptr, async_handle, wake_up_cb); - - // initialize our loop data and store it in the loop - let data: IoTaskLoopData = { - async_handle: async_handle, - msg_po: Port() - }; - ll::set_data_for_uv_handle(async_handle, addr_of(&data)); - - // Send out a handle through which folks can talk to us - // while we dwell in the I/O loop - let iotask = IoTask_({ - async_handle: async_handle, - op_chan: data.msg_po.chan() - }); - iotask_ch.send(iotask); - - log(debug, ~"about to run uv loop"); - // enter the loop... this blocks until the loop is done.. - ll::run(loop_ptr); - log(debug, ~"uv loop ended"); - ll::loop_delete(loop_ptr); +fn run_loop(iotask_ch: Chan<IoTask>) { + unsafe { + let loop_ptr = ll::loop_new(); + + // set up the special async handle we'll use to allow multi-task + // communication with this loop + let async = ll::async_t(); + let async_handle = addr_of(&async); + + // associate the async handle with the loop + ll::async_init(loop_ptr, async_handle, wake_up_cb); + + // initialize our loop data and store it in the loop + let data: IoTaskLoopData = { + async_handle: async_handle, + msg_po: Port() + }; + ll::set_data_for_uv_handle(async_handle, addr_of(&data)); + + // Send out a handle through which folks can talk to us + // while we dwell in the I/O loop + let iotask = IoTask_({ + async_handle: async_handle, + op_chan: data.msg_po.chan() + }); + iotask_ch.send(iotask); + + log(debug, ~"about to run uv loop"); + // enter the loop... this blocks until the loop is done.. + ll::run(loop_ptr); + log(debug, ~"uv loop ended"); + ll::loop_delete(loop_ptr); + } } // data that lives for the lifetime of the high-evel oo @@ -136,43 +139,51 @@ type IoTaskLoopData = { msg_po: Port<IoTaskMsg> }; -fn send_msg(iotask: IoTask, - msg: IoTaskMsg) unsafe { - iotask.op_chan.send(move msg); - ll::async_send(iotask.async_handle); +fn send_msg(iotask: IoTask, msg: IoTaskMsg) { + unsafe { + iotask.op_chan.send(move msg); + ll::async_send(iotask.async_handle); + } } /// Dispatch all pending messages extern fn wake_up_cb(async_handle: *ll::uv_async_t, - status: int) unsafe { - - log(debug, fmt!("wake_up_cb extern.. handle: %? status: %?", - async_handle, status)); - - let loop_ptr = ll::get_loop_for_uv_handle(async_handle); - let data = ll::get_data_for_uv_handle(async_handle) as *IoTaskLoopData; - let msg_po = (*data).msg_po; - - while msg_po.peek() { - match msg_po.recv() { - Interaction(ref cb) => (*cb)(loop_ptr), - TeardownLoop => begin_teardown(data) + status: int) { + unsafe { + log(debug, fmt!("wake_up_cb extern.. handle: %? status: %?", + async_handle, status)); + + let loop_ptr = ll::get_loop_for_uv_handle(async_handle); + let data = ll::get_data_for_uv_handle(async_handle) + as *IoTaskLoopData; + let msg_po = (*data).msg_po; + + while msg_po.peek() { + match msg_po.recv() { + Interaction(ref cb) => (*cb)(loop_ptr), + TeardownLoop => begin_teardown(data) + } } } } -fn begin_teardown(data: *IoTaskLoopData) unsafe { - log(debug, ~"iotask begin_teardown() called, close async_handle"); - let async_handle = (*data).async_handle; - ll::close(async_handle as *c_void, tear_down_close_cb); +fn begin_teardown(data: *IoTaskLoopData) { + unsafe { + log(debug, ~"iotask begin_teardown() called, close async_handle"); + let async_handle = (*data).async_handle; + ll::close(async_handle as *c_void, tear_down_close_cb); + } } -extern fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe { - let loop_ptr = ll::get_loop_for_uv_handle(handle); - let loop_refs = ll::loop_refcount(loop_ptr); - log(debug, fmt!("tear_down_close_cb called, closing handle at %? refs %?", - handle, loop_refs)); - assert loop_refs == 1i32; +extern fn tear_down_close_cb(handle: *ll::uv_async_t) { + unsafe { + let loop_ptr = ll::get_loop_for_uv_handle(handle); + let loop_refs = ll::loop_refcount(loop_ptr); + log(debug, + fmt!("tear_down_close_cb called, closing handle at %? refs %?", + handle, loop_refs)); + assert loop_refs == 1i32; + } } #[cfg(test)] @@ -188,37 +199,46 @@ mod test { use core::ptr; use core::task; - extern fn async_close_cb(handle: *ll::uv_async_t) unsafe { - log(debug, fmt!("async_close_cb handle %?", handle)); - let exit_ch = (*(ll::get_data_for_uv_handle(handle) - as *AhData)).exit_ch; - oldcomm::send(exit_ch, ()); + extern fn async_close_cb(handle: *ll::uv_async_t) { + unsafe { + log(debug, fmt!("async_close_cb handle %?", handle)); + let exit_ch = (*(ll::get_data_for_uv_handle(handle) + as *AhData)).exit_ch; + oldcomm::send(exit_ch, ()); + } } - extern fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int) + extern fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int) { unsafe { - log(debug, fmt!("async_handle_cb handle %? status %?",handle,status)); - ll::close(handle, async_close_cb); + log(debug, + fmt!("async_handle_cb handle %? status %?",handle,status)); + ll::close(handle, async_close_cb); + } } type AhData = { iotask: IoTask, exit_ch: oldcomm::Chan<()> }; - fn impl_uv_iotask_async(iotask: IoTask) unsafe { - let async_handle = ll::async_t(); - let ah_ptr = ptr::addr_of(&async_handle); - let exit_po = oldcomm::Port::<()>(); - let exit_ch = oldcomm::Chan(&exit_po); - let ah_data = { - iotask: iotask, - exit_ch: exit_ch - }; - let ah_data_ptr = ptr::addr_of(&ah_data); - do interact(iotask) |loop_ptr| unsafe { - ll::async_init(loop_ptr, ah_ptr, async_handle_cb); - ll::set_data_for_uv_handle(ah_ptr, ah_data_ptr as *libc::c_void); - ll::async_send(ah_ptr); - }; - oldcomm::recv(exit_po); + fn impl_uv_iotask_async(iotask: IoTask) { + unsafe { + let async_handle = ll::async_t(); + let ah_ptr = ptr::addr_of(&async_handle); + let exit_po = oldcomm::Port::<()>(); + let exit_ch = oldcomm::Chan(&exit_po); + let ah_data = { + iotask: iotask, + exit_ch: exit_ch + }; + let ah_data_ptr = ptr::addr_of(&ah_data); + do interact(iotask) |loop_ptr| { + unsafe { + ll::async_init(loop_ptr, ah_ptr, async_handle_cb); + ll::set_data_for_uv_handle(ah_ptr, + ah_data_ptr as *libc::c_void); + ll::async_send(ah_ptr); + } + }; + oldcomm::recv(exit_po); + } } // this fn documents the bear minimum neccesary to roll your own @@ -233,8 +253,10 @@ mod test { return oldcomm::recv(iotask_port); } - extern fn lifetime_handle_close(handle: *libc::c_void) unsafe { - log(debug, fmt!("lifetime_handle_close ptr %?", handle)); + extern fn lifetime_handle_close(handle: *libc::c_void) { + unsafe { + log(debug, fmt!("lifetime_handle_close ptr %?", handle)); + } } extern fn lifetime_async_callback(handle: *libc::c_void, @@ -244,31 +266,33 @@ mod test { } #[test] - fn test_uv_iotask_async() unsafe { - let exit_po = oldcomm::Port::<()>(); - let exit_ch = oldcomm::Chan(&exit_po); - let iotask = spawn_test_loop(exit_ch); - - // using this handle to manage the lifetime of the high_level_loop, - // as it will exit the first time one of the impl_uv_hl_async() is - // cleaned up with no one ref'd handles on the loop (Which can happen - // under race-condition type situations.. this ensures that the loop - // lives until, at least, all of the impl_uv_hl_async() runs have been - // called, at least. - let work_exit_po = oldcomm::Port::<()>(); - let work_exit_ch = oldcomm::Chan(&work_exit_po); - for iter::repeat(7u) { - do task::spawn_sched(task::ManualThreads(1u)) { - impl_uv_iotask_async(iotask); - oldcomm::send(work_exit_ch, ()); + fn test_uv_iotask_async() { + unsafe { + let exit_po = oldcomm::Port::<()>(); + let exit_ch = oldcomm::Chan(&exit_po); + let iotask = spawn_test_loop(exit_ch); + + // using this handle to manage the lifetime of the + // high_level_loop, as it will exit the first time one of the + // impl_uv_hl_async() is cleaned up with no one ref'd handles on + // the loop (Which can happen under race-condition type + // situations.. this ensures that the loop lives until, at least, + // all of the impl_uv_hl_async() runs have been called, at least. + let work_exit_po = oldcomm::Port::<()>(); + let work_exit_ch = oldcomm::Chan(&work_exit_po); + for iter::repeat(7u) { + do task::spawn_sched(task::ManualThreads(1u)) { + impl_uv_iotask_async(iotask); + oldcomm::send(work_exit_ch, ()); + }; }; - }; - for iter::repeat(7u) { - oldcomm::recv(work_exit_po); - }; - log(debug, ~"sending teardown_loop msg.."); - exit(iotask); - oldcomm::recv(exit_po); - log(debug, ~"after recv on exit_po.. exiting.."); + for iter::repeat(7u) { + oldcomm::recv(work_exit_po); + }; + log(debug, ~"sending teardown_loop msg.."); + exit(iotask); + oldcomm::recv(exit_po); + log(debug, ~"after recv on exit_po.. exiting.."); + } } } diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index eee3d60a66d..17b11945028 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1103,304 +1103,325 @@ pub mod test { extern fn on_alloc_cb(handle: *libc::c_void, suggested_size: libc::size_t) - -> uv_buf_t unsafe { - log(debug, ~"on_alloc_cb!"); - let char_ptr = malloc_buf_base_of(suggested_size); - log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u", - handle, - char_ptr as uint, - suggested_size as uint)); - return buf_init(char_ptr, suggested_size as uint); + -> uv_buf_t { + unsafe { + log(debug, ~"on_alloc_cb!"); + let char_ptr = malloc_buf_base_of(suggested_size); + log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u", + handle, + char_ptr as uint, + suggested_size as uint)); + return buf_init(char_ptr, suggested_size as uint); + } } extern fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, - ++buf: uv_buf_t) unsafe { - let nread = nread as int; - log(debug, fmt!("CLIENT entering on_read_cb nred: %d", - nread)); - if (nread > 0) { - // we have data - log(debug, fmt!("CLIENT read: data! nread: %d", nread)); - read_stop(stream); - let client_data = - get_data_for_uv_handle(stream as *libc::c_void) - as *request_wrapper; - let buf_base = get_base_from_buf(buf); - let buf_len = get_len_from_buf(buf); - let bytes = vec::from_buf(buf_base, buf_len as uint); - let read_chan = *((*client_data).read_chan); - let msg_from_server = str::from_bytes(bytes); - oldcomm::send(read_chan, msg_from_server); - close(stream as *libc::c_void, after_close_cb) - } - else if (nread == -1) { - // err .. possibly EOF - log(debug, ~"read: eof!"); - } - else { - // nread == 0 .. do nothing, just free buf as below - log(debug, ~"read: do nothing!"); + ++buf: uv_buf_t) { + unsafe { + let nread = nread as int; + log(debug, fmt!("CLIENT entering on_read_cb nred: %d", + nread)); + if (nread > 0) { + // we have data + log(debug, fmt!("CLIENT read: data! nread: %d", nread)); + read_stop(stream); + let client_data = + get_data_for_uv_handle(stream as *libc::c_void) + as *request_wrapper; + let buf_base = get_base_from_buf(buf); + let buf_len = get_len_from_buf(buf); + let bytes = vec::from_buf(buf_base, buf_len as uint); + let read_chan = *((*client_data).read_chan); + let msg_from_server = str::from_bytes(bytes); + oldcomm::send(read_chan, msg_from_server); + close(stream as *libc::c_void, after_close_cb) + } + else if (nread == -1) { + // err .. possibly EOF + log(debug, ~"read: eof!"); + } + else { + // nread == 0 .. do nothing, just free buf as below + log(debug, ~"read: do nothing!"); + } + // when we're done + free_base_of_buf(buf); + log(debug, ~"CLIENT exiting on_read_cb"); } - // when we're done - free_base_of_buf(buf); - log(debug, ~"CLIENT exiting on_read_cb"); } extern fn on_write_complete_cb(write_req: *uv_write_t, - status: libc::c_int) unsafe { - log(debug, fmt!("CLIENT beginning on_write_complete_cb status: %d", - status as int)); - let stream = get_stream_handle_from_write_req(write_req); - log(debug, fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", - stream as int, write_req as int)); - let result = read_start(stream, on_alloc_cb, on_read_cb); - log(debug, fmt!("CLIENT ending on_write_complete_cb .. status: %d", - result as int)); + status: libc::c_int) { + unsafe { + log(debug, + fmt!("CLIENT beginning on_write_complete_cb status: %d", + status as int)); + let stream = get_stream_handle_from_write_req(write_req); + log(debug, + fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", + stream as int, write_req as int)); + let result = read_start(stream, on_alloc_cb, on_read_cb); + log(debug, + fmt!("CLIENT ending on_write_complete_cb .. status: %d", + result as int)); + } } extern fn on_connect_cb(connect_req_ptr: *uv_connect_t, - status: libc::c_int) unsafe { - log(debug, fmt!("beginning on_connect_cb .. status: %d", - status as int)); - let stream = - get_stream_handle_from_connect_req(connect_req_ptr); - if (status == 0i32) { - log(debug, ~"on_connect_cb: in status=0 if.."); - let client_data = get_data_for_req( - connect_req_ptr as *libc::c_void) - as *request_wrapper; - let write_handle = (*client_data).write_req; - log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d", - stream as int, write_handle as int)); - let write_result = write(write_handle, - stream as *libc::c_void, - (*client_data).req_buf, - on_write_complete_cb); - log(debug, fmt!("on_connect_cb: write() status: %d", - write_result as int)); - } - else { - let test_loop = get_loop_for_uv_handle( - stream as *libc::c_void); - let err_msg = get_last_err_info(test_loop); - log(debug, err_msg); - assert false; + status: libc::c_int) { + unsafe { + log(debug, fmt!("beginning on_connect_cb .. status: %d", + status as int)); + let stream = + get_stream_handle_from_connect_req(connect_req_ptr); + if (status == 0i32) { + log(debug, ~"on_connect_cb: in status=0 if.."); + let client_data = get_data_for_req( + connect_req_ptr as *libc::c_void) + as *request_wrapper; + let write_handle = (*client_data).write_req; + log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d", + stream as int, write_handle as int)); + let write_result = write(write_handle, + stream as *libc::c_void, + (*client_data).req_buf, + on_write_complete_cb); + log(debug, fmt!("on_connect_cb: write() status: %d", + write_result as int)); + } + else { + let test_loop = get_loop_for_uv_handle( + stream as *libc::c_void); + let err_msg = get_last_err_info(test_loop); + log(debug, err_msg); + assert false; + } + log(debug, ~"finishing on_connect_cb"); } - log(debug, ~"finishing on_connect_cb"); } fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str, - client_chan: *oldcomm::Chan<~str>) unsafe { - let test_loop = loop_new(); - let tcp_handle = tcp_t(); - let tcp_handle_ptr = ptr::addr_of(&tcp_handle); - let connect_handle = connect_t(); - let connect_req_ptr = ptr::addr_of(&connect_handle); - - // this is the persistent payload of data that we - // need to pass around to get this example to work. - // In C, this would be a malloc'd or stack-allocated - // struct that we'd cast to a void* and store as the - // data field in our uv_connect_t struct - let req_str_bytes = str::to_bytes(req_str); - let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes); - log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint)); - let req_msg = ~[ - buf_init(req_msg_ptr, vec::len(req_str_bytes)) - ]; - // this is the enclosing record, we'll pass a ptr to - // this to C.. - let write_handle = write_t(); - let write_handle_ptr = ptr::addr_of(&write_handle); - log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d", - tcp_handle_ptr as int, - write_handle_ptr as int)); - let client_data = { writer_handle: write_handle_ptr, - req_buf: ptr::addr_of(&req_msg), - read_chan: client_chan }; - - let tcp_init_result = tcp_init( - test_loop as *libc::c_void, tcp_handle_ptr); - if (tcp_init_result == 0i32) { - log(debug, ~"sucessful tcp_init_result"); - - log(debug, ~"building addr..."); - let addr = ip4_addr(ip, port); - // FIXME ref #2064 - let addr_ptr = ptr::addr_of(&addr); - log(debug, fmt!("after build addr in rust. port: %u", - addr.sin_port as uint)); - - // this should set up the connection request.. - log(debug, fmt!("b4 call tcp_connect connect cb: %u ", - on_connect_cb as uint)); - let tcp_connect_result = tcp_connect( - connect_req_ptr, tcp_handle_ptr, - addr_ptr, on_connect_cb); - if (tcp_connect_result == 0i32) { - // not set the data on the connect_req - // until its initialized - set_data_for_req( - connect_req_ptr as *libc::c_void, - ptr::addr_of(&client_data) as *libc::c_void); - set_data_for_uv_handle( - tcp_handle_ptr as *libc::c_void, - ptr::addr_of(&client_data) as *libc::c_void); - log(debug, ~"before run tcp req loop"); - run(test_loop); - log(debug, ~"after run tcp req loop"); + client_chan: *oldcomm::Chan<~str>) { + unsafe { + let test_loop = loop_new(); + let tcp_handle = tcp_t(); + let tcp_handle_ptr = ptr::addr_of(&tcp_handle); + let connect_handle = connect_t(); + let connect_req_ptr = ptr::addr_of(&connect_handle); + + // this is the persistent payload of data that we + // need to pass around to get this example to work. + // In C, this would be a malloc'd or stack-allocated + // struct that we'd cast to a void* and store as the + // data field in our uv_connect_t struct + let req_str_bytes = str::to_bytes(req_str); + let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes); + log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint)); + let req_msg = ~[ + buf_init(req_msg_ptr, vec::len(req_str_bytes)) + ]; + // this is the enclosing record, we'll pass a ptr to + // this to C.. + let write_handle = write_t(); + let write_handle_ptr = ptr::addr_of(&write_handle); + log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d", + tcp_handle_ptr as int, + write_handle_ptr as int)); + let client_data = { writer_handle: write_handle_ptr, + req_buf: ptr::addr_of(&req_msg), + read_chan: client_chan }; + + let tcp_init_result = tcp_init( + test_loop as *libc::c_void, tcp_handle_ptr); + if (tcp_init_result == 0i32) { + log(debug, ~"sucessful tcp_init_result"); + + log(debug, ~"building addr..."); + let addr = ip4_addr(ip, port); + // FIXME ref #2064 + let addr_ptr = ptr::addr_of(&addr); + log(debug, fmt!("after build addr in rust. port: %u", + addr.sin_port as uint)); + + // this should set up the connection request.. + log(debug, fmt!("b4 call tcp_connect connect cb: %u ", + on_connect_cb as uint)); + let tcp_connect_result = tcp_connect( + connect_req_ptr, tcp_handle_ptr, + addr_ptr, on_connect_cb); + if (tcp_connect_result == 0i32) { + // not set the data on the connect_req + // until its initialized + set_data_for_req( + connect_req_ptr as *libc::c_void, + ptr::addr_of(&client_data) as *libc::c_void); + set_data_for_uv_handle( + tcp_handle_ptr as *libc::c_void, + ptr::addr_of(&client_data) as *libc::c_void); + log(debug, ~"before run tcp req loop"); + run(test_loop); + log(debug, ~"after run tcp req loop"); + } + else { + log(debug, ~"tcp_connect() failure"); + assert false; + } } else { - log(debug, ~"tcp_connect() failure"); - assert false; + log(debug, ~"tcp_init() failure"); + assert false; } + loop_delete(test_loop); } - else { - log(debug, ~"tcp_init() failure"); - assert false; - } - loop_delete(test_loop); - } - extern fn server_after_close_cb(handle: *libc::c_void) unsafe { - log(debug, fmt!("SERVER server stream closed, should exit.. h: %?", - handle)); + extern fn server_after_close_cb(handle: *libc::c_void) { + unsafe { + log(debug, fmt!("SERVER server stream closed, should exit. h: %?", + handle)); + } } - extern fn client_stream_after_close_cb(handle: *libc::c_void) + extern fn client_stream_after_close_cb(handle: *libc::c_void) { unsafe { - log(debug, - ~"SERVER: closed client stream, now closing server stream"); - let client_data = get_data_for_uv_handle( - handle) as - *tcp_server_data; - close((*client_data).server as *libc::c_void, - server_after_close_cb); + log(debug, + ~"SERVER: closed client stream, now closing server stream"); + let client_data = get_data_for_uv_handle( + handle) as + *tcp_server_data; + close((*client_data).server as *libc::c_void, + server_after_close_cb); + } } - extern fn after_server_resp_write(req: *uv_write_t) unsafe { - let client_stream_ptr = - get_stream_handle_from_write_req(req); - log(debug, ~"SERVER: resp sent... closing client stream"); - close(client_stream_ptr as *libc::c_void, - client_stream_after_close_cb) + extern fn after_server_resp_write(req: *uv_write_t) { + unsafe { + let client_stream_ptr = + get_stream_handle_from_write_req(req); + log(debug, ~"SERVER: resp sent... closing client stream"); + close(client_stream_ptr as *libc::c_void, + client_stream_after_close_cb) + } } extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t, nread: libc::ssize_t, - ++buf: uv_buf_t) unsafe { - let nread = nread as int; - if (nread > 0) { - // we have data - log(debug, fmt!("SERVER read: data! nread: %d", nread)); - - // pull out the contents of the write from the client - let buf_base = get_base_from_buf(buf); - let buf_len = get_len_from_buf(buf) as uint; - log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d", - buf_base as uint, - buf_len as uint, - nread)); - let bytes = vec::from_buf(buf_base, buf_len); - let request_str = str::from_bytes(bytes); - - let client_data = get_data_for_uv_handle( - client_stream_ptr as *libc::c_void) as *tcp_server_data; - - let server_kill_msg = (*client_data).server_kill_msg; - let write_req = (*client_data).server_write_req; - if (str::contains(request_str, server_kill_msg)) { - log(debug, ~"SERVER: client req contains kill_msg!"); - log(debug, ~"SERVER: sending response to client"); - read_stop(client_stream_ptr); - let server_chan = *((*client_data).server_chan); - oldcomm::send(server_chan, request_str); - let write_result = write( - write_req, - client_stream_ptr as *libc::c_void, - (*client_data).server_resp_buf, - after_server_resp_write); - log(debug, fmt!("SERVER: resp write result: %d", - write_result as int)); - if (write_result != 0i32) { - log(debug, ~"bad result for server resp write()"); - log(debug, get_last_err_info( - get_loop_for_uv_handle(client_stream_ptr - as *libc::c_void))); - assert false; + ++buf: uv_buf_t) { + unsafe { + let nread = nread as int; + if (nread > 0) { + // we have data + log(debug, fmt!("SERVER read: data! nread: %d", nread)); + + // pull out the contents of the write from the client + let buf_base = get_base_from_buf(buf); + let buf_len = get_len_from_buf(buf) as uint; + log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d", + buf_base as uint, + buf_len as uint, + nread)); + let bytes = vec::from_buf(buf_base, buf_len); + let request_str = str::from_bytes(bytes); + + let client_data = get_data_for_uv_handle( + client_stream_ptr as *libc::c_void) as *tcp_server_data; + + let server_kill_msg = (*client_data).server_kill_msg; + let write_req = (*client_data).server_write_req; + if (str::contains(request_str, server_kill_msg)) { + log(debug, ~"SERVER: client req contains kill_msg!"); + log(debug, ~"SERVER: sending response to client"); + read_stop(client_stream_ptr); + let server_chan = *((*client_data).server_chan); + oldcomm::send(server_chan, request_str); + let write_result = write( + write_req, + client_stream_ptr as *libc::c_void, + (*client_data).server_resp_buf, + after_server_resp_write); + log(debug, fmt!("SERVER: resp write result: %d", + write_result as int)); + if (write_result != 0i32) { + log(debug, ~"bad result for server resp write()"); + log(debug, get_last_err_info( + get_loop_for_uv_handle(client_stream_ptr + as *libc::c_void))); + assert false; + } + } + else { + log(debug, ~"SERVER: client req !contain kill_msg!"); } } + else if (nread == -1) { + // err .. possibly EOF + log(debug, ~"read: eof!"); + } else { - log(debug, ~"SERVER: client req !contain kill_msg!"); + // nread == 0 .. do nothing, just free buf as below + log(debug, ~"read: do nothing!"); } + // when we're done + free_base_of_buf(buf); + log(debug, ~"SERVER exiting on_read_cb"); } - else if (nread == -1) { - // err .. possibly EOF - log(debug, ~"read: eof!"); - } - else { - // nread == 0 .. do nothing, just free buf as below - log(debug, ~"read: do nothing!"); - } - // when we're done - free_base_of_buf(buf); - log(debug, ~"SERVER exiting on_read_cb"); } extern fn server_connection_cb(server_stream_ptr: *uv_stream_t, - status: libc::c_int) unsafe { - log(debug, ~"client connecting!"); - let test_loop = get_loop_for_uv_handle( - server_stream_ptr as *libc::c_void); - if status != 0i32 { - let err_msg = get_last_err_info(test_loop); - log(debug, fmt!("server_connect_cb: non-zero status: %?", - err_msg)); - return; - } - let server_data = get_data_for_uv_handle( - server_stream_ptr as *libc::c_void) as *tcp_server_data; - let client_stream_ptr = (*server_data).client; - let client_init_result = tcp_init(test_loop, - client_stream_ptr); - set_data_for_uv_handle( - client_stream_ptr as *libc::c_void, - server_data as *libc::c_void); - if (client_init_result == 0i32) { - log(debug, ~"successfully initialized client stream"); - let accept_result = accept(server_stream_ptr as - *libc::c_void, - client_stream_ptr as - *libc::c_void); - if (accept_result == 0i32) { - // start reading - let read_result = read_start( - client_stream_ptr as *uv_stream_t, - on_alloc_cb, - on_server_read_cb); - if (read_result == 0i32) { - log(debug, ~"successful server read start"); + status: libc::c_int) { + unsafe { + log(debug, ~"client connecting!"); + let test_loop = get_loop_for_uv_handle( + server_stream_ptr as *libc::c_void); + if status != 0i32 { + let err_msg = get_last_err_info(test_loop); + log(debug, fmt!("server_connect_cb: non-zero status: %?", + err_msg)); + return; + } + let server_data = get_data_for_uv_handle( + server_stream_ptr as *libc::c_void) as *tcp_server_data; + let client_stream_ptr = (*server_data).client; + let client_init_result = tcp_init(test_loop, + client_stream_ptr); + set_data_for_uv_handle( + client_stream_ptr as *libc::c_void, + server_data as *libc::c_void); + if (client_init_result == 0i32) { + log(debug, ~"successfully initialized client stream"); + let accept_result = accept(server_stream_ptr as + *libc::c_void, + client_stream_ptr as + *libc::c_void); + if (accept_result == 0i32) { + // start reading + let read_result = read_start( + client_stream_ptr as *uv_stream_t, + on_alloc_cb, + on_server_read_cb); + if (read_result == 0i32) { + log(debug, ~"successful server read start"); + } + else { + log(debug, fmt!("server_connection_cb: bad read:%d", + read_result as int)); + assert false; + } } else { - log(debug, fmt!("server_connection_cb: bad read:%d", - read_result as int)); + log(debug, fmt!("server_connection_cb: bad accept: %d", + accept_result as int)); assert false; } } else { - log(debug, fmt!("server_connection_cb: bad accept: %d", - accept_result as int)); + log(debug, fmt!("server_connection_cb: bad client init: %d", + client_init_result as int)); assert false; } } - else { - log(debug, fmt!("server_connection_cb: bad client init: %d", - client_init_result as int)); - assert false; - } } type tcp_server_data = { @@ -1422,17 +1443,19 @@ pub mod test { } extern fn continue_async_cb(async_handle: *uv_async_t, - status: libc::c_int) unsafe { - // once we're in the body of this callback, - // the tcp server's loop is set up, so we - // can continue on to let the tcp client - // do its thang - let data = get_data_for_uv_handle( - async_handle as *libc::c_void) as *async_handle_data; - let continue_chan = *((*data).continue_chan); - let should_continue = status == 0i32; - oldcomm::send(continue_chan, should_continue); - close(async_handle as *libc::c_void, async_close_cb); + status: libc::c_int) { + unsafe { + // once we're in the body of this callback, + // the tcp server's loop is set up, so we + // can continue on to let the tcp client + // do its thang + let data = get_data_for_uv_handle( + async_handle as *libc::c_void) as *async_handle_data; + let continue_chan = *((*data).continue_chan); + let should_continue = status == 0i32; + oldcomm::send(continue_chan, should_continue); + close(async_handle as *libc::c_void, async_close_cb); + } } fn impl_uv_tcp_server(server_ip: &str, @@ -1440,144 +1463,148 @@ pub mod test { +kill_server_msg: ~str, +server_resp_msg: ~str, server_chan: *oldcomm::Chan<~str>, - continue_chan: *oldcomm::Chan<bool>) unsafe { - let test_loop = loop_new(); - let tcp_server = tcp_t(); - let tcp_server_ptr = ptr::addr_of(&tcp_server); - - let tcp_client = tcp_t(); - let tcp_client_ptr = ptr::addr_of(&tcp_client); - - let server_write_req = write_t(); - let server_write_req_ptr = ptr::addr_of(&server_write_req); - - let resp_str_bytes = str::to_bytes(server_resp_msg); - let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes); - log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint)); - let resp_msg = ~[ - buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) - ]; - - let continue_async_handle = async_t(); - let continue_async_handle_ptr = - ptr::addr_of(&continue_async_handle); - let async_data = - { continue_chan: continue_chan }; - let async_data_ptr = ptr::addr_of(&async_data); - - let server_data: tcp_server_data = { - client: tcp_client_ptr, - server: tcp_server_ptr, - server_kill_msg: kill_server_msg, - server_resp_buf: ptr::addr_of(&resp_msg), - server_chan: server_chan, - server_write_req: server_write_req_ptr - }; - let server_data_ptr = ptr::addr_of(&server_data); - set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, - server_data_ptr as *libc::c_void); - - // uv_tcp_init() - let tcp_init_result = tcp_init( - test_loop as *libc::c_void, tcp_server_ptr); - if (tcp_init_result == 0i32) { - let server_addr = ip4_addr(server_ip, server_port); - // FIXME ref #2064 - let server_addr_ptr = ptr::addr_of(&server_addr); - - // uv_tcp_bind() - let bind_result = tcp_bind(tcp_server_ptr, - server_addr_ptr); - if (bind_result == 0i32) { - log(debug, ~"successful uv_tcp_bind, listening"); - - // uv_listen() - let listen_result = listen(tcp_server_ptr as - *libc::c_void, - 128i32, - server_connection_cb); - if (listen_result == 0i32) { - // let the test know it can set up the tcp server, - // now.. this may still present a race, not sure.. - let async_result = async_init(test_loop, - continue_async_handle_ptr, - continue_async_cb); - if (async_result == 0i32) { - set_data_for_uv_handle( - continue_async_handle_ptr as *libc::c_void, - async_data_ptr as *libc::c_void); - async_send(continue_async_handle_ptr); - // uv_run() - run(test_loop); - log(debug, ~"server uv::run() has returned"); + continue_chan: *oldcomm::Chan<bool>) { + unsafe { + let test_loop = loop_new(); + let tcp_server = tcp_t(); + let tcp_server_ptr = ptr::addr_of(&tcp_server); + + let tcp_client = tcp_t(); + let tcp_client_ptr = ptr::addr_of(&tcp_client); + + let server_write_req = write_t(); + let server_write_req_ptr = ptr::addr_of(&server_write_req); + + let resp_str_bytes = str::to_bytes(server_resp_msg); + let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes); + log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint)); + let resp_msg = ~[ + buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) + ]; + + let continue_async_handle = async_t(); + let continue_async_handle_ptr = + ptr::addr_of(&continue_async_handle); + let async_data = + { continue_chan: continue_chan }; + let async_data_ptr = ptr::addr_of(&async_data); + + let server_data: tcp_server_data = { + client: tcp_client_ptr, + server: tcp_server_ptr, + server_kill_msg: kill_server_msg, + server_resp_buf: ptr::addr_of(&resp_msg), + server_chan: server_chan, + server_write_req: server_write_req_ptr + }; + let server_data_ptr = ptr::addr_of(&server_data); + set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, + server_data_ptr as *libc::c_void); + + // uv_tcp_init() + let tcp_init_result = tcp_init( + test_loop as *libc::c_void, tcp_server_ptr); + if (tcp_init_result == 0i32) { + let server_addr = ip4_addr(server_ip, server_port); + // FIXME ref #2064 + let server_addr_ptr = ptr::addr_of(&server_addr); + + // uv_tcp_bind() + let bind_result = tcp_bind(tcp_server_ptr, + server_addr_ptr); + if (bind_result == 0i32) { + log(debug, ~"successful uv_tcp_bind, listening"); + + // uv_listen() + let listen_result = listen(tcp_server_ptr as + *libc::c_void, + 128i32, + server_connection_cb); + if (listen_result == 0i32) { + // let the test know it can set up the tcp server, + // now.. this may still present a race, not sure.. + let async_result = async_init(test_loop, + continue_async_handle_ptr, + continue_async_cb); + if (async_result == 0i32) { + set_data_for_uv_handle( + continue_async_handle_ptr as *libc::c_void, + async_data_ptr as *libc::c_void); + async_send(continue_async_handle_ptr); + // uv_run() + run(test_loop); + log(debug, ~"server uv::run() has returned"); + } + else { + log(debug, fmt!("uv_async_init failure: %d", + async_result as int)); + assert false; + } } else { - log(debug, fmt!("uv_async_init failure: %d", - async_result as int)); + log(debug, fmt!("non-zero result on uv_listen: %d", + listen_result as int)); assert false; } } else { - log(debug, fmt!("non-zero result on uv_listen: %d", - listen_result as int)); + log(debug, fmt!("non-zero result on uv_tcp_bind: %d", + bind_result as int)); assert false; } } else { - log(debug, fmt!("non-zero result on uv_tcp_bind: %d", - bind_result as int)); + log(debug, fmt!("non-zero result on uv_tcp_init: %d", + tcp_init_result as int)); assert false; } + loop_delete(test_loop); } - else { - log(debug, fmt!("non-zero result on uv_tcp_init: %d", - tcp_init_result as int)); - assert false; - } - loop_delete(test_loop); } // this is the impl for a test that is (maybe) ran on a // per-platform/arch basis below - fn impl_uv_tcp_server_and_request() unsafe { - let bind_ip = ~"0.0.0.0"; - let request_ip = ~"127.0.0.1"; - let port = 8886; - let kill_server_msg = ~"does a dog have buddha nature?"; - let server_resp_msg = ~"mu!"; - let client_port = oldcomm::Port::<~str>(); - let client_chan = oldcomm::Chan::<~str>(&client_port); - let server_port = oldcomm::Port::<~str>(); - let server_chan = oldcomm::Chan::<~str>(&server_port); - - let continue_port = oldcomm::Port::<bool>(); - let continue_chan = oldcomm::Chan::<bool>(&continue_port); - let continue_chan_ptr = ptr::addr_of(&continue_chan); - - do task::spawn_sched(task::ManualThreads(1)) { - impl_uv_tcp_server(bind_ip, port, - kill_server_msg, - server_resp_msg, - ptr::addr_of(&server_chan), - continue_chan_ptr); - }; + fn impl_uv_tcp_server_and_request() { + unsafe { + let bind_ip = ~"0.0.0.0"; + let request_ip = ~"127.0.0.1"; + let port = 8886; + let kill_server_msg = ~"does a dog have buddha nature?"; + let server_resp_msg = ~"mu!"; + let client_port = oldcomm::Port::<~str>(); + let client_chan = oldcomm::Chan::<~str>(&client_port); + let server_port = oldcomm::Port::<~str>(); + let server_chan = oldcomm::Chan::<~str>(&server_port); + + let continue_port = oldcomm::Port::<bool>(); + let continue_chan = oldcomm::Chan::<bool>(&continue_port); + let continue_chan_ptr = ptr::addr_of(&continue_chan); + + do task::spawn_sched(task::ManualThreads(1)) { + impl_uv_tcp_server(bind_ip, port, + kill_server_msg, + server_resp_msg, + ptr::addr_of(&server_chan), + continue_chan_ptr); + }; - // block until the server up is.. possibly a race? - log(debug, ~"before receiving on server continue_port"); - oldcomm::recv(continue_port); - log(debug, ~"received on continue port, set up tcp client"); + // block until the server up is.. possibly a race? + log(debug, ~"before receiving on server continue_port"); + oldcomm::recv(continue_port); + log(debug, ~"received on continue port, set up tcp client"); - do task::spawn_sched(task::ManualThreads(1u)) { - impl_uv_tcp_request(request_ip, port, - kill_server_msg, - ptr::addr_of(&client_chan)); - }; + do task::spawn_sched(task::ManualThreads(1u)) { + impl_uv_tcp_request(request_ip, port, + kill_server_msg, + ptr::addr_of(&client_chan)); + }; - let msg_from_client = oldcomm::recv(server_port); - let msg_from_server = oldcomm::recv(client_port); + let msg_from_client = oldcomm::recv(server_port); + let msg_from_server = oldcomm::recv(client_port); - assert str::contains(msg_from_client, kill_server_msg); - assert str::contains(msg_from_server, server_resp_msg); + assert str::contains(msg_from_client, kill_server_msg); + assert str::contains(msg_from_server, server_resp_msg); + } } // FIXME don't run on fbsd or linux 32 bit(#2064) @@ -1590,8 +1617,10 @@ pub mod test { pub mod impl64 { use uv_ll::test::*; #[test] - pub fn test_uv_ll_tcp_server_and_request() unsafe { - impl_uv_tcp_server_and_request(); + pub fn test_uv_ll_tcp_server_and_request() { + unsafe { + impl_uv_tcp_server_and_request(); + } } } #[cfg(target_arch="x86")] @@ -1600,8 +1629,10 @@ pub mod test { use uv_ll::test::*; #[test] #[ignore(cfg(target_os = "linux"))] - pub fn test_uv_ll_tcp_server_and_request() unsafe { - impl_uv_tcp_server_and_request(); + pub fn test_uv_ll_tcp_server_and_request() { + unsafe { + impl_uv_tcp_server_and_request(); + } } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8211f646ec7..65216e55493 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -33,8 +33,6 @@ macro_rules! interner_key ( (-3 as uint, 0u))) ) -// FIXME(#3534): Replace with the struct-based newtype when it's been -// implemented. struct ident { repr: uint } impl<S: Encoder> ident: Encodable<S> { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 531b9501d6c..56fe46251e9 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -304,9 +304,9 @@ fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] { } // This is sort of stupid here, converting to a vec of mutables and back - let v: ~[mut @ast::meta_item] = vec::to_mut(items); + let v: ~[mut @ast::meta_item] = vec::cast_to_mut(items); std::sort::quick_sort(v, lteq); - vec::from_mut(move v) + vec::cast_from_mut(move v) } fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: ~str) -> diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 1e4a40405fd..7a7c2312f56 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -208,14 +208,16 @@ pub impl FileMap { self.lines.push(pos); } - pub fn get_line(&self, line: int) -> ~str unsafe { - let begin: BytePos = self.lines[line] - self.start_pos; - let begin = begin.to_uint(); - let end = match str::find_char_from(*self.src, '\n', begin) { - Some(e) => e, - None => str::len(*self.src) - }; - str::slice(*self.src, begin, end) + pub fn get_line(&self, line: int) -> ~str { + unsafe { + let begin: BytePos = self.lines[line] - self.start_pos; + let begin = begin.to_uint(); + let end = match str::find_char_from(*self.src, '\n', begin) { + Some(e) => e, + None => str::len(*self.src) + }; + str::slice(*self.src, begin, end) + } } pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index dab57dd0ad4..a8c05296390 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -25,65 +25,65 @@ use std::map::HashMap; // new-style macro! tt code: // -// syntax_expander_tt, syntax_expander_tt_item, mac_result, -// normal_tt, item_tt +// SyntaxExpanderTT, SyntaxExpanderTTItem, MacResult, +// NormalTT, ItemTT // // also note that ast::mac used to have a bunch of extraneous cases and // is now probably a redundant AST node, can be merged with // ast::mac_invoc_tt. -struct macro_def { +struct MacroDef { name: ~str, - ext: syntax_extension, + ext: SyntaxExtension } -type item_decorator = +type ItemDecorator = fn@(ext_ctxt, span, ast::meta_item, ~[@ast::item]) -> ~[@ast::item]; -struct syntax_expander_tt { - expander: syntax_expander_tt_, - span: Option<span>, +struct SyntaxExpanderTT { + expander: SyntaxExpanderTTFun, + span: Option<span> } -type syntax_expander_tt_ = fn@(ext_ctxt, span, ~[ast::token_tree]) - -> mac_result; +type SyntaxExpanderTTFun = fn@(ext_ctxt, span, ~[ast::token_tree]) + -> MacResult; -struct syntax_expander_tt_item { - expander: syntax_expander_tt_item_, - span: Option<span>, +struct SyntaxExpanderTTItem { + expander: SyntaxExpanderTTItemFun, + span: Option<span> } -type syntax_expander_tt_item_ - = fn@(ext_ctxt, span, ast::ident, ~[ast::token_tree]) -> mac_result; +type SyntaxExpanderTTItemFun + = fn@(ext_ctxt, span, ast::ident, ~[ast::token_tree]) -> MacResult; -enum mac_result { - mr_expr(@ast::expr), - mr_item(@ast::item), - mr_any(fn@()-> @ast::expr, fn@()-> Option<@ast::item>, fn@()->@ast::stmt), - mr_def(macro_def) +enum MacResult { + MRExpr(@ast::expr), + MRItem(@ast::item), + MRAny(fn@()-> @ast::expr, fn@()-> Option<@ast::item>, fn@()->@ast::stmt), + MRDef(MacroDef) } -enum syntax_extension { +enum SyntaxExtension { // #[auto_encode] and such - item_decorator(item_decorator), + ItemDecorator(ItemDecorator), // Token-tree expanders - normal_tt(syntax_expander_tt), + NormalTT(SyntaxExpanderTT), // perhaps macro_rules! will lose its odd special identifier argument, // and this can go away also - item_tt(syntax_expander_tt_item), + ItemTT(SyntaxExpanderTTItem), } // A temporary hard-coded map of methods for expanding syntax extension // AST nodes into full ASTs -fn syntax_expander_table() -> HashMap<~str, syntax_extension> { - fn builtin_normal_tt(f: syntax_expander_tt_) -> syntax_extension { - normal_tt(syntax_expander_tt {expander: f, span: None}) +fn syntax_expander_table() -> HashMap<~str, SyntaxExtension> { + fn builtin_normal_tt(f: SyntaxExpanderTTFun) -> SyntaxExtension { + NormalTT(SyntaxExpanderTT{expander: f, span: None}) } - fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension { - item_tt(syntax_expander_tt_item {expander: f, span: None}) + fn builtin_item_tt(f: SyntaxExpanderTTItemFun) -> SyntaxExtension { + ItemTT(SyntaxExpanderTTItem{expander: f, span: None}) } let syntax_expanders = HashMap(); syntax_expanders.insert(~"macro_rules", @@ -93,10 +93,10 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { builtin_normal_tt(ext::fmt::expand_syntax_ext)); syntax_expanders.insert( ~"auto_encode", - item_decorator(ext::auto_encode::expand_auto_encode)); + ItemDecorator(ext::auto_encode::expand_auto_encode)); syntax_expanders.insert( ~"auto_decode", - item_decorator(ext::auto_encode::expand_auto_decode)); + ItemDecorator(ext::auto_encode::expand_auto_decode)); syntax_expanders.insert(~"env", builtin_normal_tt(ext::env::expand_syntax_ext)); syntax_expanders.insert(~"concat_idents", @@ -106,10 +106,10 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { builtin_normal_tt( ext::log_syntax::expand_syntax_ext)); syntax_expanders.insert(~"deriving_eq", - item_decorator( + ItemDecorator( ext::deriving::expand_deriving_eq)); syntax_expanders.insert(~"deriving_iter_bytes", - item_decorator( + ItemDecorator( ext::deriving::expand_deriving_iter_bytes)); // Quasi-quoting expanders diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 8e94ed19021..3d5d0b42cd0 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -14,7 +14,7 @@ use ext::base::*; use ext::base; fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let mut res_str = ~""; for tts.eachi |i, e| { if i & 1 == 1 { @@ -48,5 +48,5 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) ), span: sp, }; - mr_expr(e) + MRExpr(e) } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index c07853a400b..ad827377ac4 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -25,7 +25,7 @@ use core::os; export expand_syntax_ext; fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let var = get_single_str_from_tts(cx, sp, tts, "env!"); @@ -36,7 +36,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) option::None => mk_uniq_str(cx, sp, ~""), option::Some(ref s) => mk_uniq_str(cx, sp, (*s)) }; - mr_expr(e) + MRExpr(e) } // diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4b096f07b75..068b372c069 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -22,7 +22,7 @@ use core::option; use core::vec; use std::map::HashMap; -fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, +fn expand_expr(exts: HashMap<~str, SyntaxExtension>, cx: ext_ctxt, e: expr_, s: span, fld: ast_fold, orig: fn@(expr_, span, ast_fold) -> (expr_, span)) -> (expr_, span) @@ -46,15 +46,14 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)) } - Some(normal_tt( - syntax_expander_tt { expander: exp, span: exp_sp } - )) => { + Some(NormalTT(SyntaxExpanderTT{expander: exp, + span: exp_sp})) => { cx.bt_push(ExpandedFrom({call_site: s, callie: {name: *extname, span: exp_sp}})); let expanded = match exp(cx, (*mac).span, (*tts)) { - mr_expr(e) => e, - mr_any(expr_maker,_,_) => expr_maker(), + MRExpr(e) => e, + MRAny(expr_maker,_,_) => expr_maker(), _ => cx.span_fatal( pth.span, fmt!("non-expr macro in expr pos: %s", *extname)) @@ -85,11 +84,11 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, // attribute prefixing an item, and are interpreted by feeding the item // through the named attribute _as a syntax extension_ and splicing in the // resulting item vec into place in favour of the decorator. Note that -// these do _not_ work for macro extensions, just item_decorator ones. +// these do _not_ work for macro extensions, just ItemDecorator ones. // // NB: there is some redundancy between this and expand_item, below, and // they might benefit from some amount of semantic and language-UI merger. -fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, +fn expand_mod_items(exts: HashMap<~str, SyntaxExtension>, cx: ext_ctxt, module_: ast::_mod, fld: ast_fold, orig: fn@(ast::_mod, ast_fold) -> ast::_mod) -> ast::_mod @@ -108,8 +107,8 @@ fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, ast::meta_list(ref n, _) => (*n) }; match exts.find(mname) { - None | Some(normal_tt(_)) | Some(item_tt(*)) => items, - Some(item_decorator(dec_fn)) => { + None | Some(NormalTT(_)) | Some(ItemTT(*)) => items, + Some(ItemDecorator(dec_fn)) => { cx.bt_push(ExpandedFrom({call_site: attr.span, callie: {name: copy mname, span: None}})); @@ -126,7 +125,7 @@ fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, // When we enter a module, record it, for the sake of `module!` -fn expand_item(exts: HashMap<~str, syntax_extension>, +fn expand_item(exts: HashMap<~str, SyntaxExtension>, cx: ext_ctxt, &&it: @ast::item, fld: ast_fold, orig: fn@(&&v: @ast::item, ast_fold) -> Option<@ast::item>) -> Option<@ast::item> @@ -153,7 +152,7 @@ fn expand_item(exts: HashMap<~str, syntax_extension>, // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. -fn expand_item_mac(exts: HashMap<~str, syntax_extension>, +fn expand_item_mac(exts: HashMap<~str, SyntaxExtension>, cx: ext_ctxt, &&it: @ast::item, fld: ast_fold) -> Option<@ast::item> { @@ -169,7 +168,7 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>, None => cx.span_fatal(pth.span, fmt!("macro undefined: '%s!'", *extname)), - Some(normal_tt(ref expand)) => { + Some(NormalTT(ref expand)) => { if it.ident != parse::token::special_idents::invalid { cx.span_fatal(pth.span, fmt!("macro %s! expects no ident argument, \ @@ -181,7 +180,7 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>, span: (*expand).span}})); ((*expand).expander)(cx, it.span, tts) } - Some(item_tt(ref expand)) => { + Some(ItemTT(ref expand)) => { if it.ident == parse::token::special_idents::invalid { cx.span_fatal(pth.span, fmt!("macro %s! expects an ident argument", @@ -197,13 +196,13 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>, }; let maybe_it = match expanded { - mr_item(it) => fld.fold_item(it), - mr_expr(_) => cx.span_fatal(pth.span, + MRItem(it) => fld.fold_item(it), + MRExpr(_) => cx.span_fatal(pth.span, ~"expr macro in item position: " + *extname), - mr_any(_, item_maker, _) => + MRAny(_, item_maker, _) => option::chain(item_maker(), |i| {fld.fold_item(i)}), - mr_def(ref mdef) => { + MRDef(ref mdef) => { exts.insert((*mdef).name, (*mdef).ext); None } @@ -212,7 +211,7 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>, return maybe_it; } -fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, +fn expand_stmt(exts: HashMap<~str, SyntaxExtension>, cx: ext_ctxt, && s: stmt_, sp: span, fld: ast_fold, orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span)) -> (stmt_, span) @@ -233,16 +232,15 @@ fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, None => cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)), - Some(normal_tt( - syntax_expander_tt { expander: exp, span: exp_sp } - )) => { + Some(NormalTT( + SyntaxExpanderTT{expander: exp, span: exp_sp})) => { cx.bt_push(ExpandedFrom( {call_site: sp, callie: {name: *extname, span: exp_sp}})); let expanded = match exp(cx, mac.span, tts) { - mr_expr(e) => + MRExpr(e) => @ast::spanned { node: stmt_expr(e, cx.next_id()), span: e.span}, - mr_any(_,_,stmt_mkr) => stmt_mkr(), + MRAny(_,_,stmt_mkr) => stmt_mkr(), _ => cx.span_fatal( pth.span, fmt!("non-stmt macro in stmt pos: %s", *extname)) @@ -302,6 +300,14 @@ fn core_macros() -> ~str { ) ) + macro_rules! fail_unless( + ($cond:expr) => { + if !$cond { + die!(~\"assertion failed: \" + stringify!($cond)) + } + } + ) + macro_rules! condition ( { $c:ident: $in:ty -> $out:ty; } => { diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 0eaa983ccad..2b7bd9ddf32 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -28,7 +28,7 @@ use extfmt::ct::*; export expand_syntax_ext; fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let args = get_exprs_from_tts(cx, copy tts); if args.len() == 0 { cx.span_fatal(sp, "fmt! takes at least 1 argument."); @@ -46,7 +46,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) parse_fmt_err_(cx, fmtspan, s) }; let pieces = parse_fmt_string(fmt, parse_fmt_err); - mr_expr(pieces_to_expr(cx, sp, pieces, args)) + MRExpr(pieces_to_expr(cx, sp, pieces, args)) } // FIXME (#2249): A lot of these functions for producing expressions can diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs index 5308f4c3486..b92e0b58bd5 100644 --- a/src/libsyntax/ext/log_syntax.rs +++ b/src/libsyntax/ext/log_syntax.rs @@ -18,14 +18,14 @@ use core::io::WriterUtil; use core::option; fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, tt: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { cx.print_backtrace(); io::stdout().write_line( print::pprust::tt_to_str(ast::tt_delim(tt),cx.parse_sess().interner)); //trivial expression - mr_expr(@ast::expr { + MRExpr(@ast::expr { id: cx.next_id(), callee_id: cx.next_id(), node: ast::expr_rec(~[], option::None), diff --git a/src/libsyntax/ext/pipes/mod.rs b/src/libsyntax/ext/pipes/mod.rs index cb17e56e990..8eef065395e 100644 --- a/src/libsyntax/ext/pipes/mod.rs +++ b/src/libsyntax/ext/pipes/mod.rs @@ -70,7 +70,7 @@ mod liveness; fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident, - tt: ~[ast::token_tree]) -> base::mac_result + tt: ~[ast::token_tree]) -> base::MacResult { let sess = cx.parse_sess(); let cfg = cx.cfg(); @@ -88,6 +88,6 @@ fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident, liveness::analyze(proto, cx); // compile - base::mr_item(proto.compile(cx)) + base::MRItem(proto.compile(cx)) } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 4aed5b64747..3354d015476 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -219,45 +219,45 @@ pub mod rt { pub fn expand_quote_tokens(cx: ext_ctxt, sp: span, - tts: ~[ast::token_tree]) -> base::mac_result { - base::mr_expr(expand_tts(cx, sp, tts)) + tts: ~[ast::token_tree]) -> base::MacResult { + base::MRExpr(expand_tts(cx, sp, tts)) } pub fn expand_quote_expr(cx: ext_ctxt, sp: span, - tts: ~[ast::token_tree]) -> base::mac_result { - base::mr_expr(expand_parse_call(cx, sp, ~"parse_expr", ~[], tts)) + tts: ~[ast::token_tree]) -> base::MacResult { + base::MRExpr(expand_parse_call(cx, sp, ~"parse_expr", ~[], tts)) } pub fn expand_quote_item(cx: ext_ctxt, sp: span, - tts: ~[ast::token_tree]) -> base::mac_result { + tts: ~[ast::token_tree]) -> base::MacResult { let e_attrs = build::mk_uniq_vec_e(cx, sp, ~[]); - base::mr_expr(expand_parse_call(cx, sp, ~"parse_item", + base::MRExpr(expand_parse_call(cx, sp, ~"parse_item", ~[e_attrs], tts)) } pub fn expand_quote_pat(cx: ext_ctxt, sp: span, - tts: ~[ast::token_tree]) -> base::mac_result { + tts: ~[ast::token_tree]) -> base::MacResult { let e_refutable = build::mk_lit(cx, sp, ast::lit_bool(true)); - base::mr_expr(expand_parse_call(cx, sp, ~"parse_pat", + base::MRExpr(expand_parse_call(cx, sp, ~"parse_pat", ~[e_refutable], tts)) } pub fn expand_quote_ty(cx: ext_ctxt, sp: span, - tts: ~[ast::token_tree]) -> base::mac_result { + tts: ~[ast::token_tree]) -> base::MacResult { let e_param_colons = build::mk_lit(cx, sp, ast::lit_bool(false)); - base::mr_expr(expand_parse_call(cx, sp, ~"parse_ty", + base::MRExpr(expand_parse_call(cx, sp, ~"parse_ty", ~[e_param_colons], tts)) } pub fn expand_quote_stmt(cx: ext_ctxt, sp: span, - tts: ~[ast::token_tree]) -> base::mac_result { + tts: ~[ast::token_tree]) -> base::MacResult { let e_attrs = build::mk_uniq_vec_e(cx, sp, ~[]); - base::mr_expr(expand_parse_call(cx, sp, ~"parse_stmt", + base::MRExpr(expand_parse_call(cx, sp, ~"parse_stmt", ~[e_attrs], tts)) } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 3d012b393bb..3ade0bf86b1 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -32,56 +32,56 @@ export expand_include_bin; /* line!(): expands to the current line number */ fn expand_line(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { base::check_zero_tts(cx, sp, tts, "line!"); let loc = cx.codemap().lookup_char_pos(sp.lo); - base::mr_expr(mk_uint(cx, sp, loc.line)) + base::MRExpr(mk_uint(cx, sp, loc.line)) } /* col!(): expands to the current column number */ fn expand_col(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { base::check_zero_tts(cx, sp, tts, "col!"); let loc = cx.codemap().lookup_char_pos(sp.lo); - base::mr_expr(mk_uint(cx, sp, loc.col.to_uint())) + base::MRExpr(mk_uint(cx, sp, loc.col.to_uint())) } /* file!(): expands to the current filename */ /* The filemap (`loc.file`) contains a bunch more information we could spit * out if we wanted. */ fn expand_file(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { base::check_zero_tts(cx, sp, tts, "file!"); let Loc { file: @FileMap { name: filename, _ }, _ } = cx.codemap().lookup_char_pos(sp.lo); - base::mr_expr(mk_base_str(cx, sp, filename)) + base::MRExpr(mk_base_str(cx, sp, filename)) } fn expand_stringify(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let s = pprust::tts_to_str(tts, cx.parse_sess().interner); - base::mr_expr(mk_base_str(cx, sp, s)) + base::MRExpr(mk_base_str(cx, sp, s)) } fn expand_mod(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { base::check_zero_tts(cx, sp, tts, "module_path!"); - base::mr_expr(mk_base_str(cx, sp, + base::MRExpr(mk_base_str(cx, sp, str::connect(cx.mod_path().map( |x| cx.str_of(*x)), ~"::"))) } fn expand_include(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include!"); let p = parse::new_sub_parser_from_file( cx.parse_sess(), cx.cfg(), &res_rel_file(cx, sp, &Path(file)), sp); - base::mr_expr(p.parse_expr()) + base::MRExpr(p.parse_expr()) } fn expand_include_str(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include_str!"); let res = io::read_whole_file_str(&res_rel_file(cx, sp, &Path(file))); match res { @@ -91,18 +91,18 @@ fn expand_include_str(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) } } - base::mr_expr(mk_base_str(cx, sp, result::unwrap(res))) + base::MRExpr(mk_base_str(cx, sp, result::unwrap(res))) } fn expand_include_bin(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) - -> base::mac_result { + -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include_bin!"); match io::read_whole_file(&res_rel_file(cx, sp, &Path(file))) { result::Ok(src) => { let u8_exprs = vec::map(src, |char| { mk_u8(cx, sp, *char) }); - base::mr_expr(mk_base_vec_e(cx, sp, u8_exprs)) + base::MRExpr(mk_base_vec_e(cx, sp, u8_exprs)) } result::Err(ref e) => { cx.parse_sess().span_diagnostic.handler().fatal((*e)) diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index d5031b97718..e4ea46416d3 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -19,7 +19,7 @@ use parse::parser::Parser; use core::option::None; fn expand_trace_macros(cx: ext_ctxt, sp: span, - tt: ~[ast::token_tree]) -> base::mac_result { + tt: ~[ast::token_tree]) -> base::MacResult { let sess = cx.parse_sess(); let cfg = cx.cfg(); let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, @@ -39,5 +39,5 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, let rust_parser = Parser(sess, cfg, rdr.dup()); let result = rust_parser.parse_expr(); - base::mr_expr(result) + base::MRExpr(result) } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 4ee9ddf48c8..bcaa7679a5a 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -15,7 +15,7 @@ use ast::{tt_delim}; use ast; use ast_util::dummy_sp; use codemap::span; -use ext::base::{ext_ctxt, mac_result, mr_any, mr_def, normal_tt}; +use ext::base::{ext_ctxt, MacResult, MRAny, MRDef, MacroDef, NormalTT}; use ext::base; use ext::tt::macro_parser::{error}; use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; @@ -30,7 +30,7 @@ use core::io; use std::map::HashMap; fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, - arg: ~[ast::token_tree]) -> base::mac_result { + arg: ~[ast::token_tree]) -> base::MacResult { // these spans won't matter, anyways fn ms(m: matcher_) -> matcher { ast::spanned { node: m, span: dummy_sp() } @@ -73,7 +73,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, fn generic_extension(cx: ext_ctxt, sp: span, name: ident, arg: ~[ast::token_tree], lhses: ~[@named_match], rhses: ~[@named_match]) - -> mac_result { + -> MacResult { if cx.trace_macros() { io::println(fmt!("%s! { %s }", @@ -119,7 +119,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, // Let the context choose how to interpret the result. // Weird, but useful for X-macros. - return mr_any(|| p.parse_expr(), + return MRAny(|| p.parse_expr(), || p.parse_item(~[/* no attrs*/]), || p.parse_stmt(~[/* no attrs*/])); } @@ -136,14 +136,11 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, cx.span_fatal(best_fail_spot, best_fail_msg); } - let exp: @fn(ext_ctxt, span, ~[ast::token_tree]) -> mac_result = + let exp: @fn(ext_ctxt, span, ~[ast::token_tree]) -> MacResult = |cx, sp, arg| generic_extension(cx, sp, name, arg, lhses, rhses); - mr_def(base::macro_def { + return MRDef(MacroDef{ name: *cx.parse_sess().interner.get(name), - ext: normal_tt(base::syntax_expander_tt { - expander: exp, - span: Some(sp), - }) - }) + ext: NormalTT(base::SyntaxExpanderTT{expander: exp, span: Some(sp)}) + }); } diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 573c36e619b..1574a037a46 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -157,11 +157,13 @@ fn byte_offset(rdr: string_reader) -> BytePos { (rdr.pos - rdr.filemap.start_pos) } -fn get_str_from(rdr: string_reader, start: BytePos) -> ~str unsafe { - // I'm pretty skeptical about this subtraction. What if there's a - // multi-byte character before the mark? - return str::slice(*rdr.src, start.to_uint() - 1u, - byte_offset(rdr).to_uint() - 1u); +fn get_str_from(rdr: string_reader, start: BytePos) -> ~str { + unsafe { + // I'm pretty skeptical about this subtraction. What if there's a + // multi-byte character before the mark? + return str::slice(*rdr.src, start.to_uint() - 1u, + byte_offset(rdr).to_uint() - 1u); + } } fn bump(rdr: string_reader) { diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 15905c090db..67f6c4bed3f 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -44,7 +44,8 @@ pub enum ObsoleteSyntax { ObsoletePrivSection, ObsoleteModeInFnType, ObsoleteMoveInit, - ObsoleteBinaryMove + ObsoleteBinaryMove, + ObsoleteUnsafeBlock } impl ObsoleteSyntax : cmp::Eq { @@ -118,6 +119,10 @@ impl Parser { ObsoleteBinaryMove => ( "binary move", "Write `foo = move bar` instead" + ), + ObsoleteUnsafeBlock => ( + "non-standalone unsafe block", + "use an inner `unsafe { ... }` block instead" ) }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 61105f6297d..2b1312f16d9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -69,6 +69,7 @@ use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator}; use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove}; use parse::obsolete::{ObsoleteStructCtor, ObsoleteWith, ObsoleteClassMethod}; use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds}; +use parse::obsolete::{ObsoleteUnsafeBlock}; use parse::prec::{as_prec, token_to_binop}; use parse::token::{can_begin_expr, is_ident, is_ident_or_path}; use parse::token::{is_plain_ident, INTERPOLATED, special_idents}; @@ -2336,12 +2337,13 @@ impl Parser { } let lo = self.span.lo; - let us = self.eat_keyword(~"unsafe"); + if self.eat_keyword(~"unsafe") { + self.obsolete(copy self.span, ObsoleteUnsafeBlock); + } self.expect(token::LBRACE); let {inner: move inner, next: move next} = maybe_parse_inner_attrs_and_next(self, parse_attrs); - let blk_check_mode = if us { unsafe_blk } else { default_blk }; - return (inner, self.parse_block_tail_(lo, blk_check_mode, next)); + return (inner, self.parse_block_tail_(lo, default_blk, next)); } fn parse_block_no_value() -> blk { @@ -2531,6 +2533,10 @@ impl Parser { } else { break; } + + if self.eat(token::BINOP(token::PLUS)) { + // Should be `break;` but that isn't backwards compatible. + } } } return @move bounds; @@ -3646,7 +3652,8 @@ impl Parser { visibility, maybe_append(attrs, extra_attrs))); } else if foreign_items_allowed && - (self.is_keyword(~"fn") || self.is_keyword(~"pure")) { + (self.is_keyword(~"fn") || self.is_keyword(~"pure") || + self.is_keyword(~"unsafe")) { let item = self.parse_item_foreign_fn(attrs); return iovi_foreign_item(item); } else if items_allowed && self.is_keyword(~"unsafe") diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 93c03063623..2136499f8f0 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -200,19 +200,24 @@ fn to_str(in: @ident_interner, t: Token) -> ~str { DOC_COMMENT(s) => *in.get(s), EOF => ~"<eof>", INTERPOLATED(ref nt) => { - ~"an interpolated " + - match (*nt) { - nt_item(*) => ~"item", - nt_block(*) => ~"block", - nt_stmt(*) => ~"statement", - nt_pat(*) => ~"pattern", - nt_expr(*) => ~"expression", - nt_ty(*) => ~"type", - nt_ident(*) => ~"identifier", - nt_path(*) => ~"path", - nt_tt(*) => ~"tt", - nt_matchers(*) => ~"matcher sequence" + match nt { + &nt_expr(e) => ::print::pprust::expr_to_str(e, in), + _ => { + ~"an interpolated " + + match (*nt) { + nt_item(*) => ~"item", + nt_block(*) => ~"block", + nt_stmt(*) => ~"statement", + nt_pat(*) => ~"pattern", + nt_expr(*) => fail ~"should have been handled above", + nt_ty(*) => ~"type", + nt_ident(*) => ~"identifier", + nt_path(*) => ~"path", + nt_tt(*) => ~"tt", + nt_matchers(*) => ~"matcher sequence" + } } + } } } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index b3b267027ce..6bc23aa1271 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -142,9 +142,9 @@ fn mk_printer(out: io::Writer, linewidth: uint) -> printer { // fall behind. let n: uint = 3 * linewidth; debug!("mk_printer %u", linewidth); - let token: ~[mut token] = vec::to_mut(vec::from_elem(n, EOF)); - let size: ~[mut int] = vec::to_mut(vec::from_elem(n, 0)); - let scan_stack: ~[mut uint] = vec::to_mut(vec::from_elem(n, 0u)); + let token: ~[mut token] = vec::cast_to_mut(vec::from_elem(n, EOF)); + let size: ~[mut int] = vec::cast_to_mut(vec::from_elem(n, 0)); + let scan_stack: ~[mut uint] = vec::cast_to_mut(vec::from_elem(n, 0u)); printer_(@{out: out, buf_len: n, mut margin: linewidth as int, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 31ad0bd6ca8..baeb437152c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -172,15 +172,15 @@ fn fun_to_str(decl: ast::fn_decl, name: ast::ident, #[test] fn test_fun_to_str() { - let decl: ast::fn_decl = { + let decl: ast::fn_decl = ast::fn_decl { inputs: ~[], - output: @{id: 0, + output: @ast::Ty {id: 0, node: ast::ty_nil, span: ast_util::dummy_sp()}, - purity: ast::impure_fn, + //purity: ast::impure_fn, cf: ast::return_val }; - assert fun_to_str(decl, "a", ~[]) == "fn a()"; + assert fun_to_str(decl, "abba", ~[]) == "fn abba()"; } fn block_to_str(blk: ast::blk, intr: @ident_interner) -> ~str { @@ -214,7 +214,7 @@ fn test_variant_to_str() { attrs: ~[], args: ~[], id: 0, - disr_expr: none + disr_expr: None }); let varstr = variant_to_str(var); @@ -1791,8 +1791,15 @@ fn print_arg_mode(s: ps, m: ast::mode) { fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) { if bounds.is_not_empty() { word(s.s, ~":"); + let mut first = true; for vec::each(*bounds) |&bound| { nbsp(s); + if first { + first = false; + } else { + word_space(s, ~"+"); + } + match bound { TraitTyParamBound(ty) => print_type(s, ty), RegionTyParamBound => word(s.s, ~"&static"), diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index fd759a32941..e4a09c3c349 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -29,7 +29,7 @@ fn mk<T:Eq IterBytes Hash Const Copy>() -> Interner<T> { move ((move hi) as Interner::<T>) } -fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> Interner<T> { +fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: &[T]) -> Interner<T> { let rv = mk(); for init.each() |v| { rv.intern(*v); } return rv; @@ -70,3 +70,45 @@ impl <T:Eq IterBytes Hash Const Copy> hash_interner<T>: Interner<T> { fn len() -> uint { return self.vect.len(); } } + + +#[test] +#[should_fail] +fn i1 () { + let i : Interner<@~str> = mk(); + i.get(13); +} + +#[test] +fn i2 () { + let i : Interner<@~str> = mk(); + // first one is zero: + assert i.intern (@~"dog") == 0; + // re-use gets the same entry: + assert i.intern (@~"dog") == 0; + // different string gets a different #: + assert i.intern (@~"cat") == 1; + assert i.intern (@~"cat") == 1; + // dog is still at zero + assert i.intern (@~"dog") == 0; + // gensym gets 3 + assert i.gensym (@~"zebra" ) == 2; + // gensym of same string gets new number : + assert i.gensym (@~"zebra" ) == 3; + // gensym of *existing* string gets new number: + assert i.gensym (@~"dog") == 4; + assert i.get(0) == @~"dog"; + assert i.get(1) == @~"cat"; + assert i.get(2) == @~"zebra"; + assert i.get(3) == @~"zebra"; + assert i.get(4) == @~"dog"; +} + +#[test] +fn i3 () { + let i : Interner<@~str> = mk_prefill([@~"Alan",@~"Bob",@~"Carol"]); + assert i.get(0) == @~"Alan"; + assert i.get(1) == @~"Bob"; + assert i.get(2) == @~"Carol"; + assert i.intern(@~"Bob") == 1; +} diff --git a/src/libuv b/src/libuv -Subproject 1170ffba3ac5191930b40c897d4569a9d8a296a +Subproject 4d392c86feb6389f550d8110d36fa90d66c0925 diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index 2b1a8a29dbb..a14cc3758b1 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -35,8 +35,10 @@ fn arc<T: Const>(_data: T) -> arc_destruct<T> { arc_destruct(0) } -fn init() -> arc_destruct<context_res> unsafe { - arc(context_res()) +fn init() -> arc_destruct<context_res> { + unsafe { + arc(context_res()) + } } struct context_res { diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 45fec9edeb9..58cc6a1513c 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -122,7 +122,7 @@ fn gen_search_keys(graph: graph, n: uint) -> ~[node_id] { */ fn bfs(graph: graph, key: node_id) -> bfs_result { let marks : ~[mut node_id] - = vec::to_mut(vec::from_elem(vec::len(graph), -1i64)); + = vec::cast_to_mut(vec::from_elem(vec::len(graph), -1i64)); let Q = deque::create(); @@ -141,7 +141,7 @@ fn bfs(graph: graph, key: node_id) -> bfs_result { }; } - vec::from_mut(move marks) + vec::cast_from_mut(move marks) } /** diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs new file mode 100644 index 00000000000..a07dcee35f4 --- /dev/null +++ b/src/test/bench/noise.rs @@ -0,0 +1,110 @@ +// Perlin noise benchmark from https://gist.github.com/1170424 + +struct Vec2 { + x: f32, + y: f32, +} + +fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } +fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } + +fn random_gradient(r: rand::Rng) -> Vec2 { + let v = r.gen_float() * float::consts::pi * 2.0; + Vec2{ + x: float::cos(v) as f32, + y: float::sin(v) as f32, + } +} + +fn gradient(orig: Vec2, grad: Vec2, p: Vec2) -> f32 { + let sp = Vec2{x: p.x - orig.x, y: p.y - orig.y}; + grad.x * sp.x + grad.y + sp.y +} + +struct Noise2DContext { + rgradients: [Vec2 * 256], + permutations: [int * 256], +} + +fn Noise2DContext() -> ~Noise2DContext { + let r = rand::Rng(); + let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ]; + for int::range(0, 256) |i| { rgradients[i] = random_gradient(r); } + let mut permutations = [ 0, ..256 ]; + for int::range(0, 256) |i| { permutations[i] = i; } + r.shuffle_mut(permutations); + + ~Noise2DContext{ + rgradients: move rgradients, + permutations: move permutations, + } +} + +impl Noise2DContext { + #[inline(always)] + fn get_gradient(&self, x: int, y: int) -> Vec2 { + let idx = self.permutations[x & 255] + self.permutations[y & 255]; + self.rgradients[idx & 255] + } + + #[inline(always)] + fn get_gradients(&self, gradients: &mut [Vec2 * 4], origins: &mut [Vec2 * 4], x: f32, y: f32) { + let x0f = f32::floor(x); + let y0f = f32::floor(y); + let x0 = x0f as int; + let y0 = y0f as int; + let x1 = x0 + 1; + let y1 = y0 + 1; + + gradients[0] = self.get_gradient(x0, y0); + gradients[1] = self.get_gradient(x1, y0); + gradients[2] = self.get_gradient(x0, y1); + gradients[3] = self.get_gradient(x1, y1); + + origins[0] = Vec2{x: x0f + 0.0, y: y0f + 0.0}; + origins[1] = Vec2{x: x0f + 1.0, y: y0f + 0.0}; + origins[2] = Vec2{x: x0f + 0.0, y: y0f + 1.0}; + origins[3] = Vec2{x: x0f + 1.0, y: y0f + 1.0}; + } + + fn get(&self, x: f32, y: f32) -> f32 { + let p = Vec2{x: x, y: y}; + let mut gradients = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; + let mut origins = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; + self.get_gradients(&mut gradients, &mut origins, x, y); + let v0 = gradient(origins[0], gradients[0], p); + let v1 = gradient(origins[1], gradients[1], p); + let v2 = gradient(origins[2], gradients[2], p); + let v3 = gradient(origins[3], gradients[3], p); + let fx = smooth(x - origins[0].x); + let vx0 = lerp(v0, v1, fx); + let vx1 = lerp(v2, v3, fx); + let fy = smooth(y - origins[0].y); + lerp(vx0, vx1, fy) + } +} + +fn main() { + let symbols = [" ", "░", "▒", "▓", "█", "█"]; + let mut pixels = vec::from_elem(256*256, 0f32); + let n2d = Noise2DContext(); + for int::range(0, 100) |_| { + for int::range(0, 256) |y| { + for int::range(0, 256) |x| { + let v = n2d.get( + x as f32 * 0.1f32, + y as f32 * 0.1f32 + ) * 0.5f32 + 0.5f32; + pixels[y*256+x] = v; + }; + }; + }; + + /*for int::range(0, 256) |y| { + for int::range(0, 256) |x| { + io::print(symbols[pixels[y*256+x] / 0.2f32 as int]); + } + io::println(""); + }*/ +} + diff --git a/src/test/bench/shootout-fannkuchredux.rs b/src/test/bench/shootout-fannkuchredux.rs index d65cc199290..bb790a94ae4 100644 --- a/src/test/bench/shootout-fannkuchredux.rs +++ b/src/test/bench/shootout-fannkuchredux.rs @@ -14,9 +14,9 @@ extern mod std; fn fannkuch(n: int) -> int { fn perm1init(i: uint) -> int { return i as int; } - let perm = vec::to_mut(vec::from_elem(n as uint, 0)); - let perm1 = vec::to_mut(vec::from_fn(n as uint, |i| perm1init(i))); - let count = vec::to_mut(vec::from_elem(n as uint, 0)); + let perm = vec::cast_to_mut(vec::from_elem(n as uint, 0)); + let perm1 = vec::cast_to_mut(vec::from_fn(n as uint, |i| perm1init(i))); + let count = vec::cast_to_mut(vec::from_elem(n as uint, 0)); let mut f = 0; let mut i = 0; let mut k = 0; diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 4a03ab6ae65..ffb32181dc4 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -64,18 +64,20 @@ fn make_random_fasta(wr: io::Writer, id: ~str, desc: ~str, genelist: ~[aminoacid if str::len(op) > 0u { wr.write_line(op); } } -fn make_repeat_fasta(wr: io::Writer, id: ~str, desc: ~str, s: ~str, n: int) unsafe { - wr.write_line(~">" + id + ~" " + desc); - let mut op: ~str = ~""; - let sl: uint = str::len(s); - for uint::range(0u, n as uint) |i| { - str::raw::push_byte(&mut op, s[i % sl]); - if str::len(op) >= LINE_LENGTH() { - wr.write_line(op); - op = ~""; +fn make_repeat_fasta(wr: io::Writer, id: ~str, desc: ~str, s: ~str, n: int) { + unsafe { + wr.write_line(~">" + id + ~" " + desc); + let mut op: ~str = ~""; + let sl: uint = str::len(s); + for uint::range(0u, n as uint) |i| { + str::raw::push_byte(&mut op, s[i % sl]); + if str::len(op) >= LINE_LENGTH() { + wr.write_line(op); + op = ~""; + } } + if str::len(op) > 0u { wr.write_line(op); } } - if str::len(op) > 0u { wr.write_line(op); } } fn acid(ch: char, prob: u32) -> aminoacids { return {ch: ch, prob: prob}; } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 99b9b4a55f5..a2f83e3f84f 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -151,7 +151,7 @@ fn main() { // initialize each sequence sorter let sizes = ~[1,2,3,4,6,12,18]; let streams = vec::map(sizes, |_sz| Some(stream())); - let streams = vec::to_mut(move streams); + let streams = vec::cast_to_mut(move streams); let mut from_child = ~[]; let to_child = vec::mapi(sizes, |ii, sz| { let sz = *sz; diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index 1c0a70c32a2..75e277e3379 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -98,23 +98,25 @@ mod NBodySystem { pub fn advance_one(bi: &mut Body::props, bj: &mut Body::props, - dt: float) unsafe { - let dx = bi.x - bj.x; - let dy = bi.y - bj.y; - let dz = bi.z - bj.z; + dt: float) { + unsafe { + let dx = bi.x - bj.x; + let dy = bi.y - bj.y; + let dz = bi.z - bj.z; - let dSquared = dx * dx + dy * dy + dz * dz; + let dSquared = dx * dx + dy * dy + dz * dz; - let distance = ::libc::sqrt(dSquared); - let mag = dt / (dSquared * distance); + let distance = ::libc::sqrt(dSquared); + let mag = dt / (dSquared * distance); - bi.vx -= dx * bj.mass * mag; - bi.vy -= dy * bj.mass * mag; - bi.vz -= dz * bj.mass * mag; + bi.vx -= dx * bj.mass * mag; + bi.vy -= dy * bj.mass * mag; + bi.vz -= dz * bj.mass * mag; - bj.vx += dx * bi.mass * mag; - bj.vy += dy * bi.mass * mag; - bj.vz += dz * bi.mass * mag; + bj.vx += dx * bi.mass * mag; + bj.vy += dy * bi.mass * mag; + bj.vz += dz * bi.mass * mag; + } } pub fn move_(b: &mut Body::props, dt: float) { @@ -123,36 +125,41 @@ mod NBodySystem { b.z += dt * b.vz; } - pub fn energy(bodies: &[Body::props]) -> float unsafe { - let mut dx; - let mut dy; - let mut dz; - let mut distance; - let mut e = 0.0; - - let mut i = 0; - while i < 5 { - e += - 0.5 * bodies[i].mass * - (bodies[i].vx * bodies[i].vx + bodies[i].vy * bodies[i].vy - + bodies[i].vz * bodies[i].vz); - - let mut j = i + 1; - while j < 5 { - dx = bodies[i].x - bodies[j].x; - dy = bodies[i].y - bodies[j].y; - dz = bodies[i].z - bodies[j].z; - - distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz); - e -= bodies[i].mass * bodies[j].mass / distance; - - j += 1; + pub fn energy(bodies: &[Body::props]) -> float { + unsafe { + let mut dx; + let mut dy; + let mut dz; + let mut distance; + let mut e = 0.0; + + let mut i = 0; + while i < 5 { + e += + 0.5 * bodies[i].mass * + (bodies[i].vx * bodies[i].vx + + bodies[i].vy * bodies[i].vy + + bodies[i].vz * bodies[i].vz); + + let mut j = i + 1; + while j < 5 { + dx = bodies[i].x - bodies[j].x; + dy = bodies[i].y - bodies[j].y; + dz = bodies[i].z - bodies[j].z; + + distance = ::libc::sqrt(dx * dx + + dy * dy + + dz * dz); + e -= bodies[i].mass + * bodies[j].mass / distance; + + j += 1; + } + + i += 1; } - - i += 1; + return e; } - return e; - } } diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index b6ee45417d5..89827c8be77 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -45,7 +45,7 @@ fn eval_At_times_u(u: &[const float], Au: &[mut float]) { } fn eval_AtA_times_u(u: &[const float], AtAu: &[mut float]) { - let v = vec::to_mut(vec::from_elem(vec::len(u), 0.0)); + let v = vec::cast_to_mut(vec::from_elem(vec::len(u), 0.0)); eval_A_times_u(u, v); eval_At_times_u(v, AtAu); } @@ -62,8 +62,8 @@ fn main() { let N = uint::from_str(args[1]).get(); - let u = vec::to_mut(vec::from_elem(N, 1.0)); - let v = vec::to_mut(vec::from_elem(N, 0.0)); + let u = vec::cast_to_mut(vec::from_elem(N, 1.0)); + let v = vec::cast_to_mut(vec::from_elem(N, 0.0)); let mut i = 0u; while i < 10u { eval_AtA_times_u(u, v); diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 0dc91bbdfb4..ffd169c7081 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -42,7 +42,7 @@ fn read_grid(f: io::Reader) -> grid_t { assert f.read_line() == ~"9,9"; /* assert first line is exactly "9,9" */ let g = vec::from_fn(10u, {|_i| - vec::to_mut(vec::from_elem(10u, 0 as u8)) + vec::cast_to_mut(vec::from_elem(10u, 0 as u8)) }); while !f.eof() { let comps = str::split_char(str::trim(f.read_line()), ','); @@ -142,7 +142,7 @@ fn main() { // FIXME create sudoku inline since nested vec consts dont work yet // (#3733) let g = vec::from_fn(10u, |_i| { - vec::to_mut(vec::from_elem(10u, 0 as u8)) + vec::cast_to_mut(vec::from_elem(10u, 0 as u8)) }); g[0][1] = 4u8; g[0][3] = 6u8; diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs new file mode 100644 index 00000000000..d8443f836f5 --- /dev/null +++ b/src/test/compile-fail/eval-enum.rs @@ -0,0 +1,6 @@ +enum test { + div_zero = 1/0, //~ERROR expected constant: divide by zero + rem_zero = 1%0 //~ERROR expected constant: modulo zero +} + +fn main() {} diff --git a/src/test/run-fail/assert-as-macro.rs b/src/test/run-fail/assert-as-macro.rs new file mode 100644 index 00000000000..8bb1e278fd1 --- /dev/null +++ b/src/test/run-fail/assert-as-macro.rs @@ -0,0 +1,6 @@ +// error-pattern:assertion failed: 1 == 2 + +fn main() { + fail_unless!(1 == 2); +} + diff --git a/src/test/run-fail/too-much-recursion-unwinding.rs b/src/test/run-fail/too-much-recursion-unwinding.rs index f1629a2c4b2..b6a9bce934f 100644 --- a/src/test/run-fail/too-much-recursion-unwinding.rs +++ b/src/test/run-fail/too-much-recursion-unwinding.rs @@ -21,20 +21,24 @@ fn recurse() { struct r { recursed: *mut bool, - drop unsafe { - if !*(self.recursed) { - *(self.recursed) = true; - recurse(); + drop { + unsafe { + if !*(self.recursed) { + *(self.recursed) = true; + recurse(); + } } } } -fn r(recursed: *mut bool) -> r unsafe { - r { recursed: recursed } +fn r(recursed: *mut bool) -> r { + unsafe { + r { recursed: recursed } + } } fn main() { let mut recursed = false; let _r = r(ptr::mut_addr_of(&recursed)); recurse(); -} \ No newline at end of file +} diff --git a/src/test/run-fail/unwind-box-res.rs b/src/test/run-fail/unwind-box-res.rs index 751bd749828..b38651b3165 100644 --- a/src/test/run-fail/unwind-box-res.rs +++ b/src/test/run-fail/unwind-box-res.rs @@ -32,11 +32,13 @@ fn r(v: *int) -> r { } } -fn main() unsafe { - let i1 = ~0; - let i1p = cast::reinterpret_cast(&i1); - cast::forget(move i1); - let x = @r(i1p); - failfn(); - log(error, x); +fn main() { + unsafe { + let i1 = ~0; + let i1p = cast::reinterpret_cast(&i1); + cast::forget(move i1); + let x = @r(i1p); + failfn(); + log(error, x); + } } diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index 04cc55b2264..4f58e41766b 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -62,19 +62,21 @@ fn test_box() { assert (@10 == @10); } -fn test_ptr() unsafe { - let p1: *u8 = ::core::cast::reinterpret_cast(&0); - let p2: *u8 = ::core::cast::reinterpret_cast(&0); - let p3: *u8 = ::core::cast::reinterpret_cast(&1); +fn test_ptr() { + unsafe { + let p1: *u8 = ::core::cast::reinterpret_cast(&0); + let p2: *u8 = ::core::cast::reinterpret_cast(&0); + let p3: *u8 = ::core::cast::reinterpret_cast(&1); - assert p1 == p2; - assert p1 != p3; - assert p1 < p3; - assert p1 <= p3; - assert p3 > p1; - assert p3 >= p3; - assert p1 <= p2; - assert p1 >= p2; + assert p1 == p2; + assert p1 != p3; + assert p1 < p3; + assert p1 <= p3; + assert p3 > p1; + assert p3 >= p3; + assert p1 <= p2; + assert p1 >= p2; + } } #[abi = "cdecl"] diff --git a/src/test/run-pass/extern-pub.rs b/src/test/run-pass/extern-pub.rs new file mode 100644 index 00000000000..92e580253a8 --- /dev/null +++ b/src/test/run-pass/extern-pub.rs @@ -0,0 +1,10 @@ +extern { + pub unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc, + ++v: **vec::raw::VecRepr, + ++n: libc::size_t); +} + +fn main() { +} + + diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index c598d56f8dc..9df30d90d1c 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -19,10 +19,12 @@ extern mod libc { fn my_strlen(str: *u8) -> uint; } -fn strlen(str: ~str) -> uint unsafe { - // C string is terminated with a zero - let bytes = str::to_bytes(str) + ~[0u8]; - return libc::my_strlen(vec::raw::to_ptr(bytes)); +fn strlen(str: ~str) -> uint { + unsafe { + // C string is terminated with a zero + let bytes = str::to_bytes(str) + ~[0u8]; + return libc::my_strlen(vec::raw::to_ptr(bytes)); + } } fn main() { diff --git a/src/test/run-pass/import-in-block.rs b/src/test/run-pass/import-in-block.rs index 58b45f3d5f8..56756086a26 100644 --- a/src/test/run-pass/import-in-block.rs +++ b/src/test/run-pass/import-in-block.rs @@ -9,8 +9,8 @@ // except according to those terms. fn main() { - use vec::to_mut; - log(debug, vec::len(to_mut(~[1, 2]))); + use vec::cast_to_mut; + log(debug, vec::len(cast_to_mut(~[1, 2]))); { use vec::*; log(debug, len(~[2])); diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs index efa6d05f9da..c15616d9f9f 100644 --- a/src/test/run-pass/issue-2214.rs +++ b/src/test/run-pass/issue-2214.rs @@ -14,8 +14,10 @@ use core::cast; use core::libc::{c_double, c_int}; use core::f64::*; -fn to_c_int(v: &mut int) -> &mut c_int unsafe { - cast::reinterpret_cast(&v) +fn to_c_int(v: &mut int) -> &mut c_int { + unsafe { + cast::reinterpret_cast(&v) + } } fn lgamma(n: c_double, value: &mut int) -> c_double { diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 7c35c9e8cf1..871d349b24b 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -34,13 +34,15 @@ pub mod pipes { mut payload: Option<T> }; - pub fn packet<T: Owned>() -> *packet<T> unsafe { - let p: *packet<T> = cast::transmute(~{ - mut state: empty, - mut blocked_task: None::<task::Task>, - mut payload: None::<T> - }); - p + pub fn packet<T: Owned>() -> *packet<T> { + unsafe { + let p: *packet<T> = cast::transmute(~{ + mut state: empty, + mut blocked_task: None::<task::Task>, + mut payload: None::<T> + }); + p + } } #[abi = "rust-intrinsic"] @@ -218,22 +220,26 @@ pub mod pingpong { pub enum ping = ::pipes::send_packet<pong>; pub enum pong = ::pipes::send_packet<ping>; - pub fn liberate_ping(-p: ping) -> ::pipes::send_packet<pong> unsafe { - let addr : *::pipes::send_packet<pong> = match &p { - &ping(ref x) => { cast::transmute(ptr::addr_of(x)) } - }; - let liberated_value = move *addr; - cast::forget(move p); - move liberated_value + pub fn liberate_ping(-p: ping) -> ::pipes::send_packet<pong> { + unsafe { + let addr : *::pipes::send_packet<pong> = match &p { + &ping(ref x) => { cast::transmute(ptr::addr_of(x)) } + }; + let liberated_value = move *addr; + cast::forget(move p); + move liberated_value + } } - pub fn liberate_pong(-p: pong) -> ::pipes::send_packet<ping> unsafe { - let addr : *::pipes::send_packet<ping> = match &p { - &pong(ref x) => { cast::transmute(ptr::addr_of(x)) } - }; - let liberated_value = move *addr; - cast::forget(move p); - move liberated_value + pub fn liberate_pong(-p: pong) -> ::pipes::send_packet<ping> { + unsafe { + let addr : *::pipes::send_packet<ping> = match &p { + &pong(ref x) => { cast::transmute(ptr::addr_of(x)) } + }; + let liberated_value = move *addr; + cast::forget(move p); + move liberated_value + } } pub fn init() -> (client::ping, server::ping) { diff --git a/src/test/run-pass/issue-2723-b.rs b/src/test/run-pass/issue-2723-b.rs index 90e26c7bd8b..9a0fbdfb77a 100644 --- a/src/test/run-pass/issue-2723-b.rs +++ b/src/test/run-pass/issue-2723-b.rs @@ -14,6 +14,8 @@ extern mod issue_2723_a; use issue_2723_a::*; -fn main() unsafe { - f(~[2]); -} \ No newline at end of file +fn main() { + unsafe { + f(~[2]); + } +} diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index 4517ce770ae..50ca15cbd1d 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -72,7 +72,7 @@ fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt { let mut line = ~[]; vec::grow_set(&mut line, width-1, &'.', '.'); - push(vec::to_mut(line)); + push(vec::cast_to_mut(line)); } }; diff --git a/src/test/run-pass/loop-unsafe.rs b/src/test/run-pass/loop-unsafe.rs deleted file mode 100644 index 2ab4989f52c..00000000000 --- a/src/test/run-pass/loop-unsafe.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that "loop unsafe" isn't misparsed. - -fn main() { - loop unsafe { - io::println("Hello world!"); - return (); - } -} - diff --git a/src/test/run-pass/multiple-trait-bounds.rs b/src/test/run-pass/multiple-trait-bounds.rs new file mode 100644 index 00000000000..e64b51888ef --- /dev/null +++ b/src/test/run-pass/multiple-trait-bounds.rs @@ -0,0 +1,7 @@ +fn f<T:Eq + Ord>(_: T) { +} + +fn main() { + f(3); +} + diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs index 054c29c2a05..09de1650027 100644 --- a/src/test/run-pass/regions-mock-trans.rs +++ b/src/test/run-pass/regions-mock-trans.rs @@ -23,9 +23,11 @@ type ccx = { x: int }; -fn alloc(_bcx : &arena) -> &bcx unsafe { - return cast::reinterpret_cast( - &libc::malloc(sys::size_of::<bcx/&blk>() as libc::size_t)); +fn alloc(_bcx : &arena) -> &bcx { + unsafe { + return cast::reinterpret_cast( + &libc::malloc(sys::size_of::<bcx/&blk>() as libc::size_t)); + } } fn h(bcx : &bcx) -> &bcx { diff --git a/src/test/run-pass/resource-cycle.rs b/src/test/run-pass/resource-cycle.rs index e4f38c4750a..80aaad5c90f 100644 --- a/src/test/run-pass/resource-cycle.rs +++ b/src/test/run-pass/resource-cycle.rs @@ -26,9 +26,11 @@ impl r : Drop { } } -fn r(v: *int) -> r unsafe { - r { - v: v +fn r(v: *int) -> r { + unsafe { + r { + v: v + } } } @@ -37,41 +39,43 @@ enum t = { r: r }; -fn main() unsafe { - let i1 = ~0; - let i1p = cast::reinterpret_cast(&i1); - cast::forget(move i1); - let i2 = ~0; - let i2p = cast::reinterpret_cast(&i2); - cast::forget(move i2); +fn main() { + unsafe { + let i1 = ~0; + let i1p = cast::reinterpret_cast(&i1); + cast::forget(move i1); + let i2 = ~0; + let i2p = cast::reinterpret_cast(&i2); + cast::forget(move i2); - let x1 = @t({ - mut next: None, - r: { - let rs = r(i1p); - debug!("r = %x", - cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); - move rs } - }); - - debug!("x1 = %x, x1.r = %x", - cast::reinterpret_cast::<@t, uint>(&x1), - cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x1.r)))); + let x1 = @t({ + mut next: None, + r: { + let rs = r(i1p); + debug!("r = %x", + cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); + move rs } + }); + + debug!("x1 = %x, x1.r = %x", + cast::reinterpret_cast::<@t, uint>(&x1), + cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x1.r)))); - let x2 = @t({ - mut next: None, - r: { - let rs = r(i2p); - debug!("r2 = %x", - cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); - move rs - } - }); - - debug!("x2 = %x, x2.r = %x", - cast::reinterpret_cast::<@t, uint>(&x2), - cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x2.r)))); + let x2 = @t({ + mut next: None, + r: { + let rs = r(i2p); + debug!("r2 = %x", + cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); + move rs + } + }); + + debug!("x2 = %x, x2.r = %x", + cast::reinterpret_cast::<@t, uint>(&x2), + cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x2.r)))); - x1.next = Some(x2); - x2.next = Some(x1); + x1.next = Some(x2); + x2.next = Some(x1); + } } diff --git a/src/test/run-pass/resource-cycle2.rs b/src/test/run-pass/resource-cycle2.rs index a1dfecb4aba..3a1f6d812a8 100644 --- a/src/test/run-pass/resource-cycle2.rs +++ b/src/test/run-pass/resource-cycle2.rs @@ -39,25 +39,27 @@ enum t = { r: r }; -fn main() unsafe { - let i1 = ~0xA; - let i1p = cast::reinterpret_cast(&i1); - cast::forget(move i1); - let i2 = ~0xA; - let i2p = cast::reinterpret_cast(&i2); - cast::forget(move i2); - - let u1 = {a: 0xB, b: 0xC, c: i1p}; - let u2 = {a: 0xB, b: 0xC, c: i2p}; - - let x1 = @t({ - mut next: None, - r: r(u1) - }); - let x2 = @t({ - mut next: None, - r: r(u2) - }); - x1.next = Some(x2); - x2.next = Some(x1); +fn main() { + unsafe { + let i1 = ~0xA; + let i1p = cast::reinterpret_cast(&i1); + cast::forget(move i1); + let i2 = ~0xA; + let i2p = cast::reinterpret_cast(&i2); + cast::forget(move i2); + + let u1 = {a: 0xB, b: 0xC, c: i1p}; + let u2 = {a: 0xB, b: 0xC, c: i2p}; + + let x1 = @t({ + mut next: None, + r: r(u1) + }); + let x2 = @t({ + mut next: None, + r: r(u2) + }); + x1.next = Some(x2); + x2.next = Some(x1); + } } diff --git a/src/test/run-pass/resource-cycle3.rs b/src/test/run-pass/resource-cycle3.rs index 0e5bac0642f..7a4e9e6faf5 100644 --- a/src/test/run-pass/resource-cycle3.rs +++ b/src/test/run-pass/resource-cycle3.rs @@ -33,11 +33,13 @@ impl r : Drop { } } -fn r(v: u, w: int, _x: *int) -> r unsafe { - r { - v: v, - w: w, - x: cast::reinterpret_cast(&0) +fn r(v: u, w: int, _x: *int) -> r { + unsafe { + r { + v: v, + w: w, + x: cast::reinterpret_cast(&0) + } } } @@ -46,25 +48,27 @@ enum t = { r: r }; -fn main() unsafe { - let i1 = ~0xA; - let i1p = cast::reinterpret_cast(&i1); - cast::forget(move i1); - let i2 = ~0xA; - let i2p = cast::reinterpret_cast(&i2); - cast::forget(move i2); +fn main() { + unsafe { + let i1 = ~0xA; + let i1p = cast::reinterpret_cast(&i1); + cast::forget(move i1); + let i2 = ~0xA; + let i2p = cast::reinterpret_cast(&i2); + cast::forget(move i2); - let u1 = {a: 0xB, b: 0xC, c: i1p}; - let u2 = {a: 0xB, b: 0xC, c: i2p}; + let u1 = {a: 0xB, b: 0xC, c: i1p}; + let u2 = {a: 0xB, b: 0xC, c: i2p}; - let x1 = @t({ - mut next: None, - r: r(u1, 42, i1p) - }); - let x2 = @t({ - mut next: None, - r: r(u2, 42, i2p) - }); - x1.next = Some(x2); - x2.next = Some(x1); + let x1 = @t({ + mut next: None, + r: r(u1, 42, i1p) + }); + let x2 = @t({ + mut next: None, + r: r(u2, 42, i2p) + }); + x1.next = Some(x2); + x2.next = Some(x1); + } } diff --git a/src/test/run-pass/rt-sched-1.rs b/src/test/run-pass/rt-sched-1.rs index 09f9bee7527..5435efd40e4 100644 --- a/src/test/run-pass/rt-sched-1.rs +++ b/src/test/run-pass/rt-sched-1.rs @@ -24,25 +24,27 @@ extern mod rustrt { fn start_task(id: task_id, f: closure); } -fn main() unsafe { - let po = oldcomm::Port(); - let ch = oldcomm::Chan(&po); - let parent_sched_id = rustrt::rust_get_sched_id(); - error!("parent %?", parent_sched_id); - let num_threads = 1u; - let new_sched_id = rustrt::rust_new_sched(num_threads); - error!("new_sched_id %?", new_sched_id); - let new_task_id = rustrt::rust_new_task_in_sched(new_sched_id); - assert !new_task_id.is_null(); - let f = fn~() { - let child_sched_id = rustrt::rust_get_sched_id(); - error!("child_sched_id %?", child_sched_id); - assert child_sched_id != parent_sched_id; - assert child_sched_id == new_sched_id; - oldcomm::send(ch, ()); - }; - let fptr = cast::reinterpret_cast(&ptr::addr_of(&f)); - rustrt::start_task(new_task_id, fptr); - cast::forget(move f); - oldcomm::recv(po); +fn main() { + unsafe { + let po = oldcomm::Port(); + let ch = oldcomm::Chan(&po); + let parent_sched_id = rustrt::rust_get_sched_id(); + error!("parent %?", parent_sched_id); + let num_threads = 1u; + let new_sched_id = rustrt::rust_new_sched(num_threads); + error!("new_sched_id %?", new_sched_id); + let new_task_id = rustrt::rust_new_task_in_sched(new_sched_id); + assert !new_task_id.is_null(); + let f = fn~() { + let child_sched_id = rustrt::rust_get_sched_id(); + error!("child_sched_id %?", child_sched_id); + assert child_sched_id != parent_sched_id; + assert child_sched_id == new_sched_id; + oldcomm::send(ch, ()); + }; + let fptr = cast::reinterpret_cast(&ptr::addr_of(&f)); + rustrt::start_task(new_task_id, fptr); + cast::forget(move f); + oldcomm::recv(po); + } } diff --git a/src/test/run-pass/tag-variant-disr-val.rs b/src/test/run-pass/tag-variant-disr-val.rs index 472cc78e86a..64eb50cf0ff 100644 --- a/src/test/run-pass/tag-variant-disr-val.rs +++ b/src/test/run-pass/tag-variant-disr-val.rs @@ -37,7 +37,7 @@ fn main() { test_color(orange, 4, ~"orange"); } -fn test_color(color: color, val: int, name: ~str) unsafe { +fn test_color(color: color, val: int, name: ~str) { //assert unsafe::reinterpret_cast(color) == val; assert color as int == val; assert color as float == val as float; diff --git a/src/test/run-pass/typeclasses-eq-example.rs b/src/test/run-pass/typeclasses-eq-example.rs index c3a2ed2ca10..c3a2ed2ca10 100755..100644 --- a/src/test/run-pass/typeclasses-eq-example.rs +++ b/src/test/run-pass/typeclasses-eq-example.rs diff --git a/src/test/run-pass/unify-return-ty.rs b/src/test/run-pass/unify-return-ty.rs index ee6cde331f3..3f925e34475 100644 --- a/src/test/run-pass/unify-return-ty.rs +++ b/src/test/run-pass/unify-return-ty.rs @@ -13,6 +13,10 @@ // in that type gets resolved. extern mod std; -fn null<T>() -> *T unsafe { cast::reinterpret_cast(&0) } +fn null<T>() -> *T { + unsafe { + cast::reinterpret_cast(&0) + } +} fn main() { null::<int>(); } diff --git a/src/test/run-pass/unique-copy-box.rs b/src/test/run-pass/unique-copy-box.rs index 2d3bb42ad4c..95d3703a28c 100644 --- a/src/test/run-pass/unique-copy-box.rs +++ b/src/test/run-pass/unique-copy-box.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() unsafe { - let i = ~@1; - let j = ~@2; - let rc1 = sys::refcount(*i); - let j = copy i; - let rc2 = sys::refcount(*i); - error!("rc1: %u rc2: %u", rc1, rc2); - assert rc1 + 1u == rc2; +fn main() { + unsafe { + let i = ~@1; + let j = ~@2; + let rc1 = sys::refcount(*i); + let j = copy i; + let rc2 = sys::refcount(*i); + error!("rc1: %u rc2: %u", rc1, rc2); + assert rc1 + 1u == rc2; + } } diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs index dbb73a0c0c2..5c6fb247497 100644 --- a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs @@ -20,9 +20,5 @@ fn g() { } } -fn h() unsafe { - f(); -} - fn main() { } |
