]> git.lizzy.rs Git - rust.git/commitdiff
Merge pull request #2322 from bkircher/fix-getopts-docs
authorBrian Anderson <andersrb@gmail.com>
Tue, 1 May 2012 17:30:39 +0000 (10:30 -0700)
committerBrian Anderson <andersrb@gmail.com>
Tue, 1 May 2012 17:30:39 +0000 (10:30 -0700)
Fix getopts docs

56 files changed:
configure
mk/tests.mk
src/etc/tidy.py
src/libcore/os.rs
src/libcore/priv.rs
src/libcore/vec.rs
src/librustsyntax/ast.rs
src/librustsyntax/diagnostic.rs
src/librustsyntax/parse.rs
src/librustsyntax/parse/parser.rs
src/librustsyntax/print/pprust.rs
src/libstd/time.rs
src/libstd/timer.rs
src/libstd/uv_global_loop.rs
src/libstd/uv_hl.rs
src/libstd/uv_ll.rs
src/llvm
src/rt/rust_builtin.cpp
src/rt/rust_kernel.cpp
src/rt/rust_kernel.h
src/rt/rust_uv.cpp
src/rt/rustrt.def.in
src/rustc/driver/rustc.rs
src/rustc/metadata/creader.rs
src/rustc/metadata/csearch.rs
src/rustc/middle/infer.rs
src/rustc/middle/kind.rs
src/rustc/middle/resolve.rs
src/rustc/middle/ty.rs
src/rustc/middle/typeck.rs
src/rustllvm/RustWrapper.cpp
src/test/auxiliary/issue_2316_a.rs [new file with mode: 0644]
src/test/auxiliary/issue_2316_b.rs [new file with mode: 0644]
src/test/compile-fail/issue-1763.rs [new file with mode: 0644]
src/test/compile-fail/issue-2163.rs
src/test/compile-fail/region-unused.rs [new file with mode: 0644]
src/test/compile-fail/regions-blk.rs [new file with mode: 0644]
src/test/compile-fail/regions-in-consts.rs [new file with mode: 0644]
src/test/compile-fail/regions-in-type-items.rs
src/test/compile-fail/regions-out-of-scope-slice.rs [new file with mode: 0644]
src/test/compile-fail/regions-var-type-out-of-scope.rs [new file with mode: 0644]
src/test/compile-fail/unreachable-code-1.rs [deleted file]
src/test/compile-fail/use-after-send.rs
src/test/compile-fail/vector-no-ann.rs [new file with mode: 0644]
src/test/run-fail/bug-811.rs
src/test/run-fail/issue-1763.rs [deleted file]
src/test/run-fail/result-get-fail.rs
src/test/run-pass/class-poly-methods-cross-crate.rs
src/test/run-pass/issue-2316-c.rs [new file with mode: 0644]
src/test/run-pass/issue-2316.rs [new file with mode: 0644]
src/test/run-pass/iter-to-vec.rs
src/test/run-pass/regions-mock-trans.rs
src/test/run-pass/unreachable-code-1.rs [new file with mode: 0644]
src/test/run-pass/unreachable-code.rs [deleted file]
src/test/run-pass/vector-no-ann.rs [deleted file]
src/test/run-pass/weird-exprs.rs

index 513ea2614062529f12793037501d90e85d9b5ed9..7ee140e60692219d1b48015ac2b74123b8f6e7d4 100755 (executable)
--- a/configure
+++ b/configure
@@ -259,9 +259,9 @@ esac
 
 DEFAULT_HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
 
-CFG_SELF=$(echo $0 | tr '\\' '/')
-CFG_SRC_DIR="$(dirname $CFG_SELF)/"
-CFG_BUILD_DIR="$(echo $PWD | tr '\\' '/')/"
+CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
+CFG_BUILD_DIR="$(pwd)/"
+CFG_SELF=${CFG_SRC_DIR}$(basename $0)
 CFG_CONFIGURE_ARGS="$@"
 
 OPTIONS=""
@@ -509,32 +509,25 @@ step_msg "configuring submodules"
 if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ]
 then
     cd ${CFG_SRC_DIR}
+
     msg "git: submodule sync"
-    "${CFG_GIT}" submodule sync --quiet
-    SUBMODULES=$("${CFG_GIT}" submodule status | awk '{print $2}')
-    for s in $SUBMODULES
-    do
-        msg "git: submodule status ${s}"
-        status=$("${CFG_GIT}" submodule status ${s} | awk '{print $1}')
-        case ${status} in
-            -*)
-                msg "${s} is not initialized, initializing"
-                "${CFG_GIT}" submodule init --quiet ${s}
-                need_ok "git failed"
-                msg "${s} updating"
-                "${CFG_GIT}" submodule update --quiet ${s}
-                need_ok "git failed"
-                ;;
-            +*)
-                msg "${s} is not up to date, updating"
-                "${CFG_GIT}" submodule update --quiet ${s}
-                need_ok "git failed"
-                ;;
-            *)
-                msg "${s} is clean"
-                ;;
-        esac
-    done
+    "${CFG_GIT}" submodule --quiet sync
+
+    # NB: this is just for the sake of getting the submodule SHA1 values
+    # and status written into the build log.
+    msg "git: submodule status"
+    "${CFG_GIT}" submodule status --recursive
+
+    msg "git: submodule update"
+    "${CFG_GIT}" submodule --quiet update --init --recursive
+    need_ok "git failed"
+
+    msg "git: submodule clobber"
+    "${CFG_GIT}" submodule --quiet foreach --recursive git clean -dxf
+    need_ok "git failed"
+    "${CFG_GIT}" submodule --quiet foreach --recursive git checkout .
+    need_ok "git failed"
+
     cd ${CFG_BUILD_DIR}
 fi
 
index 634837f7c4dfbccc9783ce1ee134ddbf8a1cf89d..6f1c6bacc35765f5b7211756cc9ce8ad622b1e3c 100644 (file)
@@ -120,6 +120,7 @@ ALL_HS := $(filter-out $(S)src/rt/vg/valgrind.h \
 tidy:
                @$(call E, check: formatting)
                $(Q)find $(S)src -name '*.r[sc]' \
+               | grep '^$(S)src/test' -v \
                | xargs -n 10 python $(S)src/etc/tidy.py
                $(Q)find $(S)src/etc -name '*.py' \
                | xargs -n 10 python $(S)src/etc/tidy.py
index 0948b5fb00c8d303e19d6b3ecb6ff0ddd6fe28b2..a8d87ece9894bce2baf1b8c4be2e89cde3f4fa27 100644 (file)
@@ -32,9 +32,7 @@ try:
             report_err("trailing whitespace")
         line_len = len(line)-2 if autocrlf else len(line)-1
 
-        # Along long lines if they are part of an expected error message
-        # in a test, which is denoted with "//!":
-        if line_len > cols and "//!" not in line:
+        if line_len > cols:
             report_err("line longer than %d chars" % cols)
 except UnicodeDecodeError, e:
     report_err("UTF-8 decoding error " + str(e))
index 12b51d43f98adcc4edbff545f6219a8293fd8c01..09617355e1ac5eec77a57044fa74cca2b559c8aa 100644 (file)
@@ -121,61 +121,141 @@ fn as_utf16_p<T>(s: str, f: fn(*u16) -> T) -> T {
     }
 }
 
+fn getenv(n: str) -> option<str> {
+    global_env::getenv(n)
+}
 
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-fn getenv(n: str) -> option<str> unsafe {
-    let s = as_c_charp(n, libc::getenv);
-    ret if unsafe::reinterpret_cast(s) == 0 {
-            option::none::<str>
-        } else {
-            let s = unsafe::reinterpret_cast(s);
-            option::some::<str>(str::unsafe::from_buf(s))
-        };
+fn setenv(n: str, v: str) {
+    global_env::setenv(n, v)
 }
 
-#[cfg(target_os = "win32")]
-fn getenv(n: str) -> option<str> unsafe {
-    import libc::types::os::arch::extra::*;
-    import libc::funcs::extra::kernel32::*;
-    import win32::*;
-    as_utf16_p(n) {|u|
-        fill_utf16_buf_and_decode() {|buf, sz|
-            GetEnvironmentVariableW(u, buf, sz)
-        }
+mod global_env {
+    #[doc = "Internal module for serializing access to getenv/setenv"];
+
+    export getenv;
+    export setenv;
+
+    native mod rustrt {
+        fn rust_global_env_chan_ptr() -> *libc::uintptr_t;
     }
-}
 
+    enum msg {
+        msg_getenv(str, comm::chan<option<str>>),
+        msg_setenv(str, str, comm::chan<()>)
+    }
 
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-fn setenv(n: str, v: str) {
+    fn getenv(n: str) -> option<str> {
+        let env_ch = get_global_env_chan();
+        let po = comm::port();
+        comm::send(env_ch, msg_getenv(n, comm::chan(po)));
+        comm::recv(po)
+    }
 
-    // FIXME: remove this when export globs work properly.
-    import libc::funcs::posix01::unistd::setenv;
-    as_c_charp(n) {|nbuf|
-        as_c_charp(v) {|vbuf|
-            setenv(nbuf, vbuf, 1i32);
+    fn setenv(n: str, v: str) {
+        let env_ch = get_global_env_chan();
+        let po = comm::port();
+        comm::send(env_ch, msg_setenv(n, v, comm::chan(po)));
+        comm::recv(po)
+    }
+
+    fn get_global_env_chan() -> comm::chan<msg> {
+        let global_ptr = rustrt::rust_global_env_chan_ptr();
+        let builder_fn = {||
+            let builder = task::builder();
+            task::unsupervise(builder);
+            task::set_opts(builder, {
+                sched:  some({
+                    mode: task::single_threaded,
+                    // FIXME: This would be a good place to use
+                    // a very small native stack
+                    native_stack_size: none
+                })
+                with task::get_opts(builder)
+            });
+            builder
+        };
+        unsafe {
+            priv::chan_from_global_ptr(
+                global_ptr, builder_fn, global_env_task)
         }
     }
-}
 
+    fn global_env_task(msg_po: comm::port<msg>) unsafe {
+        priv::weaken_task {|weak_po|
+            loop {
+                alt comm::select2(msg_po, weak_po) {
+                  either::left(msg_getenv(n, resp_ch)) {
+                    comm::send(resp_ch, impl::getenv(n))
+                  }
+                  either::left(msg_setenv(n, v, resp_ch)) {
+                    comm::send(resp_ch, impl::setenv(n, v))
+                  }
+                  either::right(_) {
+                    break;
+                  }
+                }
+            }
+        }
+    }
 
-#[cfg(target_os = "win32")]
-fn setenv(n: str, v: str) {
-    // FIXME: remove imports when export globs work properly.
-    import libc::funcs::extra::kernel32::*;
-    import win32::*;
-    as_utf16_p(n) {|nbuf|
-        as_utf16_p(v) {|vbuf|
-            SetEnvironmentVariableW(nbuf, vbuf);
+    mod impl {
+
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "freebsd")]
+        fn getenv(n: str) -> option<str> unsafe {
+            let s = str::as_c_str(n, libc::getenv);
+            ret if unsafe::reinterpret_cast(s) == 0 {
+                option::none::<str>
+            } else {
+                let s = unsafe::reinterpret_cast(s);
+                option::some::<str>(str::unsafe::from_buf(s))
+            };
+        }
+
+        #[cfg(target_os = "win32")]
+        fn getenv(n: str) -> option<str> unsafe {
+            import libc::types::os::arch::extra::*;
+            import libc::funcs::extra::kernel32::*;
+            import win32::*;
+            as_utf16_p(n) {|u|
+                fill_utf16_buf_and_decode() {|buf, sz|
+                    GetEnvironmentVariableW(u, buf, sz)
+                }
+            }
+        }
+
+
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "freebsd")]
+        fn setenv(n: str, v: str) {
+
+            // FIXME: remove this when export globs work properly.
+            import libc::funcs::posix01::unistd::setenv;
+            str::as_c_str(n) {|nbuf|
+                str::as_c_str(v) {|vbuf|
+                    setenv(nbuf, vbuf, 1i32);
+                }
+            }
+        }
+
+
+        #[cfg(target_os = "win32")]
+        fn setenv(n: str, v: str) {
+            // FIXME: remove imports when export globs work properly.
+            import libc::funcs::extra::kernel32::*;
+            import win32::*;
+            as_utf16_p(n) {|nbuf|
+                as_utf16_p(v) {|vbuf|
+                    SetEnvironmentVariableW(nbuf, vbuf);
+                }
+            }
         }
+
     }
 }
 
-
 fn fdopen(fd: c_int) -> *FILE {
     ret as_c_charp("r") {|modebuf|
         libc::fdopen(fd, modebuf)
@@ -726,7 +806,6 @@ fn make_rand_name() -> str {
     }
 
     #[test]
-    #[ignore(reason = "fails periodically on mac")]
     fn test_setenv() {
         let n = make_rand_name();
         setenv(n, "VALUE");
@@ -734,7 +813,6 @@ fn test_setenv() {
     }
 
     #[test]
-    #[ignore(reason = "fails periodically on mac")]
     fn test_setenv_overwrite() {
         let n = make_rand_name();
         setenv(n, "1");
@@ -747,7 +825,6 @@ fn test_setenv_overwrite() {
     // Windows GetEnvironmentVariable requires some extra work to make sure
     // the buffer the variable is copied into is the right size
     #[test]
-    #[ignore(reason = "fails periodically on mac")]
     fn test_getenv_big() {
         let mut s = "";
         let mut i = 0;
index 90fc9239e14db67722ce76241c0b8e4b54637018..4aa8b57568f9113da5a1db61f21478411bebbd0d 100644 (file)
@@ -14,7 +14,7 @@ fn rust_compare_and_swap_ptr(address: *libc::uintptr_t,
     fn rust_task_unweaken(ch: rust_port_id);
 }
 
-type global_ptr<T: send> = *libc::uintptr_t;
+type global_ptr = *libc::uintptr_t;
 
 #[doc = "
 Atomically gets a channel from a pointer to a pointer-sized memory location
@@ -22,7 +22,7 @@ fn rust_compare_and_swap_ptr(address: *libc::uintptr_t,
 task to receive from it.
 "]
 unsafe fn chan_from_global_ptr<T: send>(
-    global: global_ptr<T>,
+    global: global_ptr,
     builder: fn() -> task::builder,
     f: fn~(comm::port<T>)
 ) -> comm::chan<T> {
index ad1c3f2344ab916d57d7d96a5afe74417be4a313..3215f3b9f289cb5034f174f1976fc41c21844e33 100644 (file)
@@ -1168,7 +1168,9 @@ unsafe fn to_ptr<T>(v: [const T]) -> *T {
     #[inline(always)]
     unsafe fn form_slice<T,U>(p: *T, len: uint, f: fn([T]/&) -> U) -> U {
         let pair = (p, len * sys::size_of::<T>());
-        let v : *([T]/&) = ::unsafe::reinterpret_cast(ptr::addr_of(pair));
+        // FIXME: should use &blk not &static here, but a snapshot is req'd
+        let v : *([T]/&static) =
+            ::unsafe::reinterpret_cast(ptr::addr_of(pair));
         f(*v)
     }
 }
index 48e8866d3f56d953ba2170b31e5d53848c952673..4a4b5ea4d38f96346e9f0b2c5f3e587b43b61669 100644 (file)
@@ -452,11 +452,7 @@ enum prim_ty {
 type region = {id: node_id, node: region_};
 
 #[auto_serialize]
-enum region_ {
-    re_anon,
-    re_named(ident),
-    re_static
-}
+enum region_ { re_anon, re_named(ident) }
 
 #[auto_serialize]
 enum ty_ {
index 047c3ccf119264f5290f3e06bc93467501eae8bd..184c32f21467f78d0d0c6e21aa85a9961dd366e5 100644 (file)
@@ -105,7 +105,7 @@ fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level) {
 }
 
 fn ice_msg(msg: str) -> str {
-    #fmt["internal compiler error %s", msg]
+    #fmt["internal compiler error: %s", msg]
 }
 
 fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler {
index d1a997187dafc296d013eb52fd94fa00d8edd383..96fa2dae8b5b1223f3eeb78119646285e518af8b 100644 (file)
@@ -152,7 +152,7 @@ fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
    parser {
     let src = alt io::read_whole_file_str(path) {
       result::ok(src) {
-        // FIXME: This copy is unfortunate
+        // FIXME: This copy is unfortunate (#2319)
         @src
       }
       result::err(e) {
index 890e59cbb140bb9e0f876662e65ba9d44cedc9d3..0c681900dd560a5d069d6c1e41221ecf9210bbfa 100644 (file)
@@ -250,16 +250,7 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
 
 fn region_from_name(p: parser, s: option<str>) -> @ast::region {
     let r = alt s {
-      some (string) {
-        // FIXME: To be consistent with our type resolution, the
-        // static region should probably be resolved during type
-        // checking, not in the parser. (Issue #2256)
-        if string == "static" {
-            ast::re_static
-        } else {
-            ast::re_named(string)
-        }
-      }
+      some (string) { ast::re_named(string) }
       none { ast::re_anon }
     };
 
index 6310a8b08a38b520df43ebd12fe802a8671c0804..d67a2c822d01d9db53fac7b4d2b903dc2c88bb57 100644 (file)
@@ -329,7 +329,6 @@ fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) {
 fn print_region(s: ps, region: @ast::region) {
     alt region.node {
       ast::re_anon { word_space(s, "&"); }
-      ast::re_static { word_space(s, "&static"); }
       ast::re_named(name) {
         word(s.s, "&");
         word_space(s, name);
index da1edbdf895641e4d782f67c5efb8bcadac062b1..cbc18d32bc1d167a6fb9d888520a13aadbd783c8 100644 (file)
@@ -823,21 +823,7 @@ fn rfc3339() -> str {
 mod tests {
     import task;
 
-    // FIXME #2160: These tests are all run in the same task because
-    // getenv/setenv interacts poorly with threads on OS X
     #[test]
-    fn test_all() {
-        test_get_time();
-        test_precise_time();
-        test_at_utc();
-        test_at();
-        test_to_timespec();
-        test_conversions();
-        test_strptime();
-        test_ctime();
-        test_strftime();
-    }
-
     fn test_get_time() {
         const some_recent_date: i64 = 1325376000i64; // 2012-01-01T00:00:00Z
         const some_future_date: i64 = 1577836800i64; // 2020-01-01T00:00:00Z
@@ -861,6 +847,7 @@ fn test_get_time() {
         }
     }
 
+    #[test]
     fn test_precise_time() {
         let s0 = precise_time_s();
         let ns1 = precise_time_ns();
@@ -878,6 +865,7 @@ fn test_precise_time() {
         assert ns2 >= ns1;
     }
 
+    #[test]
     fn test_at_utc() {
         os::setenv("TZ", "America/Los_Angeles");
 
@@ -898,6 +886,7 @@ fn test_at_utc() {
         assert utc.tm_nsec == 54321_i32;
     }
 
+    #[test]
     fn test_at() {
         os::setenv("TZ", "America/Los_Angeles");
 
@@ -923,6 +912,7 @@ fn test_at() {
         assert local.tm_nsec == 54321_i32;
     }
 
+    #[test]
     fn test_to_timespec() {
         os::setenv("TZ", "America/Los_Angeles");
 
@@ -933,6 +923,7 @@ fn test_to_timespec() {
         assert utc.to_local().to_timespec() == time;
     }
 
+    #[test]
     fn test_conversions() {
         os::setenv("TZ", "America/Los_Angeles");
 
@@ -948,6 +939,7 @@ fn test_conversions() {
         assert utc.to_local().to_utc() == utc;
     }
 
+    #[test]
     fn test_strptime() {
         os::setenv("TZ", "America/Los_Angeles");
 
@@ -1092,6 +1084,7 @@ fn test(s: str, format: str) -> bool {
         assert test("%", "%%");
     }
 
+    #[test]
     fn test_ctime() {
         os::setenv("TZ", "America/Los_Angeles");
 
@@ -1103,6 +1096,7 @@ fn test_ctime() {
         assert local.ctime() == "Fri Feb 13 15:31:30 2009";
     }
 
+    #[test]
     fn test_strftime() {
         os::setenv("TZ", "America/Los_Angeles");
 
index a7cb1762c4f9e259a32764b6cf36f68de0dd7bc7..69bcbf2e4193c7fe85649a1736e9e9b74336d31c 100644 (file)
@@ -30,7 +30,6 @@ fn delayed_send<T: send>(msecs: uint, ch: comm::chan<T>, val: T) {
             let timer_ptr = ptr::addr_of(timer);
             let hl_loop = uv::global_loop::get();
             uv::hl::interact(hl_loop) {|loop_ptr|
-                uv::hl::ref(hl_loop, timer_ptr);
                 let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
                 if (init_result == 0i32) {
                     let start_result = uv::ll::timer_start(
@@ -54,9 +53,6 @@ fn delayed_send<T: send>(msecs: uint, ch: comm::chan<T>, val: T) {
             comm::recv(timer_done_po);
             // notify the caller immediately
             comm::send(ch, copy(val));
-            // then clean up our handle
-            uv::hl::unref_and_close(hl_loop, timer_ptr,
-                                    delayed_send_close_cb);
             // uv_close for this timer has been processed
             comm::recv(timer_done_po);
         }
@@ -122,6 +118,7 @@ fn recv_timeout<T: send>(msecs: uint, wait_po: comm::port<T>) -> option<T> {
     let stop_result = uv::ll::timer_stop(handle);
     if (stop_result == 0i32) {
         comm::send(timer_done_ch, ());
+        uv::ll::close(handle, delayed_send_close_cb);
     }
     else {
         let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
@@ -140,14 +137,53 @@ fn recv_timeout<T: send>(msecs: uint, wait_po: comm::port<T>) -> option<T> {
 #[cfg(test)]
 mod test {
     #[test]
-    #[ignore]
-    fn test_timer_simple_sleep_test() {
+    fn test_gl_timer_simple_sleep_test() {
         sleep(1u);
     }
 
     #[test]
-    #[ignore]
-    fn test_timer_recv_timeout_before_time_passes() {
+    fn test_gl_timer_sleep_stress1() {
+        iter::repeat(500u) {||
+            sleep(1u);
+        }
+    }
+
+    #[test]
+    fn test_gl_timer_sleep_stress2() {
+        let po = comm::port();
+        let ch = comm::chan(po);
+
+        let repeat = 100u;
+        let spec = {
+
+            [(1u, 100u),
+             (10u, 10u),
+             (100u, 2u)]
+
+        };
+
+        iter::repeat(repeat) {||
+
+            for spec.each {|spec|
+                let (times, maxms) = spec;
+                task::spawn {||
+                    import rand::*;
+                    let rng = rng();
+                    iter::repeat(times) {||
+                        sleep(rng.next() as uint % maxms);
+                    }
+                    comm::send(ch, ());
+                }
+            }
+        }
+
+        iter::repeat(repeat * spec.len()) {||
+            comm::recv(po)
+        }
+    }
+
+    #[test]
+    fn test_gl_timer_recv_timeout_before_time_passes() {
         let expected = rand::rng().gen_str(16u);
         let test_po = comm::port::<str>();
         let test_ch = comm::chan(test_po);
@@ -165,8 +201,7 @@ fn test_timer_recv_timeout_before_time_passes() {
     }
 
     #[test]
-    #[ignore]
-    fn test_timer_recv_timeout_after_time_passes() {
+    fn test_gl_timer_recv_timeout_after_time_passes() {
         let expected = rand::rng().gen_str(16u);
         let fail_msg = rand::rng().gen_str(16u);
         let test_po = comm::port::<str>();
index 0434bba9bfb7c88f5fa110541711e972ca0dc073..c280a184cef860505a6f4d73d353a5b17a4c25b3 100644 (file)
@@ -6,23 +6,17 @@
 import hl = uv_hl;
 import get_gl = get;
 
-export get, get_single_task_gl, get_monitor_task_gl;
+export get, get_monitor_task_gl;
 
 native mod rustrt {
     fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
-    fn rust_uv_get_kernel_monitor_global_chan_ptr() -> *libc::uintptr_t;
-    fn rust_uv_get_kernel_global_async_handle() -> *libc::uintptr_t;
-    fn rust_compare_and_swap_ptr(address: *libc::uintptr_t,
-                                 oldval: libc::uintptr_t,
-                                 newval: libc::uintptr_t) -> bool;
 }
 
 #[doc ="
 Race-free helper to get access to a global task where a libuv
 loop is running.
 
-Use `uv::hl::interact`, `uv::hl::ref`, `uv::hl::unref` and
-uv `uv::hl::unref_and_close` to do operations against the global
+Use `uv::hl::interact` to do operations against the global
 loop that this function returns.
 
 # Return
@@ -34,64 +28,12 @@ fn get() -> hl::high_level_loop {
     ret get_monitor_task_gl();
 }
 
-// WARNING: USE ONLY ONE get_*_task_gl fn in the scope of a process lifetime.
 #[doc(hidden)]
 fn get_monitor_task_gl() -> hl::high_level_loop {
-    let monitor_loop_chan =
-        rustrt::rust_uv_get_kernel_monitor_global_chan_ptr();
-    ret spawn_global_weak_task(
-        monitor_loop_chan,
-        {|weak_exit_po, msg_po, loop_ptr, first_msg|
-            log(debug, "monitor gl: entering inner loop");
-            unsafe {
-                monitor_task_loop_body(weak_exit_po, msg_po, loop_ptr,
-                                       copy(first_msg))
-            }
-        },
-        {|msg_ch|
-            hl::monitor_task_loop({op_chan: msg_ch})
-        });
-}
-
-// WARNING: USE ONLY ONE get_*_task_gl fn in the scope of a process lifetime.
-#[doc(hidden)]
-fn get_single_task_gl() -> hl::high_level_loop {
-    let global_loop_chan_ptr = rustrt::rust_uv_get_kernel_global_chan_ptr();
-    ret spawn_global_weak_task(
-        global_loop_chan_ptr,
-        {|weak_exit_po, msg_po, loop_ptr, first_msg|
-            log(debug, "single-task gl: about to enter inner loop");
-            unsafe {
-                single_task_loop_body(weak_exit_po, msg_po, loop_ptr,
-                                      copy(first_msg))
-            }
-        },
-        {|msg_ch|
-            log(debug, "after priv::chan_from_global_ptr");
-            unsafe {
-                let handle = get_global_async_handle_native_representation()
-                    as **ll::uv_async_t;
-                hl::single_task_loop(
-                    { async_handle: handle, op_chan: msg_ch })
-            }
-        }
-    );
-}
-
-// INTERNAL API
-
-fn spawn_global_weak_task(
-        global_loop_chan_ptr: *libc::uintptr_t,
-        weak_task_body_cb: fn~(
-            comm::port<()>,
-            comm::port<hl::high_level_msg>,
-            *libc::c_void,
-            hl::high_level_msg) -> bool,
-        after_task_spawn_cb: fn~(comm::chan<hl::high_level_msg>)
-          -> hl::high_level_loop) -> hl::high_level_loop {
+    let monitor_loop_chan_ptr =
+        rustrt::rust_uv_get_kernel_global_chan_ptr();
     log(debug, #fmt("ENTERING global_loop::get() loop chan: %?",
-       global_loop_chan_ptr));
-
+       monitor_loop_chan_ptr));
     let builder_fn = {||
         let builder = task::builder();
         let opts = {
@@ -106,206 +48,95 @@ fn spawn_global_weak_task(
     };
     unsafe {
         log(debug, "before priv::chan_from_global_ptr");
-        let msg_ch = priv::chan_from_global_ptr::<hl::high_level_msg>(
-            global_loop_chan_ptr,
-            builder_fn) {|port|
-
-            // the actual body of our global loop lives here
-            log(debug, "initialized global port task!");
-            log(debug, "GLOBAL initialized global port task!");
-            outer_global_loop_body(port, weak_task_body_cb);
+        type hl_loop_req_ch = comm::chan<hl::high_level_loop>;
+        let msg_ch = priv::chan_from_global_ptr::<hl_loop_req_ch>(
+            monitor_loop_chan_ptr,
+            builder_fn) {|msg_po|
+            log(debug, "global monitor task starting");
+            priv::weaken_task() {|weak_exit_po|
+                log(debug, "global monitor task is now weak");
+                let hl_loop_data = spawn_libuv_weak_task();
+                let hl_loop = alt hl_loop_data {
+                  (async, msg_ch) {
+                    hl::simple_task_loop({async_handle:async, op_chan:msg_ch})
+                  }
+                };
+                loop {
+                    log(debug, "in outer_loop...");
+                    let continue = either::either(
+                        {|weak_exit|
+                            // all normal tasks have ended, tell the
+                            // libuv loop to tear_down, then exit
+                            log(debug, #fmt("weak_exit_po recv'd msg: %?",
+                                           weak_exit));
+                            let ( a, loop_msg_ch )= hl_loop_data;
+                            comm::send(loop_msg_ch, hl::teardown_loop);
+                            ll::async_send(a);
+                            false
+                        }, {|fetch_ch|
+                            log(debug, #fmt("hl_loop req recv'd: %?",
+                                           fetch_ch));
+                            comm::send(fetch_ch, copy(hl_loop));
+                            true
+                        }, comm::select2(weak_exit_po, msg_po));
+                    if !continue { break; }
+                }
+                log(debug, "global monitor task is leaving weakend state");
+            };
+            log(debug, "global monitor task exiting");
         };
-        ret after_task_spawn_cb(msg_ch);
+        // once we have a chan to the monitor loop, we ask it for
+        // the libuv loop's async handle
+        let fetch_po = comm::port::<hl::high_level_loop>();
+        let fetch_ch = comm::chan(fetch_po);
+        comm::send(msg_ch, fetch_ch);
+        comm::recv(fetch_po)
     }
 }
 
-unsafe fn outer_global_loop_body(
-    msg_po: comm::port<hl::high_level_msg>,
-    weak_task_body_cb: fn~(
-        comm::port<()>,
-        comm::port<hl::high_level_msg>,
-        *libc::c_void,
-        hl::high_level_msg) -> bool) {
-    // we're going to use a single libuv-generated loop ptr
-    // for the duration of the process
-    let loop_ptr = ll::loop_new();
+unsafe fn spawn_libuv_weak_task() -> (*ll::uv_async_t,
+                                      comm::chan<hl::high_level_msg>){
+    let exit_po = comm::port::<(*ll::uv_async_t,
+                              comm::chan<hl::high_level_msg>)>();
+    let exit_ch = comm::chan(exit_po);
 
-    // data structure for loop goes here..
-
-    // immediately weaken the task this is running in.
-    priv::weaken_task() {|weak_exit_po|
-        // when we first enter this loop, we're going
-        // to wait on stand-by to receive a request to
-        // fire-up the libuv loop
-        let mut continue = true;
-        while continue {
-            log(debug, "in outer_loop...");
-            continue = either::either(
-                {|left_val|
-                    // bail out..
-                    // if we catch this msg at this point,
-                    // we should just be able to exit because
-                    // the loop isn't active
-                    log(debug, #fmt("weak_exit_po recv'd msg: %?",
-                                   left_val));
-                    false
-                }, {|right_val|
-                    weak_task_body_cb(weak_exit_po, msg_po, loop_ptr,
-                                      right_val)
-                }, comm::select2(weak_exit_po, msg_po));
-            log(debug,#fmt("GLOBAL LOOP EXITED, WAITING TO RESTART? %?",
-                       continue));
-        }
-    };
-
-    ll::loop_delete(loop_ptr);
-}
-
-unsafe fn monitor_task_loop_body(weak_exit_po_in: comm::port<()>,
-                          msg_po_in: comm::port<hl::high_level_msg>,
-                          loop_ptr: *libc::c_void,
-                          -first_interaction: hl::high_level_msg) -> bool {
-    // resend the msg to be handled in the select2 loop below..
-    comm::send(comm::chan(msg_po_in), first_interaction);
-
-    // our async_handle
-    let async_handle_po = comm::port::<*ll::uv_async_t>();
-    let async_handle_ch = comm::chan(async_handle_po);
-
-    // the msg_po that libuv will be receiving on..
-    let loop_msg_po = comm::port::<hl::high_level_msg>();
-    let loop_msg_po_ptr = ptr::addr_of(loop_msg_po);
-    let loop_msg_ch = comm::chan(loop_msg_po);
-
-    // the question of whether unsupervising this will even do any
-    // good is there.. but since this'll go into blocking in libuv with
-    // a quickness.. any errors that occur (including inside crust) will
-    // be segfaults.. so yeah.
     task::spawn_sched(task::manual_threads(1u)) {||
-        let loop_msg_po_in = *loop_msg_po_ptr;
-        hl::run_high_level_loop(
-            loop_ptr,
-            loop_msg_po_in, // here the loop gets handed a different message
-                            // port, as we'll be receiving all of the messages
-                            // initially and then passing them on..
-            // before_run
-            {|async_handle|
-                log(debug,#fmt("monitor gl: before_run: async_handle %?",
-                              async_handle));
-                // when this is ran, our async_handle is set up, so let's
-                // do an async_send with it.. letting the loop know, once it
-                // starts, that is has work
-                ll::async_send(async_handle);
-                comm::send(async_handle_ch, copy(async_handle));
-            },
-            // before_msg_drain
-            {|async_handle|
-                log(debug,#fmt("monitor gl: b4_msg_drain: async_handle %?",
-                              async_handle));
-                true
-            },
-            // before_tear_down
-            {|async_handle|
-                log(debug,#fmt("monitor gl: b4_tear_down: async_handle %?",
-                              async_handle));
-            });
+        log(debug, "entering global libuv task");
+        let loop_ptr = ll::loop_new();
+        priv::weaken_task() {|weak_exit_po|
+            log(debug, #fmt("global libuv task is now weak %?",
+                            weak_exit_po));
+            let loop_msg_po = comm::port::<hl::high_level_msg>();
+            let loop_msg_ch = comm::chan(loop_msg_po);
+            hl::run_high_level_loop(
+                loop_ptr,
+                loop_msg_po,
+                // before_run
+                {|async_handle|
+                    log(debug,#fmt("global libuv: before_run %?",
+                                  async_handle));
+                    let out_data = (async_handle, loop_msg_ch);
+                    comm::send(exit_ch, out_data);
+                },
+                // before_msg_process
+                {|async_handle, loop_active|
+                    log(debug,#fmt("global libuv: before_msg_drain %? %?",
+                                  async_handle, loop_active));
+                    true
+                },
+                // before_tear_down
+                {|async_handle|
+                    log(debug,#fmt("libuv task: before_tear_down %?",
+                                  async_handle));
+                }
+            );
+            log(debug, "global libuv task is leaving weakened state");
+        };
+        ll::loop_delete(loop_ptr);
+        log(debug, "global libuv task exiting");
     };
 
-    // our loop is set up, so let's emit the handle back out to our users..
-    let async_handle = comm::recv(async_handle_po);
-    // supposed to return a bool to indicate to the enclosing loop whether
-    // it should continue or not..
-    let mut continue_inner_loop = true;
-    let mut didnt_get_hl_bailout = true;
-    while continue_inner_loop {
-        log(debug, "monitor task inner loop.. about to block on select2");
-        continue_inner_loop = either::either(
-            {|left_val|
-                // bail out..
-                log(debug, #fmt("monitor inner weak_exit_po recv'd msg: %?",
-                               left_val));
-                // TODO: make loop bail out
-                didnt_get_hl_bailout = false;
-                false
-            }, {|right_val|
-                // wake up our inner loop and pass it a msg..
-                comm::send(loop_msg_ch, copy(right_val));
-                ll::async_send(async_handle);
-                true
-            }, comm::select2(weak_exit_po_in, msg_po_in)
-        )
-    }
-    didnt_get_hl_bailout
-}
-
-unsafe fn single_task_loop_body(weak_exit_po_in: comm::port<()>,
-                          msg_po_in: comm::port<hl::high_level_msg>,
-                          loop_ptr: *libc::c_void,
-                          -first_interaction: hl::high_level_msg) -> bool {
-    // resend the msg
-    comm::send(comm::chan(msg_po_in), first_interaction);
-
-    // black magic
-    let weak_exit_po_ptr = ptr::addr_of(weak_exit_po_in);
-    hl::run_high_level_loop(
-        loop_ptr,
-        msg_po_in,
-        // before_run
-        {|async_handle|
-            log(debug,#fmt("global_loop before_run: async_handle %?",
-                          async_handle));
-            // set the handle as the global
-            set_global_async_handle(0u as *ll::uv_async_t,
-                                    async_handle);
-            // when this is ran, our async_handle is set up, so let's
-            // do an async_send with it
-            ll::async_send(async_handle);
-        },
-        // before_msg_drain
-        {|async_handle|
-            log(debug,#fmt("global_loop before_msg_drain: async_handle %?",
-                          async_handle));
-            let weak_exit_po = *weak_exit_po_ptr;
-            if(comm::peek(weak_exit_po)) {
-                // if this is true, immediately bail and return false, causing
-                // the libuv loop to start tearing down
-                log(debug,"got weak_exit meg inside libuv loop");
-                comm::recv(weak_exit_po);
-                false
-            }
-            // if no weak_exit_po msg is received, then we'll let the
-            // loop continue
-            else {
-                true
-            }
-        },
-        // before_tear_down
-        {|async_handle|
-            log(debug,#fmt("global_loop before_tear_down: async_handle %?",
-                          async_handle));
-            set_global_async_handle(async_handle,
-                                    0 as *ll::uv_async_t);
-        });
-    // supposed to return a bool to indicate to the enclosing loop whether
-    // it should continue or not..
-    ret true;
-}
-
-unsafe fn get_global_async_handle_native_representation()
-    -> *libc::uintptr_t {
-    ret rustrt::rust_uv_get_kernel_global_async_handle();
-}
-
-unsafe fn get_global_async_handle() -> *ll::uv_async_t {
-    ret (*get_global_async_handle_native_representation()) as *ll::uv_async_t;
-}
-
-unsafe fn set_global_async_handle(old: *ll::uv_async_t,
-                           new_ptr: *ll::uv_async_t) {
-    rustrt::rust_compare_and_swap_ptr(
-        get_global_async_handle_native_representation(),
-        old as libc::uintptr_t,
-        new_ptr as libc::uintptr_t);
+    comm::recv(exit_po)
 }
 
 #[cfg(test)]
@@ -325,8 +156,7 @@ mod test {
         let hl_loop = get_gl();
         hl::interact(hl_loop) {|loop_ptr|
             log(debug, "closing timer");
-            //ll::close(timer_ptr as *libc::c_void, simple_timer_close_cb);
-            hl::unref_and_close(hl_loop, timer_ptr, simple_timer_close_cb);
+            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");
         };
@@ -345,7 +175,6 @@ fn impl_uv_hl_simple_timer(hl_loop: hl::high_level_loop) unsafe {
             log(debug, "user code inside interact loop!!!");
             let init_status = ll::timer_init(loop_ptr, timer_ptr);
             if(init_status == 0i32) {
-                hl::ref(hl_loop, timer_ptr);
                 ll::set_data_for_uv_handle(
                     timer_ptr as *libc::c_void,
                     exit_ch_ptr as *libc::c_void);
@@ -364,13 +193,39 @@ fn impl_uv_hl_simple_timer(hl_loop: hl::high_level_loop) unsafe {
         comm::recv(exit_po);
         log(debug, "global_loop timer test: msg recv on exit_po, done..");
     }
+
     #[test]
-    #[ignore]
-    fn test_uv_global_loop_high_level_global_timer() unsafe {
+    fn test_gl_uv_global_loop_high_level_global_timer() unsafe {
         let hl_loop = get_gl();
+        let exit_po = comm::port::<()>();
+        let exit_ch = comm::chan(exit_po);
         task::spawn_sched(task::manual_threads(1u), {||
             impl_uv_hl_simple_timer(hl_loop);
+            comm::send(exit_ch, ());
         });
         impl_uv_hl_simple_timer(hl_loop);
+        comm::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 = comm::port::<()>();
+        let exit_ch = comm::chan(exit_po);
+        let cycles = 5000u;
+        iter::repeat(cycles) {||
+            task::spawn_sched(task::manual_threads(1u), {||
+                impl_uv_hl_simple_timer(hl_loop);
+                comm::send(exit_ch, ());
+            });
+        };
+        iter::repeat(cycles) {||
+            comm::recv(exit_po);
+        };
+        log(debug, "test_stress_gl_uv_global_loop_high_level_global_timer"+
+            " exiting sucessfully!");
     }
 }
\ No newline at end of file
index 8ce0fb8e5c74770bb04f08fcd74813eac41b76ff..83080348d0b91465b1655c1209a8cefefdf6448d 100644 (file)
@@ -6,94 +6,68 @@
 libuv functionality.
 "];
 
-export high_level_loop, hl_loop_ext, high_level_msg;
-export run_high_level_loop, interact, ref, unref, unref_and_close;
+export high_level_loop, high_level_msg;
+export run_high_level_loop, interact;
 
 import ll = uv_ll;
 
 #[doc = "
 Used to abstract-away direct interaction with a libuv loop.
-
-# Arguments
-
-* async_handle - a pointer to a pointer to a uv_async_t struct used to 'poke'
-the C uv loop to process any pending callbacks
-
-* op_chan - a channel used to send function callbacks to be processed
-by the C uv loop
 "]
 enum high_level_loop {
+    #[doc="
+    `high_level_loop` variant that carries a `comm::chan` and
+    a `*ll::uv_async_t`.
+    "]
     simple_task_loop({
         async_handle: *ll::uv_async_t,
         op_chan: comm::chan<high_level_msg>
-    }),
-    single_task_loop({
-        async_handle: **ll::uv_async_t,
-        op_chan: comm::chan<high_level_msg>
-    }),
-    monitor_task_loop({
-        op_chan: comm::chan<high_level_msg>
     })
 }
 
-impl hl_loop_ext for high_level_loop {
-    fn async_handle() -> **ll::uv_async_t {
-        alt self {
-          single_task_loop({async_handle, op_chan}) {
-            ret async_handle;
-          }
-          _ {
-            fail "variant of hl::high_level_loop that doesn't include" +
-                "an async_handle field";
-          }
-        }
-    }
-    fn op_chan() -> comm::chan<high_level_msg> {
-        alt self {
-          single_task_loop({async_handle, op_chan}) {
-            ret op_chan;
-          }
-          monitor_task_loop({op_chan}) {
-            ret op_chan;
-          }
-          simple_task_loop({async_handle, op_chan}) {
-            ret op_chan;
-          }
-        }
-    }
-}
-
 #[doc="
 Represents the range of interactions with a `high_level_loop`
 "]
 enum high_level_msg {
     interaction (fn~(*libc::c_void)),
-    ref_handle (*libc::c_void),
-    manual_unref_handle (*libc::c_void, option<*u8>),
-    tear_down
+    #[doc="
+For use in libraries that roll their own `high_level_loop` (like
+`std::uv::global_loop`)
+
+Is used to signal to the loop that it should close the internally-held
+async handle and do a sanity check to make sure that all other handles are
+closed, causing a failure otherwise. This should not be sent/used from
+'normal' user code.
+    "]
+    teardown_loop
 }
 
 #[doc = "
-Given a vanilla `uv_loop_t*`
+Useful for anyone who wants to roll their own `high_level_loop`.
 
 # Arguments
 
 * loop_ptr - a pointer to a currently unused libuv loop. Its `data` field
 will be overwritten before the loop begins
-must be a pointer to a clean rust `uv_async_t` record
-* msg_po - an active port that receives `high_level_msg`s
-* before_run - a unique closure that is invoked after `uv_async_init` is
-called on the `async_handle` passed into this callback, just before `uv_run`
-is called on the provided `loop_ptr`
-* before_msg_drain - a unique closure that is invoked every time the loop is
-awoken, but before the port pointed to in the `msg_po` argument is drained
+* msg_po - an active port that receives `high_level_msg`s. You can distribute
+a paired channel to users, along with the `async_handle` returned in the
+following callback (combine them to make a `hl::simpler_task_loop` varient
+of `hl::high_level_loop`)
+* before_run - a unique closure that is invoked before `uv_run()` is called
+on the provided `loop_ptr`. An `async_handle` is passed in which will be
+live for the duration of the loop. You can distribute this to users so that
+they can interact with the loop safely.
+* before_msg_process - a unique closure that is invoked at least once when
+the loop is woken up, and once more for every message that is drained from
+the loop's msg port
 * before_tear_down - called just before the loop invokes `uv_close()` on the
 provided `async_handle`. `uv_run` should return shortly after
 "]
 unsafe fn run_high_level_loop(loop_ptr: *libc::c_void,
                               msg_po: comm::port<high_level_msg>,
                               before_run: fn~(*ll::uv_async_t),
-                              before_msg_drain: fn~(*ll::uv_async_t) -> bool,
+                              before_msg_process:
+                                fn~(*ll::uv_async_t, bool) -> bool,
                               before_tear_down: fn~(*ll::uv_async_t)) {
     // set up the special async handle we'll use to allow multi-task
     // communication with this loop
@@ -106,11 +80,9 @@ unsafe fn run_high_level_loop(loop_ptr: *libc::c_void,
     let data: hl_loop_data = default_gl_data({
         async_handle: async_handle,
         mut active: true,
-        before_msg_drain: before_msg_drain,
+        before_msg_process: before_msg_process,
         before_tear_down: before_tear_down,
-        msg_po_ptr: ptr::addr_of(msg_po),
-        mut refd_handles: [mut],
-        mut unrefd_handles: [mut]
+        msg_po_ptr: ptr::addr_of(msg_po)
     });
     let data_ptr = ptr::addr_of(data);
     ll::set_data_for_uv_handle(async_handle, data_ptr);
@@ -130,55 +102,25 @@ unsafe fn run_high_level_loop(loop_ptr: *libc::c_void,
 The primary way to do operations again a running `high_level_loop` that
 doesn't involve creating a uv handle via `safe_handle`
 
+# Warning
+
+This function is the only safe way to interact with _any_ `high_level_loop`.
+Using functions in the `uv::ll` module outside of the `cb` passed into
+this function is _very dangerous_.
+
 # Arguments
 
-* a_loop - a `high_level_loop` that you want to do operations against
+* hl_loop - a `uv::hl::high_level_loop` that you want to do operations against
 * cb - a function callback to be processed on the running loop's
-thread. The only parameter is an opaque pointer to the running
-uv_loop_t. In the context of this callback, it is safe to use this pointer
-to do various uv_* API calls. _DO NOT_ send this pointer out via ports/chans
+thread. The only parameter passed in is an opaque pointer representing the
+running `uv_loop_t*`. In the context of this callback, it is safe to use
+this pointer to do various uv_* API calls contained within the `uv::ll`
+module. It is not safe to send the `loop_ptr` param to this callback out
+via ports/chans.
 "]
-unsafe fn interact(a_loop: high_level_loop,
+unsafe fn interact(hl_loop: high_level_loop,
                       -cb: fn~(*libc::c_void)) {
-    send_high_level_msg(a_loop, interaction(cb));
-}
-
-iface uv_handle_manager<T> {
-    fn init() -> T;
-}
-
-type safe_handle_fields<T> = {
-    hl_loop: high_level_loop,
-    handle: T,
-    close_cb: *u8
-};
-
-/*fn safe_handle<T>(a_loop: high_level_loop,
-                  handle_val: T,
-                  handle_init_cb: fn~(*libc::c_void, *T),
-                  close_cb: *u8) {
-
-resource safe_handle_container<T>(handle_fields: safe_handle_fields<T>) {
-}
-}*/
-
-
-#[doc="
-Needs to be encapsulated within `safe_handle`
-"]
-fn ref<T>(hl_loop: high_level_loop, handle: *T) unsafe {
-    send_high_level_msg(hl_loop, ref_handle(handle as *libc::c_void));
-}
-#[doc="
-Needs to be encapsulated within `safe_handle`
-"]
-fn unref<T>(hl_loop: high_level_loop, handle: *T) unsafe {
-    send_high_level_msg(hl_loop, manual_unref_handle(handle as *libc::c_void,
-                                                   none));
-}
-fn unref_and_close<T>(hl_loop: high_level_loop, handle: *T, cb: *u8) unsafe {
-    send_high_level_msg(hl_loop, manual_unref_handle(handle as *libc::c_void,
-                                                   some(cb)));
+    send_high_level_msg(hl_loop, interaction(cb));
 }
 
 // INTERNAL API
@@ -188,36 +130,26 @@ enum hl_loop_data {
     default_gl_data({
         async_handle: *ll::uv_async_t,
         mut active: bool,
-        before_msg_drain: fn~(*ll::uv_async_t) -> bool,
+        before_msg_process: fn~(*ll::uv_async_t, bool) -> bool,
         before_tear_down: fn~(*ll::uv_async_t),
-        msg_po_ptr: *comm::port<high_level_msg>,
-        mut refd_handles: [mut *libc::c_void],
-        mut unrefd_handles: [mut *libc::c_void]})
+        msg_po_ptr: *comm::port<high_level_msg>})
 }
 
 unsafe fn send_high_level_msg(hl_loop: high_level_loop,
-                              -msg: high_level_msg) unsafe {
-    comm::send(hl_loop.op_chan(), msg);
+                              -msg: high_level_msg) {
+    let op_chan = alt hl_loop{simple_task_loop({async_handle, op_chan}){
+      op_chan}};
+    comm::send(op_chan, msg);
 
     // if the global async handle == 0, then that means
     // the loop isn't active, so we don't need to wake it up,
     // (the loop's enclosing task should be blocking on a message
     // receive on this port)
     alt hl_loop {
-      single_task_loop({async_handle, op_chan}) {
-        if ((*async_handle) != 0 as *ll::uv_async_t) {
-            log(debug,"global async handle != 0, waking up loop..");
-            ll::async_send((*async_handle));
-        }
-        else {
-            log(debug,"GLOBAL ASYNC handle == 0");
-        }
-      }
       simple_task_loop({async_handle, op_chan}) {
         log(debug,"simple async handle != 0, waking up loop..");
         ll::async_send((async_handle));
       }
-      _ {}
     }
 }
 
@@ -228,71 +160,57 @@ unsafe fn send_high_level_msg(hl_loop: high_level_loop,
 // data member
 crust fn high_level_wake_up_cb(async_handle: *ll::uv_async_t,
                                status: int) unsafe {
-    // nothing here, yet.
     log(debug, #fmt("high_level_wake_up_cb crust.. 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 *hl_loop_data;
-    // we check to see if the loop is "active" (the loop is set to
-    // active = false the first time we realize we need to 'tear down',
-    // set subsequent calls to the global async handle may be triggered
-    // before all of the uv_close() calls are processed and loop exits
-    // on its own. So if the loop isn't active, we won't run the user's
-    // on_wake callback (and, consequently, let messages pile up, probably
-    // in the loops msg_po)
-    if (*data).active {
-        log(debug, "before on_wake");
-        let mut do_msg_drain = (*data).before_msg_drain(async_handle);
-        let mut continue = true;
-        if do_msg_drain {
-            let msg_po = *((*data).msg_po_ptr);
-            if comm::peek(msg_po) {
-                // if this is true, we'll iterate over the
-                // msgs waiting in msg_po until there's no more
-                log(debug,"got msg_po");
-                while(continue) {
-                    log(debug,"before alt'ing on high_level_msg");
-                    alt comm::recv(msg_po) {
+    alt (*data).active {
+      true {
+        let msg_po = *((*data).msg_po_ptr);
+        alt comm::peek(msg_po) {
+          true {
+            loop {
+                let msg = comm::recv(msg_po);
+                alt (*data).active {
+                  true {
+                    alt msg {
                       interaction(cb) {
-                        log(debug,"got interaction, before cb..");
-                        // call it..
+                        (*data).before_msg_process(async_handle,
+                                                   (*data).active);
                         cb(loop_ptr);
-                        log(debug,"after calling cb");
-                      }
-                      ref_handle(handle) {
-                        high_level_ref(data, handle);
                       }
-                      manual_unref_handle(handle, user_close_cb) {
-                        high_level_unref(data, handle, true, user_close_cb);
-                      }
-                      tear_down {
-                        log(debug,"incoming hl_msg: got tear_down");
+                      teardown_loop {
+                        begin_teardown(data);
                       }
                     }
-                    continue = comm::peek(msg_po);
+                  }
+                  false {
+                    // drop msg ?
+                  }
                 }
+                if !comm::peek(msg_po) { break; }
             }
-            else {
-                log(debug, "in hl wake_cb, no pending messages");
-            }
-        }
-        log(debug, #fmt("after on_wake, continue? %?", continue));
-        if !do_msg_drain {
-            high_level_tear_down(data);
+          }
+          false {
+            // no pending msgs
+          }
         }
+      }
+      false {
+        // loop not active
+      }
     }
 }
 
 crust fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe {
-    log(debug, #fmt("tear_down_close_cb called, closing handle at %?",
-                    handle));
-    let data = ll::get_data_for_uv_handle(handle) as *hl_loop_data;
-    if vec::len((*data).refd_handles) > 0u {
-        fail "Didn't unref all high-level handles";
-    }
+    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;
 }
 
-fn high_level_tear_down(data: *hl_loop_data) unsafe {
+fn begin_teardown(data: *hl_loop_data) unsafe {
     log(debug, "high_level_tear_down() called, close async_handle");
     // call user-suppled before_tear_down cb
     let async_handle = (*data).async_handle;
@@ -300,90 +218,6 @@ fn high_level_tear_down(data: *hl_loop_data) unsafe {
     ll::close(async_handle as *libc::c_void, tear_down_close_cb);
 }
 
-unsafe fn high_level_ref(data: *hl_loop_data, handle: *libc::c_void) {
-    log(debug,"incoming hl_msg: got ..ref_handle");
-    let mut refd_handles = (*data).refd_handles;
-    let mut unrefd_handles = (*data).unrefd_handles;
-    let handle_already_refd = refd_handles.contains(handle);
-    if handle_already_refd {
-        fail "attempt to do a high-level ref an already ref'd handle";
-    }
-    let handle_already_unrefd = unrefd_handles.contains(handle);
-    // if we are ref'ing a handle (by ptr) that was already unref'd,
-    // probably
-    if handle_already_unrefd {
-        let last_idx = vec::len(unrefd_handles) - 1u;
-        let handle_idx = vec::position_elem(unrefd_handles, handle);
-        alt handle_idx {
-          none {
-            fail "trying to remove handle that isn't in unrefd_handles";
-          }
-          some(idx) {
-            unrefd_handles[idx] <-> unrefd_handles[last_idx];
-            vec::pop(unrefd_handles);
-          }
-        }
-        (*data).unrefd_handles = unrefd_handles;
-    }
-    refd_handles += [handle];
-    (*data).refd_handles = refd_handles;
-}
-
-unsafe fn high_level_unref(data: *hl_loop_data, handle: *libc::c_void,
-                   manual_unref: bool, user_close_cb: option<*u8>) {
-    log(debug,"incoming hl_msg: got auto_unref_handle");
-    let mut refd_handles = (*data).refd_handles;
-    let mut unrefd_handles = (*data).unrefd_handles;
-    log(debug, #fmt("refs: %?, unrefs %? handle %?", vec::len(refd_handles),
-                    vec::len(unrefd_handles), handle));
-    let handle_already_refd = refd_handles.contains(handle);
-    if !handle_already_refd {
-        fail "attempting to high-level unref an untracked handle";
-    }
-    let double_unref = unrefd_handles.contains(handle);
-    if double_unref {
-        log(debug, "double unref encountered");
-        if manual_unref {
-            // will allow a user to manual unref, but only signal
-            // a fail when a double-unref is caused by a user
-            fail "attempting to high-level unref an unrefd handle";
-        }
-        else {
-            log(debug, "not failing...");
-        }
-    }
-    else {
-        log(debug, "attempting to unref handle");
-        alt user_close_cb {
-          some(cb) {
-            ll::close(handle, cb);
-          }
-          none { }
-        }
-        let last_idx = vec::len(refd_handles) - 1u;
-        let handle_idx = vec::position_elem(refd_handles, handle);
-        alt handle_idx {
-          none {
-            fail "trying to remove handle that isn't in refd_handles";
-          }
-          some(idx) {
-            refd_handles[idx] <-> refd_handles[last_idx];
-            vec::pop(refd_handles);
-          }
-        }
-        (*data).refd_handles = refd_handles;
-        unrefd_handles += [handle];
-        (*data).unrefd_handles = unrefd_handles;
-        if vec::len(refd_handles) == 0u {
-            log(debug, "0 referenced handles, start loop teardown");
-            high_level_tear_down(data);
-        }
-        else {
-            log(debug, "more than 0 referenced handles");
-        }
-    }
-
-}
 #[cfg(test)]
 mod test {
     crust fn async_close_cb(handle: *ll::uv_async_t) unsafe {
@@ -397,7 +231,7 @@ mod test {
         log(debug, #fmt("async_handle_cb handle %? status %?",handle,status));
         let hl_loop = (*(ll::get_data_for_uv_handle(handle)
                         as *ah_data)).hl_loop;
-        unref_and_close(hl_loop, handle, async_close_cb);
+        ll::close(handle, async_close_cb);
     }
     type ah_data = {
         hl_loop: high_level_loop,
@@ -414,7 +248,6 @@ fn impl_uv_hl_async(hl_loop: high_level_loop) unsafe {
         };
         let ah_data_ptr = ptr::addr_of(ah_data);
         interact(hl_loop) {|loop_ptr|
-            ref(hl_loop, ah_ptr);
             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);
@@ -446,9 +279,9 @@ unsafe fn spawn_test_loop(exit_ch: comm::chan<()>) -> high_level_loop {
                     }));
                 },
                 // before_msg_drain
-                {|async_handle|
-                    log(debug,#fmt("hltest before_msg_drain: async_handle %?",
-                                  async_handle));
+                {|async_handle, status|
+                    log(debug,#fmt("hltest before_msg_drain: handle %? %?",
+                                  async_handle, status));
                     true
                 },
                 // before_tear_down
@@ -473,7 +306,6 @@ unsafe fn spawn_test_loop(exit_ch: comm::chan<()>) -> high_level_loop {
     }
 
     #[test]
-    #[ignore]
     fn test_uv_hl_async() unsafe {
         let exit_po = comm::port::<()>();
         let exit_ch = comm::chan(exit_po);
@@ -485,27 +317,30 @@ fn test_uv_hl_async() unsafe {
         // 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 lifetime_handle = ll::async_t();
-        let lifetime_handle_ptr = ptr::addr_of(lifetime_handle);
-        interact(hl_loop) {|loop_ptr|
-            ref(hl_loop, lifetime_handle_ptr);
-            ll::async_init(loop_ptr, lifetime_handle_ptr,
-                          lifetime_async_callback);
-        };
-
+        let work_exit_po = comm::port::<()>();
+        let work_exit_ch = comm::chan(work_exit_po);
         iter::repeat(7u) {||
             task::spawn_sched(task::manual_threads(1u), {||
                 impl_uv_hl_async(hl_loop);
+                comm::send(work_exit_ch, ());
             });
         };
-        impl_uv_hl_async(hl_loop);
-        impl_uv_hl_async(hl_loop);
-        impl_uv_hl_async(hl_loop);
-        interact(hl_loop) {|loop_ptr|
-            ll::close(lifetime_handle_ptr, lifetime_handle_close);
-            unref(hl_loop, lifetime_handle_ptr);
-            log(debug, "close and unref lifetime handle");
+        iter::repeat(7u) {||
+            comm::recv(work_exit_po);
         };
+        log(debug, "sending teardown_loop msg..");
+        // the teardown msg usually comes, in the case of the global loop,
+        // as a result of receiving a msg on the weaken_task port. but,
+        // anyone rolling their own high_level_loop can decide when to
+        // send the msg. it's assert and barf, though, if all of your
+        // handles aren't uv_close'd first
+        alt hl_loop {
+          simple_task_loop({async_handle, op_chan}) {
+            comm::send(op_chan, teardown_loop);
+            ll::async_send(async_handle);
+          }
+        }
         comm::recv(exit_po);
+        log(debug, "after recv on exit_po.. exiting..");
     }
 }
index ff5c618cdffc717b0d785d039c7c1a24d19b1a6a..31d36430aec43f608b0cf94a92c26d16f7480ae5 100644 (file)
@@ -512,6 +512,7 @@ fn gen_stub_uv_write_t() -> uv_write_t {
 native mod rustrt {
     fn rust_uv_loop_new() -> *libc::c_void;
     fn rust_uv_loop_delete(lp: *libc::c_void);
+    fn rust_uv_loop_refcount(loop_ptr: *libc::c_void) -> libc::c_int;
     fn rust_uv_run(loop_handle: *libc::c_void);
     fn rust_uv_close(handle: *libc::c_void, cb: *u8);
     fn rust_uv_async_send(handle: *uv_async_t);
@@ -601,6 +602,10 @@ unsafe fn loop_delete(loop_handle: *libc::c_void) {
     rustrt::rust_uv_loop_delete(loop_handle);
 }
 
+unsafe fn loop_refcount(loop_ptr: *libc::c_void) -> libc::c_int {
+    ret rustrt::rust_uv_loop_refcount(loop_ptr);
+}
+
 unsafe fn run(loop_handle: *libc::c_void) {
     rustrt::rust_uv_run(loop_handle);
 }
index 8b035b5fe83ca15df171e581681bbc9cbd7e2ae0..3a57b672f89adcb2d2d06adc564dc15ca4e276d6 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 8b035b5fe83ca15df171e581681bbc9cbd7e2ae0
+Subproject commit 3a57b672f89adcb2d2d06adc564dc15ca4e276d6
index f2714c4d7c332acc9db0ba6becf34bc1d623ec74..5866c1a8dc029e9ef5e6822b88c85cfe28855635 100644 (file)
@@ -781,6 +781,12 @@ rust_task_unweaken(rust_port_id chan) {
     task->kernel->unweaken_task(chan);
 }
 
+extern "C" CDECL uintptr_t*
+rust_global_env_chan_ptr() {
+    rust_task *task = rust_get_current_task();
+    return task->kernel->get_global_env_chan();
+}
+
 //
 // Local Variables:
 // mode: C++
index 9afb010a3db8c3521f77ba4c6568c48a0586d1dc..44c6be2421ddda278e95378361483ca89c1c5eeb 100644 (file)
@@ -22,14 +22,11 @@ rust_kernel::rust_kernel(rust_env *env) :
     sched_reaper(this),
     osmain_driver(NULL),
     non_weak_tasks(0),
+    global_loop_chan(0),
+    global_env_chan(0),
     env(env)
+
 {
-    // set up storage of pointers needed to
-    // access the global loop.
-    global_loop_chan = 0;
-    async_handle_inner = (uintptr_t)0;
-    global_async_handle = &async_handle_inner;
-    *global_async_handle = (uintptr_t)0;
 
     // Create the single threaded scheduler that will run on the platform's
     // main thread
index 58739b2ada0d5371e0222840aee3b8637c467ff9..97db7cb37780c59345218c9c875d59d57b9648c4 100644 (file)
@@ -75,8 +75,8 @@ class rust_kernel {
 
     // Used to communicate with the process-side, global libuv loop
     uintptr_t global_loop_chan;
-    uintptr_t async_handle_inner;
-    uintptr_t* global_async_handle;
+    // Used to serialize access to getenv/setenv
+    uintptr_t global_env_chan;
 
 public:
     struct rust_env *env;
@@ -124,7 +124,7 @@ public:
     bool send_to_port(rust_port_id chan, void *sptr);
 
     uintptr_t* get_global_loop() { return &global_loop_chan; }
-    uintptr_t* get_global_async_handle() { return global_async_handle; }
+    uintptr_t* get_global_env_chan() { return &global_env_chan; }
 };
 
 template <typename T> struct kernel_owned {
index 7c0602f0a025b3844821d3e4890abccd33f25d46..f3806aac6eb38a8f1efda078d0ee7e44b43359ac 100644 (file)
@@ -111,6 +111,11 @@ rust_uv_loop_delete(uv_loop_t* loop) {
     uv_loop_delete(loop);
 }
 
+extern "C" int
+rust_uv_loop_refcount(uv_loop_t* loop) {
+    return uv_loop_refcount(loop);
+}
+
 extern "C" void
 rust_uv_loop_set_data(uv_loop_t* loop, void* data) {
     loop->data = data;
@@ -445,13 +450,3 @@ rust_uv_get_kernel_global_chan_ptr() {
     LOG(task, stdlib,"global loop val: %lu", (unsigned long int)*result);
     return result;
 }
-
-extern "C" uintptr_t*
-rust_uv_get_kernel_monitor_global_chan_ptr() {
-    return rust_uv_get_kernel_global_chan_ptr();
-}
-
-extern "C" uintptr_t*
-rust_uv_get_kernel_global_async_handle() {
-    return rust_get_current_task()->kernel->get_global_async_handle();
-}
index 545c3581425e71227a598c85fc29b1cdb5298a6a..2289f38e724b064bd769d22f8d7361ea19a31c31 100644 (file)
@@ -86,6 +86,7 @@ upcall_del_stack
 upcall_reset_stack_limit
 rust_uv_loop_new
 rust_uv_loop_delete
+rust_uv_loop_refcount
 rust_uv_loop_set_data
 rust_uv_bind_op_cb
 rust_uv_stop_op_cb
@@ -138,8 +139,6 @@ rust_uv_set_data_for_req
 rust_uv_get_base_from_buf
 rust_uv_get_len_from_buf
 rust_uv_get_kernel_global_chan_ptr
-rust_uv_get_kernel_monitor_global_chan_ptr
-rust_uv_get_kernel_global_async_handle
 rust_dbg_lock_create
 rust_dbg_lock_destroy
 rust_dbg_lock_lock
@@ -148,4 +147,5 @@ rust_dbg_lock_wait
 rust_dbg_lock_signal
 rust_dbg_call
 rust_osmain_sched_id
-rust_compare_and_swap_ptr
\ No newline at end of file
+rust_compare_and_swap_ptr
+rust_global_env_chan_ptr
index efd54826590614083f2ea85bf80223d947e06ac7..de194211277eae9e90dce2f1a14545e7f5719555 100644 (file)
@@ -215,12 +215,18 @@ enum monitor_msg {
                     none,
                     diagnostic::ice_msg("unexpected failure"),
                     diagnostic::error);
-                let note = "The compiler hit an unexpected failure path. \
-                            This is a bug. Try running with \
-                            RUST_LOG=rustc=0,::rt::backtrace \
-                            to get further details and report the results \
-                            to github.com/mozilla/rust/issues";
-                diagnostic::emit(none, note, diagnostic::note);
+
+                for [
+
+                    "the compiler hit an unexpected failure path. \
+                     this is a bug",
+                    "try running with RUST_LOG=rustc=0,::rt::backtrace \
+                     to get further details and report the results \
+                     to github.com/mozilla/rust/issues"
+
+                ].each {|note|
+                    diagnostic::emit(none, note, diagnostic::note)
+                }
             }
             // Fail so the process returns a failure code
             fail;
index 1f4bc2cdcf7d670f5920120c0a868f77c2b0d052..bae50d13d17d405916b288032d42a80512ce3246 100644 (file)
@@ -251,23 +251,23 @@ fn find_library_crate_aux(sess: session::session,
         if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
             #debug("skipping %s, doesn't look like %s*%s", path, prefix,
                    suffix);
-            option::none
+            option::none::<()>
         } else {
             #debug("%s is a candidate", path);
             alt get_metadata_section(sess, path) {
               option::some(cvec) {
                 if !crate_matches(cvec, metas, hash) {
                     #debug("skipping %s, metadata doesn't match", path);
-                    option::none
+                    option::none::<()>
                 } else {
                     #debug("found %s with matching metadata", path);
                     matches += [{ident: path, data: cvec}];
-                    option::none
+                    option::none::<()>
                 }
               }
               _ {
                 #debug("could not load metadata for %s", path);
-                option::none
+                option::none::<()>
               }
             }
         }
index 9ba99139b902609d8ed97e98a7751d929791c5cb..68a721b634554fde8ba5514c1cf3a90c8dd4aad4 100644 (file)
@@ -70,7 +70,7 @@ fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num,
             result += [(cnum, cm.data, def)];
         } else {
             if cm.cnum_map.contains_key(def.crate) {
-                // This reexport is itself a reexport from anther crate
+                // This reexport is itself a reexport from another crate
                 let next_cnum = cm.cnum_map.get(def.crate);
                 let next_cm_data = cstore::get_crate_data(cstore, next_cnum);
                 result += [(next_cnum, next_cm_data.data, def)];
index d5e22815b7b47096956ee2ab7b88158960c1c22b..0477f6469cca5061d6e991e99292fce7b2047fc5 100644 (file)
@@ -579,11 +579,8 @@ fn eq_regions(a: ty::region, b: ty::region) -> ures {
 // [B].  Deep resolution, on the other hand, would yield [int].
 //
 // But there is one more knob: the force_vars variable controls the
-// behavior in the face of unconstrained variables.  If we have A, B
-// and only the constraint that A <: B, then the result is [_|_] if
-// force_vars is true and [B] otherwise.  We use force_vars == true
-// when resolving types after typeck, but false otherwise (for
-// example, when pretty-printing them for errors).
+// behavior in the face of unconstrained variables.  If it is true,
+// then unconstrained variables result in an error.
 
 type resolve_state = @{
     infcx: infer_ctxt,
@@ -673,8 +670,12 @@ fn resolve_region_var(rid: region_vid) -> ty::region {
             let r1 = alt bounds {
               { ub:_, lb:some(t) } { self.resolve_region(t) }
               { ub:some(t), lb:_ } { self.resolve_region(t) }
-              { ub:none, lb:none } if self.force_vars { ty::re_static }
-              { ub:none, lb:none } { ty::re_var(rid) }
+              { ub:none, lb:none } {
+                if self.force_vars {
+                    self.err = some(unresolved_region(rid));
+                }
+                ty::re_var(rid)
+              }
             };
             vec::pop(self.r_seen);
             ret r1;
@@ -700,8 +701,12 @@ fn resolve_ty_var(vid: ty_vid) -> ty::t {
               { ub:_, lb:some(t) } if !type_is_bot(t) { self.resolve1(t) }
               { ub:some(t), lb:_ } { self.resolve1(t) }
               { ub:_, lb:some(t) } { self.resolve1(t) }
-              { ub:none, lb:none } if self.force_vars { ty::mk_bot(tcx) }
-              { ub:none, lb:none } { ty::mk_var(tcx, vid) }
+              { ub:none, lb:none } {
+                if self.force_vars {
+                    self.err = some(unresolved_ty(vid));
+                }
+                ty::mk_var(tcx, vid)
+              }
             };
             vec::pop(self.v_seen);
             ret t1;
index 0b29b0c52cd70319da29a6fe43ae09d8bc7bad98..dee278e7ed031d32cae4bd25ed1fe4a517552ed4 100644 (file)
@@ -4,6 +4,7 @@
 import ty::{kind, kind_copyable, kind_sendable, kind_noncopyable};
 import driver::session::session;
 import std::map::hashmap;
+import syntax::print::pprust::expr_to_str;
 
 // Kind analysis pass. There are three kinds:
 //
@@ -138,6 +139,7 @@ fn check_block(b: blk, cx: ctx, v: visit::vt<ctx>) {
 }
 
 fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
+    #debug["kind::check_expr(%s)", expr_to_str(e)];
     alt e.node {
       expr_assign(_, ex) | expr_assign_op(_, _, ex) |
       expr_unary(box(_), ex) | expr_unary(uniq(_), ex) |
index 150466a70978b96dd1d0a8d0efd6ecb91b8f7028..3e380816dfd21395dc46f869bc58173e83d72c2f 100644 (file)
@@ -1998,8 +1998,14 @@ fn check_export(e: @env, ident: str, _mod: @indexed_mod,
                 }
             }
         }
-        found_something |= lookup_glob_any(e, _mod, vi.span, ident,
-                                           export_id);
+        /*
+          This code previously used bitwise or (|=) but that was wrong,
+          because we need or to be lazy here. If something was already
+          found, we don't want to call lookup_glob_any (see #2316 for
+          what happens if we do)
+         */
+        found_something = found_something ||
+           lookup_glob_any(e, _mod, vi.span, ident, export_id);
         if !found_something {
             e.sess.span_warn(vi.span,
                              #fmt("exported item %s is not defined", ident));
index 9830fe9c36b1392001e45ea0a5aba9bd9fdeec7b..cf8f223afd9d280ba8878d9d977b6b721e624423 100644 (file)
@@ -37,7 +37,7 @@
 export expr_is_lval;
 export field_ty;
 export fold_ty, fold_sty_to_ty, fold_region, fold_regions, fold_ty_var;
-export fold_regions_and_ty;
+export fold_regions_and_ty, walk_regions_and_ty;
 export field;
 export field_idx;
 export get_field;
@@ -97,7 +97,7 @@
 export ty_type, mk_type;
 export ty_uint, mk_uint, mk_mach_uint;
 export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
-export ty_var, mk_var;
+export ty_var, mk_var, type_is_var;
 export ty_self, mk_self;
 export region, bound_region;
 export get, type_has_params, type_has_vars, type_has_regions;
@@ -818,6 +818,21 @@ fn fold_ty_var(cx: ctxt, t0: t, fldop: fn(ty_vid) -> t) -> t {
     }
 }
 
+fn walk_regions_and_ty(
+    cx: ctxt,
+    ty: t,
+    walkr: fn(r: region),
+    walkt: fn(t: t) -> bool) {
+
+    if (walkt(ty)) {
+        fold_regions_and_ty(
+            cx, ty,
+            { |r| walkr(r); r },
+            { |t| walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t },
+            { |t| walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t });
+    }
+}
+
 fn fold_regions_and_ty(
     cx: ctxt,
     ty: t,
@@ -1000,6 +1015,13 @@ fn type_is_nil(ty: t) -> bool { get(ty).struct == ty_nil }
 
 fn type_is_bot(ty: t) -> bool { get(ty).struct == ty_bot }
 
+fn type_is_var(ty: t) -> bool {
+    alt get(ty).struct {
+      ty_var(_) { true }
+      _ { false }
+    }
+}
+
 fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
 
 fn type_is_structural(ty: t) -> bool {
index d8c275bfd0447f72d8c899916854160828ecabe4..931d3d9e7903bd77a17b38da3f5335cbcb2227ea 100644 (file)
@@ -105,6 +105,7 @@ fn foo<T: quux, baz, bar>(a: T) -- a's vtable would have a
      ty_var_counter: @mut uint,
      region_var_counter: @mut uint,
 
+     mut blocks: [ast::node_id], // stack of blocks in scope, may be empty
      in_scope_regions: isr_alist,
 
      // While type checking a function, the intermediate types for the
@@ -276,10 +277,8 @@ fn instantiate_path(fcx: @fn_ctxt,
 
 // Type tests
 fn structurally_resolved_type(fcx: @fn_ctxt, sp: span, tp: ty::t) -> ty::t {
-    alt infer::resolve_shallow(fcx.infcx, tp, true) {
-      // note: the bot type doesn't count as resolved; it's what we use when
-      // there is no information about a variable.
-      result::ok(t_s) if !ty::type_is_bot(t_s) { ret t_s; }
+    alt infer::resolve_shallow(fcx.infcx, tp, false) {
+      result::ok(t_s) if !ty::type_is_var(t_s) { ret t_s; }
       _ {
         fcx.ccx.tcx.sess.span_fatal
             (sp, "the type of this value must be known in this context");
@@ -322,7 +321,16 @@ fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint,
       ast::vstore_uniq { ty::vstore_uniq }
       ast::vstore_box { ty::vstore_box }
       ast::vstore_slice(r) {
-        ty::vstore_slice(ast_region_to_region(fcx, fcx, e.span, r))
+        alt fcx.block_region() {
+          result::ok(b_r) {
+            let rscope = in_anon_rscope(fcx, b_r);
+            ty::vstore_slice(ast_region_to_region(fcx, rscope, e.span, r))
+          }
+          result::err(msg) {
+            fcx.ccx.tcx.sess.span_err(e.span, msg);
+            ty::vstore_slice(ty::re_static)
+          }
+        }
       }
     }
 }
@@ -386,8 +394,9 @@ impl of region_scope for empty_rscope {
     fn anon_region() -> result<ty::region, str> {
         result::err("region types are not allowed here")
     }
-    fn named_region(_id: str) -> result<ty::region, str> {
-        result::err("region types are not allowed here")
+    fn named_region(id: str) -> result<ty::region, str> {
+        if id == "static" { result::ok(ty::re_static) }
+        else { result::err("only the static region is allowed here") }
     }
 }
 
@@ -395,9 +404,7 @@ fn named_region(_id: str) -> result<ty::region, str> {
 impl of region_scope for type_rscope {
     fn anon_region() -> result<ty::region, str> {
         alt *self {
-          ast::rp_self {
-            result::ok(ty::re_bound(ty::br_self))
-          }
+          ast::rp_self { result::ok(ty::re_bound(ty::br_self)) }
           ast::rp_none {
             result::err("to use region types here, the containing type \
                          must be declared with a region bound")
@@ -405,11 +412,12 @@ fn anon_region() -> result<ty::region, str> {
         }
     }
     fn named_region(id: str) -> result<ty::region, str> {
-        if id == "self" {
-            self.anon_region()
-        } else {
-            result::err("named regions other than `self` are not \
-                         allowed as part of a type declaration")
+        empty_rscope.named_region(id).chain_err { |_e|
+            if id == "self" { self.anon_region() }
+            else {
+                result::err("named regions other than `self` are not \
+                             allowed as part of a type declaration")
+            }
         }
     }
 }
@@ -419,11 +427,14 @@ fn anon_region() -> result<ty::region, str> {
         result::ok(self.next_region_var())
     }
     fn named_region(id: str) -> result<ty::region, str> {
-        alt self.in_scope_regions.find(ty::br_named(id)) {
-          some(r) { result::ok(r) }
-          none {
-            result::err(#fmt["named region `%s` not in scope here", id])
-          }
+        empty_rscope.named_region(id).chain_err { |_e|
+            alt self.in_scope_regions.find(ty::br_named(id)) {
+              some(r) { result::ok(r) }
+              none if id == "blk" { self.block_region() }
+              none {
+                result::err(#fmt["named region `%s` not in scope here", id])
+              }
+            }
         }
     }
 }
@@ -477,7 +488,6 @@ fn ast_region_to_region<AC: ast_conv, RS: region_scope>(
     let res = alt a_r.node {
       ast::re_anon { rscope.anon_region() }
       ast::re_named(id) { rscope.named_region(id) }
-      ast::re_static { result::ok(ty::re_static) }
     };
 
     get_region_reporting_err(self.tcx(), span, res)
@@ -772,6 +782,49 @@ fn check_path_args(tcx: ty::ctxt,
     ret typ;
 }
 
+fn check_bounds_are_used(ccx: @crate_ctxt,
+                         span: span,
+                         tps: [ast::ty_param],
+                         rp: ast::region_param,
+                         ty: ty::t) {
+    let mut r_used = alt rp {
+      ast::rp_self { false }
+      ast::rp_none { true }
+    };
+
+    if tps.len() == 0u && r_used { ret; }
+    let tps_used = vec::to_mut(vec::from_elem(tps.len(), false));
+
+    ty::walk_regions_and_ty(
+        ccx.tcx, ty,
+        { |r|
+            alt r {
+              ty::re_bound(_) { r_used = true; }
+              _ { }
+            }
+        },
+        { |t|
+            alt ty::get(t).struct {
+              ty::ty_param(idx, _) { tps_used[idx] = true; }
+              _ { }
+            }
+            true
+        });
+
+    if !r_used {
+        ccx.tcx.sess.span_err(
+            span, "lifetime `self` unused inside \
+                   reference-parameterized type.");
+    }
+
+    for tps_used.eachi { |i, b|
+        if !b {
+            ccx.tcx.sess.span_err(
+                span, #fmt["Type parameter %s is unused.", tps[i].ident]);
+        }
+    }
+}
+
 fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
     -> ty::ty_param_bounds_and_ty {
 
@@ -816,6 +869,9 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
             };
             {bounds: ty_param_bounds(ccx, tps), rp: rp, ty: ty}
         };
+
+        check_bounds_are_used(ccx, t.span, tps, rp, tpt.ty);
+
         tcx.tcache.insert(local_def(it.id), tpt);
         ret tpt;
       }
@@ -1125,6 +1181,12 @@ fn tag() -> str { #fmt["%x", ptr::addr_of(*self) as uint] }
     fn ty_to_str(t: ty::t) -> str {
         ty_to_str(self.ccx.tcx, resolve_type_vars_if_possible(self, t))
     }
+    fn block_region() -> result<ty::region, str> {
+        alt vec::last_opt(self.blocks) {
+          some(bid) { result::ok(ty::re_scope(bid)) }
+          none { result::err("no block is in scope here") }
+        }
+    }
     fn write_ty(node_id: ast::node_id, ty: ty::t) {
         #debug["write_ty(%d, %s) in fcx %s",
                node_id, ty_to_str(self.tcx(), ty), self.tag()];
@@ -3144,7 +3206,7 @@ fn unpack_expected<O: copy>(fcx: @fn_ctxt, expected: option<ty::t>,
         -> option<O> {
         alt expected {
           some(t) {
-            alt infer::resolve_shallow(fcx.infcx, t, true) {
+            alt infer::resolve_shallow(fcx.infcx, t, false) {
               result::ok(t) { unpack(ty::get(t).struct) }
               _ { none }
             }
@@ -3913,6 +3975,7 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
       ast::unsafe_blk { @{purity: ast::unsafe_fn with *fcx0} }
       ast::default_blk { fcx0 }
     };
+    vec::push(fcx.blocks, blk.node.id);
     let mut bot = false;
     let mut warned = false;
     for blk.node.stmts.each {|s|
@@ -3943,6 +4006,7 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
     if bot {
         fcx.write_bot(blk.node.id);
     }
+    vec::pop(fcx.blocks);
     ret bot;
 }
 
@@ -3960,6 +4024,7 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
           locals: int_hash(),
           ty_var_counter: @mut 0u,
           region_var_counter: @mut 0u,
+          mut blocks: [],
           in_scope_regions: @nil,
           node_types: smallintmap::mk(),
           node_type_substs: map::int_hash(),
@@ -4000,6 +4065,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
           locals: int_hash(),
           ty_var_counter: @mut 0u,
           region_var_counter: @mut 0u,
+          mut blocks: [],
           in_scope_regions: @nil,
           node_types: smallintmap::mk(),
           node_type_substs: map::int_hash(),
@@ -4262,6 +4328,7 @@ fn check_fn(ccx: @crate_ctxt,
           locals: locals,
           ty_var_counter: tvc,
           region_var_counter: rvc,
+          mut blocks: [],
           in_scope_regions: isr,
           node_types: node_types,
           node_type_substs: node_type_substs,
@@ -4350,21 +4417,27 @@ fn gather_locals(fcx: @fn_ctxt,
             visit::visit_pat(p, e, v);
         };
 
+        let visit_block = fn@(b: ast::blk, &&e: (), v: visit::vt<()>) {
+            vec::push(fcx.blocks, b.node.id);
+            visit::visit_block(b, e, v);
+            vec::pop(fcx.blocks);
+        };
+
         // Don't descend into fns and items
-        fn visit_fn<T>(_fk: visit::fn_kind, _decl: ast::fn_decl,
-                       _body: ast::blk, _sp: span,
-                       _id: ast::node_id, _t: T, _v: visit::vt<T>) {
+        fn visit_fn(_fk: visit::fn_kind, _decl: ast::fn_decl,
+                    _body: ast::blk, _sp: span,
+                    _id: ast::node_id, &&_t: (), _v: visit::vt<()>) {
         }
-        fn visit_item<E>(_i: @ast::item, _e: E, _v: visit::vt<E>) { }
+        fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { }
 
-        let visit =
-            @{visit_local: visit_local,
-              visit_pat: visit_pat,
-              visit_fn: bind visit_fn(_, _, _, _, _, _, _),
-              visit_item: bind visit_item(_, _, _)
-              with *visit::default_visitor()};
+        let visit = visit::mk_vt(@{visit_local: visit_local,
+                                   visit_pat: visit_pat,
+                                   visit_fn: visit_fn,
+                                   visit_item: visit_item,
+                                   visit_block: visit_block
+                                   with *visit::default_visitor()});
 
-        visit::visit_block(body, (), visit::mk_vt(visit));
+        visit.visit_block(body, (), visit);
     }
 }
 
index ed6fdaa6dc5edbf247341b81a0a2924cb1d3fbab..bdf16266d2e681595ece8baa6a0f347680ad0892 100644 (file)
@@ -97,7 +97,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
   const Target *TheTarget = TargetRegistry::lookupTarget(triple, Err);
   std::string FeaturesStr;
   std::string Trip(triple);
-  std::string CPUStr = llvm::sys::getHostCPUName();
+  std::string CPUStr("generic");
   TargetMachine *Target =
     TheTarget->createTargetMachine(Trip, CPUStr, FeaturesStr,
                                   Options, Reloc::PIC_,
diff --git a/src/test/auxiliary/issue_2316_a.rs b/src/test/auxiliary/issue_2316_a.rs
new file mode 100644 (file)
index 0000000..418ddc0
--- /dev/null
@@ -0,0 +1,3 @@
+enum cat {
+  tabby, calico, tortoiseshell
+}
diff --git a/src/test/auxiliary/issue_2316_b.rs b/src/test/auxiliary/issue_2316_b.rs
new file mode 100644 (file)
index 0000000..c1be44d
--- /dev/null
@@ -0,0 +1,16 @@
+use issue_2316_a;
+
+mod cloth {
+
+import issue_2316_a::*;
+
+export calico, gingham, flannel;
+export fabric;
+
+enum fabric {
+  gingham, flannel, calico
+}
+
+}
+
+
diff --git a/src/test/compile-fail/issue-1763.rs b/src/test/compile-fail/issue-1763.rs
new file mode 100644 (file)
index 0000000..678e3cc
--- /dev/null
@@ -0,0 +1,7 @@
+// Issue #1763 - infer types correctly
+
+type actor<T> = { //! ERROR Type parameter T is unused.
+    unused: bool
+};
+
+fn main() {}
index 89437289ebc49bd436540924d9eed85f98338329..15b3d6d96c7ed7f157a09cef7afb2c2ed6caa6d0 100644 (file)
@@ -1,5 +1,5 @@
 fn main(s: [str]) {
-    let a = [];
+    let a: [int] = [];
     vec::each(a) { |x| //! ERROR in function `anon`, not all control paths
     }                  //! ERROR see function return type of `bool`
 }
diff --git a/src/test/compile-fail/region-unused.rs b/src/test/compile-fail/region-unused.rs
new file mode 100644 (file)
index 0000000..6173158
--- /dev/null
@@ -0,0 +1,3 @@
+type foo/& = {f: int}; //! ERROR lifetime `self` unused
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/regions-blk.rs b/src/test/compile-fail/regions-blk.rs
new file mode 100644 (file)
index 0000000..0d0cdb6
--- /dev/null
@@ -0,0 +1,15 @@
+fn foo(cond: bool) {
+    let x = 5;
+    let mut y: &blk.int = &x;
+
+    let mut z: &blk.int;
+    if cond {
+        z = &x;
+    } else {
+        let w: &blk.int = &x;
+        z = w; //! ERROR mismatched types
+    }
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/regions-in-consts.rs b/src/test/compile-fail/regions-in-consts.rs
new file mode 100644 (file)
index 0000000..c48fec0
--- /dev/null
@@ -0,0 +1,7 @@
+// xfail-test
+
+const c_x: &blk.int = 22; //! ERROR only the static region is allowed here
+const c_y: &static.int = &22; //! ERROR only the static region is allowed here
+
+fn main() {
+}
\ No newline at end of file
index 49202a340a14634f93caf576925f5ab1d5264059..c4619001e7cd00af80bb6137933bdfa4f8d109da 100644 (file)
@@ -18,7 +18,7 @@
     x: &self.uint
 };
 
-type item_ty_yes2/& = {
+type item_ty_yes2/& = { //! ERROR lifetime `self` unused inside reference-parameterized type
     x: &foo.uint //! ERROR named regions other than `self` are not allowed as part of a type declaration
 };
 
diff --git a/src/test/compile-fail/regions-out-of-scope-slice.rs b/src/test/compile-fail/regions-out-of-scope-slice.rs
new file mode 100644 (file)
index 0000000..5f5aada
--- /dev/null
@@ -0,0 +1,13 @@
+// xfail-test
+
+fn foo(cond: bool) {
+    // Here we will infer a type that uses the
+    // region of the if stmt then block, but in the scope:
+    let mut x; //! ERROR foo
+
+    if cond {
+        x = [1,2,3]/&blk;
+    }
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/regions-var-type-out-of-scope.rs b/src/test/compile-fail/regions-var-type-out-of-scope.rs
new file mode 100644 (file)
index 0000000..b8aecb0
--- /dev/null
@@ -0,0 +1,13 @@
+// xfail-test
+
+fn foo(cond: bool) {
+    // Here we will infer a type that uses the
+    // region of the if stmt then block:
+    let mut x; //! ERROR foo
+
+    if cond {
+        x = &3;
+    }
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/unreachable-code-1.rs b/src/test/compile-fail/unreachable-code-1.rs
deleted file mode 100644 (file)
index 1dba6f9..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// xfail-pretty
-
-fn id(x: bool) -> bool { x }
-
-fn call_id() {
-    let c <- fail;
-    id(c); //! WARNING unreachable statement
-}
-
-fn call_id_3() { id(ret) && id(ret); }
-    //!^ ERROR the type of this value must be known
-
-fn main() {
-}
index 3f1c0ab41e6bd69df4409b231902d2b58e320286..4fe164878a840f389771efa0809061152456440e 100644 (file)
@@ -4,7 +4,8 @@ fn send<T: send>(ch: _chan<T>, -data: T) {
     log(debug, data);
     fail;
 }
-type _chan<T> = int;
+
+enum _chan<T> = int;
 
 // Tests that "log(debug, message);" is flagged as using
 // message after the send deinitializes it
diff --git a/src/test/compile-fail/vector-no-ann.rs b/src/test/compile-fail/vector-no-ann.rs
new file mode 100644 (file)
index 0000000..8d4478d
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    let _foo = []; //! ERROR unconstrained type
+}
index 62206f939949475727ef8db2e6bd3eb4d2e846ee..a7d360ff8fc392185419a292f4521f970598f76b 100644 (file)
@@ -4,7 +4,7 @@
 type task_id = int;
 type port_id = int;
 
-type chan_t<T: send> = {task: task_id, port: port_id};
+enum chan_t<T: send> = {task: task_id, port: port_id};
 
 fn send<T: send>(ch: chan_t<T>, -data: T) { fail; }
 
diff --git a/src/test/run-fail/issue-1763.rs b/src/test/run-fail/issue-1763.rs
deleted file mode 100644 (file)
index 36ea0d9..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Issue #1763 - infer types correctly
-// error-pattern:explicit failure
-
-type actor<T> = {
-    unused: bool
-};
-
-fn act2<T>() -> actor<T> {
-    fail;
-}
-
-fn main() {
-    let a: actor<int> = act2();
-}
index 3b8e693e9699da51889fdb0477126e6975eac80d..6f614258bcbefb8b71b73804d7fa89f8cc8ea705 100644 (file)
@@ -1,4 +1,4 @@
 // error-pattern:get called on error result: "kitty"
 fn main() {
-  log(error, result::get(result::err("kitty")));
+  log(error, result::get(result::err::<int,str>("kitty")));
 }
\ No newline at end of file
index 28ddbfdd1e2fb8738fed844201e8c0b506058353..d46f501f0fafdbda4fa9cc63ecd25e42959f2b16 100644 (file)
@@ -1,3 +1,5 @@
+// xfail-test
+
 // xfail-fast
 // aux-build:cci_class_6.rs
 use cci_class_6;
diff --git a/src/test/run-pass/issue-2316-c.rs b/src/test/run-pass/issue-2316-c.rs
new file mode 100644 (file)
index 0000000..27f4d89
--- /dev/null
@@ -0,0 +1,10 @@
+// xfail-fast - check-fast doesn't understand aux-build
+// aux-build:issue_2316_a.rs
+// aux-build:issue_2316_b.rs
+
+use issue_2316_b;
+import issue_2316_b::cloth;
+
+fn main() {
+  let _c: cloth::fabric = cloth::calico;
+}
\ No newline at end of file
diff --git a/src/test/run-pass/issue-2316.rs b/src/test/run-pass/issue-2316.rs
new file mode 100644 (file)
index 0000000..a95b984
--- /dev/null
@@ -0,0 +1,5 @@
+use rustc;
+import rustc::middle::ty;
+fn main() {
+  let _t: ty::sty = rustc::middle::ty::ty_nil;
+}
index 1f7afdb1c7be7bd9da2e2c1373b2860a845e429d..3b2f1b2ced5b6558d95b5f1e7282a2f9135dd882 100644 (file)
@@ -1,7 +1,8 @@
 fn main() {
     assert [1u, 3u].to_vec() == [1u, 3u];
-    assert [].to_vec() == [];
-    assert none.to_vec() == [];
+    let e: [uint] = [];
+    assert e.to_vec() == [];
+    assert none::<uint>.to_vec() == [];
     assert some(1u).to_vec() == [1u];
     assert some(2u).to_vec() == [2u];
 }
\ No newline at end of file
index 4568bca444c9d5efacab047f13b4418f3a13d418..822ed735f772e817877787b89c809af337e3a592 100644 (file)
@@ -16,7 +16,7 @@
 };
 
 fn alloc(_bcx : &a.arena) -> &a.bcx unsafe {
-    ret unsafe::reinterpret_cast(libc::malloc(sys::size_of::<bcx>()));
+    ret unsafe::reinterpret_cast(libc::malloc(sys::size_of::<bcx/&blk>()));
 }
 
 fn h(bcx : &a.bcx) -> &a.bcx {
diff --git a/src/test/run-pass/unreachable-code-1.rs b/src/test/run-pass/unreachable-code-1.rs
new file mode 100644 (file)
index 0000000..38b97b4
--- /dev/null
@@ -0,0 +1,13 @@
+// xfail-pretty
+
+fn id(x: bool) -> bool { x }
+
+fn call_id() {
+    let c <- fail;
+    id(c); //! WARNING unreachable statement
+}
+
+fn call_id_3() { id(ret) && id(ret); }
+
+fn main() {
+}
diff --git a/src/test/run-pass/unreachable-code.rs b/src/test/run-pass/unreachable-code.rs
deleted file mode 100644 (file)
index c972241..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// xfail-pretty
-
-fn id(x: bool) -> bool { x }
-
-fn call_id() {
-    let c <- fail;
-    id(c);
-}
-
-fn call_id_2() { id(true) && id(ret); }
-
-fn call_id_4() { while id(ret) { } }
-
-fn bind_id_1() { bind id(fail); }
-
-fn bind_id_2() { bind id(ret); }
-
-fn fail_fail() { fail fail; }
-
-fn log_fail() { log(error, fail); }
-
-fn log_ret() { log(error, ret); }
-
-fn log_break() { loop { log(error, break); } }
-
-fn log_cont() { do { log(error, cont); } while false }
-
-fn ret_ret() -> int { ret 3 + (ret 2); }
-
-fn ret_guard() {
-    alt check 2 {
-      x if (ret) { x; }
-    }
-}
-
-fn rec_ret() { let _r: {c: int} = {c: ret}; }
-
-fn vec_ret() { let _v: [int] = [1, 2, ret, 4]; }
-
-fn fail_then_concat() {
-    let mut x = [], y = [3];
-    fail;
-    x += y;
-    "good" + "bye";
-}
-
-fn main() {
-  // Call the functions that don't fail.
-  rec_ret();
-  vec_ret();
-  ret_ret();
-  log_ret();
-  call_id_2();
-  call_id_4();
-  bind_id_2();
-  ret_guard();
-}
diff --git a/src/test/run-pass/vector-no-ann.rs b/src/test/run-pass/vector-no-ann.rs
deleted file mode 100644 (file)
index dec8ca2..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    // We will infer this to have the type vec[bot]
-    let _foo = [];
-}
index e13c1a0d6af3ed1df4b07e066bda9ff699b6bc33..bf3bd4c8ae6e5feb5766b49bbc3a7c478a0c9b62 100644 (file)
@@ -1,6 +1,6 @@
 // Just a grab bag of stuff that you wouldn't want to actually write.
 
-fn strange() -> bool { let _x = ret true; }
+fn strange() -> bool { let _x: bool = ret true; }
 
 fn funny() {
     fn f(_x: ()) { }
@@ -20,13 +20,14 @@ fn zombiejesus() {
         while (ret) {
             if (ret) {
                 alt (ret) {
-                    _ {
+                    1 {
                         if (ret) {
                             ret
                         } else {
                             ret
                         }
                     }
+                    _ { ret }
                 };
             } else if (ret) {
                 ret;
@@ -51,7 +52,7 @@ fn canttouchthis() -> uint {
     pure fn p() -> bool { true }
     let _a = (assert (true)) == (check (p()));
     let _c = (check (p())) == ();
-    let _b = (log(debug, 0) == (ret 0u));
+    let _b: bool = (log(debug, 0) == (ret 0u));
 }
 
 fn angrydome() {