~~~~
fn iter<T>(seq: [T], f: fn(T)) {
- for elt: T in seq { f(elt); }
+ for seq.each {|elt| f(elt); }
}
fn map<T, U>(seq: [T], f: fn(T) -> U) -> [U] {
let mut acc = [];
- for elt in seq { acc += [f(elt)]; }
+ for seq.each {|elt| acc += [f(elt)]; }
acc
}
~~~~
task in a _failing state_.
~~~~
-# let builder = task::task_builder();
-# task::unsupervise(builder);
-# task::run(builder) {||
+# let buildr = task::builder();
+# task::unsupervise(buildr);
+# task::run(buildr) {||
[1, 2, 3, 4][0];
[mut 'x', 'y'][1] = 'z';
let v: [foo] = [a, b, c];
-for e: foo in v {
+for v.each {|e|
bar(e);
}
~~~~
~~~~
Multiple alternative patterns may be joined with the `|` operator. A
-range of values may be specified with `to`. For example:
+range of values may be specified with `to`. For example:
~~~~
# let x = 2;
} while any_cake_left();
~~~~
-When iterating over a vector, use `for` instead.
-
-~~~~
-for elt in ["red", "green", "blue"] {
- io::println(elt);
-}
-~~~~
-
-This will go over each element in the given vector (a three-element
-vector of strings, in this case), and repeatedly execute the body with
-`elt` bound to the current element. You may add an optional type
-declaration (`elt: str`) for the iteration variable if you want.
-
For more involved iteration, such as going over the elements of a hash
table, Rust uses higher-order functions. We'll come back to those in a
moment.
~~~~
If an explicit discriminator is not specified for a variant, the value
-defaults to the value of the previous variant plus one. If the first
-variant does not have a discriminator, it defaults to 0. For example,
+defaults to the value of the previous variant plus one. If the first
+variant does not have a discriminator, it defaults to 0. For example,
the value of `north` is 0, `east` is 1, etc.
When an enum is C-like the `as` cast operator can be used to get the
~~~~
fn for_each(v: [mut @int], iter: fn(@int)) {
- for elt in v { iter(elt); }
+ for v.each {|elt| iter(elt); }
}
~~~~
~~~~
type mutrec = {mut x: int};
fn for_each(v: [mut mutrec], iter: fn(mutrec)) {
- for elt in v { iter(copy elt); }
+ for v.each {|elt| iter(copy elt); }
}
~~~~
fn map<T, U>(v: [T], f: fn(T) -> U) -> [U] {
let mut acc = [];
- for elt in v { acc += [f(elt)]; }
+ for v.each {|elt| acc += [f(elt)]; }
ret acc;
}
~~~~
~~~~
let n = option::none;
-# option::with_option_do(n, fn&(&&x:int) {})
+# option::iter(n, fn&(&&x:int) {})
~~~~
If you never do anything else with `n`, the compiler will not be able
~~~~ {.ignore}
#[link(name = "farm", vers = "2.5", author = "mjh")];
+#[crate_type = "lib"];
mod cow;
mod chicken;
mod horse;
Compiling this file will cause `rustc` to look for files named
`cow.rs`, `chicken.rs`, `horse.rs` in the same directory as the `.rc`
file, compile them all together, and, depending on the presence of the
-`--lib` switch, output a shared library or an executable.
+`crate_type = "lib"` attribute, output a shared library or an executable.
+(If the line `#[crate_type = "lib"];` was omitted, `rustc` would create an
+executable.)
The `#[link(...)]` part provides meta information about the module,
which other crates can use to load the right module. More about that
## Using other crates
-Having compiled a crate with `--lib`, you can use it in another crate
-with a `use` directive. We've already seen `use std` in several of the
-examples, which loads in the [standard library][std].
+Having compiled a crate that contains the `#[crate_type = "lib"]` attribute,
+you can use it in another crate with a `use` directive. We've already seen
+`use std` in several of the examples, which loads in the [standard library][std].
[std]: http://doc.rust-lang.org/doc/std/index/General.html
# iface to_str { fn to_str() -> str; }
fn comma_sep<T: to_str>(elts: [T]) -> str {
let mut result = "", first = true;
- for elt in elts {
+ for elts.each {|elt|
if first { first = false; }
else { result += ", "; }
result += elt.to_str();
impl <T> of seq<T> for [T] {
fn len() -> uint { vec::len(self) }
fn iter(b: fn(T)) {
- for elt in self { b(elt); }
+ for self.each {|elt| b(elt); }
}
}
~~~~
~~~~
# iface drawable { fn draw(); }
fn draw_all<T: drawable>(shapes: [T]) {
- for shape in shapes { shape.draw(); }
+ for shapes.each {|shape| shape.draw(); }
}
~~~~
~~~~
# iface drawable { fn draw(); }
fn draw_all(shapes: [drawable]) {
- for shape in shapes { shape.draw(); }
+ for shapes.each {|shape| shape.draw(); }
}
~~~~
fn as_hex(data: [u8]) -> str {
let mut acc = "";
- for byte in data { acc += #fmt("%02x", byte as uint); }
+ for data.each {|byte| acc += #fmt("%02x", byte as uint); }
ret acc;
}
$$(TLIB2_T_$(2)_H_$(3))/$$(FT_LIB) \
$$(SREQ2_T_$(2)_H_$(3))
@$$(call E, compile_and_link: $$@ $$<)
- $$(STAGE2_T_$(2)_H_$(3)) -L $$(TLIB2_T_$(2)_H_$(3)) -o $$@ $$<
+ $$(STAGE2_T_$(2)_H_$(3)) -o $$@ $$<
$(3)/test/$$(FT_DRIVER)-$(2).out: \
$(3)/test/$$(FT_DRIVER)-$(2)$$(X) \
#[crate_type = "bin"];
+#[no_core];
+
+use core(vers = "0.2");
+use std(vers = "0.2");
+use rustc(vers = "0.2");
+
+import core::*;
+
mod pgp;
// cargo.rs - Rust package manager
-use rustc;
-use std;
-
import rustc::syntax::{ast, codemap};
import rustc::syntax::parse::parser;
import rustc::util::filesearch::{get_cargo_root, get_cargo_root_nearest,
let mut name = none;
let mut vers = none;
let mut uuid = none;
- for a: @ast::meta_item in mis {
+ for mis.each {|a|
alt a.node {
ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
alt v {
let mut sigs = none;
let mut crate_type = none;
- for a in c.node.attrs {
+ for c.node.attrs.each {|a|
alt a.node.value.node {
ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
alt v {
let mut tags = [];
alt p.find("tags") {
some(json::list(js)) {
- for j in js {
+ for js.each {|j|
alt j {
json::string(_j) { vec::grow(tags, 1u, _j); }
_ { }
let pkgstr = io::read_whole_file_str(pkgfile);
alt json::from_str(result::get(pkgstr)) {
ok(json::list(js)) {
- for _j: json::json in js {
+ for js.each {|_j|
alt _j {
json::dict(_p) {
load_one_source_package(src, _p);
fn for_each_package(c: cargo, b: fn(source, package)) {
c.sources.values({ |v|
- for p in copy v.packages {
+ for vec::each(copy v.packages) {|p|
b(v, p);
}
})
// Runs all programs in directory <buildpath>
fn run_programs(buildpath: str) {
let newv = os::list_dir_path(buildpath);
- for ct: str in newv {
+ for newv.each {|ct|
run::run_program(ct, []);
}
}
};
let newv = os::list_dir_path(buildpath);
let exec_suffix = os::exe_suffix();
- for ct: str in newv {
+ for newv.each {|ct|
if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
(exec_suffix == "" && !str::starts_with(path::basename(ct),
"lib")) {
fail "This doesn't look like a rust package (no .rc files).";
}
- for cf: str in cratefiles {
+ for cratefiles.each {|cf|
let p = load_pkg(cf);
alt p {
none { cont; }
ret;
}
error("Found multiple packages:");
- for (s,p) in ps {
+ for ps.each {|elt|
+ let (s,p) = elt;
info(" " + s.name + "/" + p.uuid + " (" + p.name + ")");
}
}
ret;
}
error("Found multiple packages:");
- for (s,p) in ps {
+ for ps.each {|elt|
+ let (s,p) = elt;
info(" " + s.name + "/" + p.uuid + " (" + p.name + ")");
}
}
-use std;
-
fn gpg(args: [str]) -> { status: int, out: str, err: str } {
ret run::program_output("gpg", args);
}
let p = gpg(["--homedir", path, "--with-fingerprint", "--verify", sig,
data]);
let res = "Primary key fingerprint: " + keyfp;
- for line in str::split_char(p.err, '\n') {
- if line == res {
- ret true;
- }
+ let mut rslt = false;
+ for str::split_char(p.err, '\n').each {|line|
+ if line == res { rslt = true; }
}
- ret false;
+ ret rslt;
}
#[crate_type = "bin"];
-use std;
+#[no_core];
+
+use core(vers = "0.2");
+use std(vers = "0.2");
+
+import core::*;
mod procsrv;
mod util;
fn make_tests(config: config) -> [test::test_desc] {
#debug("making tests from %s", config.src_base);
let mut tests = [];
- for file: str in os::list_dir_path(config.src_base) {
+ for os::list_dir_path(config.src_base).each {|file|
let file = file;
#debug("inspecting file %s", file);
if is_test(config, file) {
let mut valid = false;
- for ext in valid_extensions {
+ for valid_extensions.each {|ext|
if str::ends_with(name, ext) { valid = true; }
}
- for pre in invalid_prefixes {
+ for invalid_prefixes.each {|pre|
if str::starts_with(name, pre) { valid = false; }
}
pp_exact = parse_pp_exact(ln, testfile);
}
- option::with_option_do(parse_aux_build(ln)) {|ab|
+ option::iter(parse_aux_build(ln)) {|ab|
aux_builds += [ab];
}
};
let mut next_err_idx = 0u;
let mut next_err_pat = props.error_patterns[next_err_idx];
- for line: str in str::split_char(procres.stderr, '\n') {
+ let mut done = false;
+ for str::split_char(procres.stderr, '\n').each {|line|
if str::contains(line, next_err_pat) {
#debug("found error pattern %s", next_err_pat);
next_err_idx += 1u;
if next_err_idx == vec::len(props.error_patterns) {
#debug("found all error patterns");
- ret;
+ done = true;
+ break;
}
next_err_pat = props.error_patterns[next_err_idx];
}
}
+ if done { ret; }
let missing_patterns =
vec::slice(props.error_patterns, next_err_idx,
fatal_procres(#fmt["error pattern '%s' not found!",
missing_patterns[0]], procres);
} else {
- for pattern: str in missing_patterns {
+ for missing_patterns.each {|pattern|
error(#fmt["error pattern '%s' not found!", pattern]);
}
fatal_procres("multiple error patterns not found", procres);
// filename:line1:col1: line2:col2: *warning:* msg
// where line1:col1: is the starting point, line2:col2:
// is the ending point, and * represents ANSI color codes.
- for line: str in str::split_char(procres.stderr, '\n') {
+ for str::split_char(procres.stderr, '\n').each {|line|
let mut was_expected = false;
- vec::iteri(expected_errors) {|i, ee|
+ for vec::eachi(expected_errors) {|i, ee|
if !found_flags[i] {
#debug["prefix=%s ee.kind=%s ee.msg=%s line=%s",
prefixes[i], ee.kind, ee.msg, line];
str::contains(line, ee.msg)) {
found_flags[i] = true;
was_expected = true;
+ break;
}
}
}
--- /dev/null
+#!/usr/bin/perl -w
+
+$ident = 0;
+while (<>) {
+ if (/^rust: ">>/) {
+ $indent += 1;
+ } elsif (/^rust: "<</) {
+ $indent -= 1;
+ }
+
+ printf "%03d ", $indent;
+ for ($i = 0; $i < $indent; $i++) {
+ printf(" ");
+ }
+ print;
+}
+
#[crate_type = "bin"];
-use std;
-use rustc;
+#[no_core];
+
+use core(vers = "0.2");
+use std(vers = "0.2");
+use rustc(vers = "0.2");
+
+import core::*;
// Local Variables:
// fill-column: 78;
} else if os::path_is_dir(path)
&& !contains(path, "compile-fail")
&& !contains(path, "build") {
- for p in os::list_dir_path(path) {
+ for os::list_dir_path(path).each {|p|
find_rust_files(files, p);
}
}
ast::expr_if_check(_, _, _) { false }
ast::expr_block(_) { false }
ast::expr_alt(_, _, _) { false }
- ast::expr_for(_, _, _) { false }
ast::expr_while(_, _) { false }
// https://github.com/mozilla/rust/issues/955
"unsafe",
"log"]; // python --> rust pipe deadlock?
- for p: str in dangerous_patterns { if contains(code, p) { ret true; } }
+ for dangerous_patterns.each {|p| if contains(code, p) { ret true; } }
ret false;
}
let dangerous_patterns =
["xfail-test"];
- for p: str in dangerous_patterns { if contains(code, p) { ret true; } }
+ for dangerous_patterns.each {|p| if contains(code, p) { ret true; } }
ret false;
}
"\n\n\n\n\n" // https://github.com/mozilla/rust/issues/850
];
- for p: str in confusing_patterns { if contains(code, p) { ret true; } }
+ for confusing_patterns.each {|p| if contains(code, p) { ret true; } }
ret false;
}
];
- for f in confusing_files { if contains(filename, f) { ret true; } }
+ for confusing_files.each {|f| if contains(filename, f) { ret true; } }
ret false;
}
fn check_convergence(files: [str]) {
#error("pp convergence tests: %u files", vec::len(files));
- for file in files {
+ for files.each {|file|
if !file_might_not_converge(file) {
let s = @result::get(io::read_whole_file_str(file));
if !content_might_not_converge(*s) {
}
fn check_variants(files: [str], cx: context) {
- for file in files {
+ for files.each {|file|
if cx.mode == tm_converge && file_might_not_converge(file) {
#error("Skipping convergence test based on file_might_not_converge");
cont;
#[abi = "cdecl"]
native mod rustrt {
- fn rust_port_id_send<T: send>(t: *sys::type_desc,
- target_port: port_id,
+ fn rust_port_id_send<T: send>(target_port: port_id,
data: T) -> libc::uintptr_t;
fn new_port(unit_sz: libc::size_t) -> *rust_port;
"]
fn send<T: send>(ch: chan<T>, -data: T) {
let chan_t(p) = ch;
- let res = rustrt::rust_port_id_send(sys::get_type_desc::<T>(), p, data);
+ let res = rustrt::rust_port_id_send(p, data);
if res != 0u unsafe {
// Data sent successfully
unsafe::forget(data);
export tuple;
export to_str;
+// FIXME: This creates some APIs that I do not want to commit to. It is
+// currently exported for the uv code in std, but when that code moves into
+// core this should become unexported
+export priv;
+
// Built-in-type support modules
mod box;
// For internal use by char, not exported
mod unicode;
-
+// Do not export
+mod priv;
// Ubiquitous-utility-type modules
// Similar to above. Some magic to make core testable.
#[cfg(test)]
mod std {
- use std;
+ use std(vers = "0.2");
import std::test;
}
impl<A> of iterable<A> for option<A> {
fn iter(blk: fn(A)) {
- option::with_option_do(self, blk)
+ option::iter(self, blk)
}
}
alt opt { some(x) { x } none { def } }
}
-fn with_option<T, U: copy>(opt: option<T>, def: U, f: fn(T) -> U) -> U {
+fn map_default<T, U: copy>(opt: option<T>, def: U, f: fn(T) -> U) -> U {
#[doc = "Applies a function to the contained value or returns a default"];
alt opt { none { def } some(t) { f(t) } }
}
-fn with_option_do<T>(opt: option<T>, f: fn(T)) {
+fn iter<T>(opt: option<T>, f: fn(T)) {
#[doc = "Performs an operation on the contained value or does nothing"];
alt opt { none { } some(t) { f(t); } }
#[doc = "Returns the contained value or a default"]
fn get_or_default(def: T) -> T { get_or_default(self, def) }
#[doc = "Applies a function to the contained value or returns a default"]
- fn with_option<U: copy>(def: U, f: fn(T) -> U) -> U
- { with_option(self, def, f) }
+ fn map_default<U: copy>(def: U, f: fn(T) -> U) -> U
+ { map_default(self, def, f) }
#[doc = "Performs an operation on the contained value or does nothing"]
- fn with_option_do(f: fn(T)) { with_option_do(self, f) }
+ fn iter(f: fn(T)) { iter(self, f) }
#[doc = "
Gets the value out of an option
}
rustrt::rust_list_files(star(p)).filter {|filename|
- !str::eq(filename, ".") || !str::eq(filename, "..")
+ !str::eq(filename, ".") && !str::eq(filename, "..")
}
}
}
#[test]
+ #[ignore]
fn test_env_getenv() {
let e = env();
assert vec::len(e) > 0u;
setenv("HOME", "");
assert os::homedir() == none;
- option::with_option_do(oldhome, {|s| setenv("HOME", s)});
+ option::iter(oldhome, {|s| setenv("HOME", s)});
}
#[test]
setenv("USERPROFILE", "/home/PaloAlto");
assert os::homedir() == some("/home/MountainView");
- option::with_option_do(oldhome, {|s| setenv("HOME", s)});
- option::with_option_do(olduserprofile,
+ option::iter(oldhome, {|s| setenv("HOME", s)});
+ option::iter(olduserprofile,
{|s| setenv("USERPROFILE", s)});
}
};
assert (ostream as uint != 0u);
let s = "hello";
- let mut buf = str::bytes(s) + [0 as u8];
+ let mut buf = vec::to_mut(str::bytes(s) + [0 as u8]);
vec::as_mut_buf(buf) {|b|
assert (libc::fwrite(b as *c_void, 1u, str::len(s) + 1u, ostream) ==
buf.len())};
--- /dev/null
+#[doc(hidden)];
+
+export chan_from_global_ptr;
+
+import compare_and_swap = rustrt::rust_compare_and_swap_ptr;
+
+type rust_port_id = uint;
+
+native mod rustrt {
+ fn rust_compare_and_swap_ptr(address: *libc::uintptr_t,
+ oldval: libc::uintptr_t,
+ newval: libc::uintptr_t) -> bool;
+ fn rust_task_weaken(ch: rust_port_id);
+ fn rust_task_unweaken(ch: rust_port_id);
+}
+
+type global_ptr<T: send> = *libc::uintptr_t;
+
+#[doc = "
+Atomically gets a channel from a pointer to a pointer-sized memory location
+or, if no channel exists creates and installs a new channel and sets up a new
+task to receive from it.
+"]
+unsafe fn chan_from_global_ptr<T: send>(
+ global: global_ptr<T>,
+ builder: fn() -> task::builder,
+ f: fn~(comm::port<T>)
+) -> comm::chan<T> {
+
+ enum msg {
+ proceed,
+ abort
+ }
+
+ let is_probably_zero = *global == 0u;
+ if is_probably_zero {
+ // There's no global channel. We must make it
+
+ let setup_po = comm::port();
+ let setup_ch = comm::chan(setup_po);
+ let setup_ch = task::run_listener(builder()) {|setup_po|
+ let po = comm::port::<T>();
+ let ch = comm::chan(po);
+ comm::send(setup_ch, ch);
+
+ // Wait to hear if we are the official instance of
+ // this global task
+ alt comm::recv::<msg>(setup_po) {
+ proceed { f(po); }
+ abort { }
+ }
+ };
+
+ // This is the proposed global channel
+ let ch = comm::recv(setup_po);
+ // 0 is our sentinal value. It is not a valid channel
+ assert unsafe::reinterpret_cast(ch) != 0u;
+
+ // Install the channel
+ let swapped = compare_and_swap(
+ global, 0u, unsafe::reinterpret_cast(ch));
+
+ if swapped {
+ // Success!
+ comm::send(setup_ch, proceed);
+ ch
+ } else {
+ // Somebody else got in before we did
+ comm::send(setup_ch, abort);
+ unsafe::reinterpret_cast(*global)
+ }
+ } else {
+ unsafe::reinterpret_cast(*global)
+ }
+}
+
+#[test]
+fn test_from_global_chan1() unsafe {
+
+ // This is unreadable, right?
+
+ // The global channel
+ let globchan = 0u;
+ let globchanp = ptr::addr_of(globchan);
+
+ // Create the global channel, attached to a new task
+ let ch = chan_from_global_ptr(globchanp, task::builder) {|po|
+ let ch = comm::recv(po);
+ comm::send(ch, true);
+ let ch = comm::recv(po);
+ comm::send(ch, true);
+ };
+ // Talk to it
+ let po = comm::port();
+ comm::send(ch, comm::chan(po));
+ assert comm::recv(po) == true;
+
+ // This one just reuses the previous channel
+ let ch = chan_from_global_ptr(globchanp, task::builder) {|po|
+ let ch = comm::recv(po);
+ comm::send(ch, false);
+ };
+
+ // Talk to the original global task
+ let po = comm::port();
+ comm::send(ch, comm::chan(po));
+ assert comm::recv(po) == true;
+}
+
+#[test]
+fn test_from_global_chan2() unsafe {
+
+ iter::repeat(100u) {||
+ // The global channel
+ let globchan = 0u;
+ let globchanp = ptr::addr_of(globchan);
+
+ let resultpo = comm::port();
+ let resultch = comm::chan(resultpo);
+
+ // Spawn a bunch of tasks that all want to compete to
+ // create the global channel
+ uint::range(0u, 10u) {|i|
+ task::spawn() {||
+ let ch = chan_from_global_ptr(
+ globchanp, task::builder) {|po|
+
+ uint::range(0u, 10u) {|_j|
+ let ch = comm::recv(po);
+ comm::send(ch, {i});
+ }
+ };
+ let po = comm::port();
+ comm::send(ch, comm::chan(po));
+ // We are the winner if our version of the
+ // task was installed
+ let winner = comm::recv(po);
+ comm::send(resultch, winner == i);
+ }
+ }
+ // There should be only one winner
+ let mut winners = 0u;
+ uint::range(0u, 10u) {|_i|
+ let res = comm::recv(resultpo);
+ if res { winners += 1u };
+ }
+ assert winners == 1u;
+ }
+}
+
+#[doc = "
+Convert the current task to a 'weak' task temporarily
+
+As a weak task it will not be counted towards the runtime's set
+of live tasks. When there are no more outstanding live (non-weak) tasks
+the runtime will send an exit message on the provided channel.
+
+This function is super-unsafe. Do not use.
+
+# Safety notes
+
+* Weak tasks must either die on their own or exit upon receipt of
+ the exit message. Failure to do so will cause the runtime to never
+ exit
+* Tasks must not call `weaken_task` multiple times. This will
+ break the kernel's accounting of live tasks.
+* Weak tasks must not be supervised. A supervised task keeps
+ a reference to its parent, so the parent will not die.
+"]
+unsafe fn weaken_task(f: fn(comm::port<()>)) unsafe {
+ let po = comm::port();
+ let ch = comm::chan(po);
+ rustrt::rust_task_weaken(unsafe::reinterpret_cast(ch));
+ let _unweaken = unweaken(ch);
+ f(po);
+
+ resource unweaken(ch: comm::chan<()>) unsafe {
+ rustrt::rust_task_unweaken(unsafe::reinterpret_cast(ch));
+ }
+}
+
+#[test]
+fn test_weaken_task_then_unweaken() unsafe {
+ task::try {||
+ weaken_task {|_po|
+ }
+ };
+}
+
+#[test]
+fn test_weaken_task_wait() unsafe {
+ let builder = task::builder();
+ task::unsupervise(builder);
+ task::run(builder) {||
+ weaken_task {|po|
+ comm::recv(po);
+ }
+ }
+}
+
+#[test]
+fn test_weaken_task_stress() unsafe {
+ // Create a bunch of weak tasks
+ iter::repeat(100u) {||
+ task::spawn {||
+ weaken_task {|_po|
+ }
+ }
+ let builder = task::builder();
+ task::unsupervise(builder);
+ task::run(builder) {||
+ weaken_task {|po|
+ // Wait for it to tell us to die
+ comm::recv(po);
+ }
+ }
+ }
+}
+
+#[test]
+#[ignore(cfg(target_os = "win32"))]
+fn test_weaken_task_fail() unsafe {
+ let res = task::try {||
+ weaken_task {|_po|
+ fail;
+ }
+ };
+ assert result::is_failure(res);
+}
\ No newline at end of file
Does not verify that the vector contains valid UTF-8.
"]
unsafe fn from_bytes(v: [const u8]) -> str unsafe {
- let mut vcopy: [u8] = v + [0u8];
+ let vcopy = v + [0u8];
let scopy: str = ::unsafe::reinterpret_cast(vcopy);
::unsafe::forget(vcopy);
ret scopy;
"]
#[inline]
fn is_whitespace() -> bool { is_whitespace(self) }
+ #[inline]
+ #[doc ="Returns the size in bytes not counting the null terminator"]
+ fn len() -> uint { len(self) }
#[doc = "
Returns a slice of the given string from the byte range [`begin`..`end`)
export sched_mode;
export sched_opts;
export task_opts;
-export task_builder::{};
+export builder::{};
export default_task_opts;
export get_opts;
// when you try to reuse the builder to spawn a new task. We'll just
// sidestep that whole issue by making builder's uncopyable and making
// the run function move them in.
-enum task_builder {
- task_builder_({
+enum builder {
+ builder_({
mut opts: task_opts,
mut gen_body: fn@(+fn~()) -> fn~(),
can_not_copy: option<comm::port<()>>
}
}
-fn task_builder() -> task_builder {
- #[doc = "Construct a task_builder"];
+fn builder() -> builder {
+ #[doc = "Construct a builder"];
let body_identity = fn@(+body: fn~()) -> fn~() { body };
- task_builder_({
+ builder_({
mut opts: default_task_opts(),
mut gen_body: body_identity,
can_not_copy: none
})
}
-fn get_opts(builder: task_builder) -> task_opts {
- #[doc = "Get the task_opts associated with a task_builder"];
+fn get_opts(builder: builder) -> task_opts {
+ #[doc = "Get the task_opts associated with a builder"];
builder.opts
}
-fn set_opts(builder: task_builder, opts: task_opts) {
+fn set_opts(builder: builder, opts: task_opts) {
#[doc = "
- Set the task_opts associated with a task_builder
+ Set the task_opts associated with a builder
To update a single option use a pattern like the following:
builder.opts = opts;
}
-fn add_wrapper(builder: task_builder, gen_body: fn@(+fn~()) -> fn~()) {
+fn add_wrapper(builder: builder, gen_body: fn@(+fn~()) -> fn~()) {
#[doc = "
Add a wrapper to the body of the spawned task.
};
}
-fn run(-builder: task_builder, +f: fn~()) {
+fn run(-builder: builder, +f: fn~()) {
#[doc = "
Creates and exucutes a new child task
/* Builder convenience functions */
-fn future_result(builder: task_builder) -> future::future<task_result> {
+fn future_result(builder: builder) -> future::future<task_result> {
#[doc = "
Get a future representing the exit status of the task.
}
}
-fn future_task(builder: task_builder) -> future::future<task> {
+fn future_task(builder: builder) -> future::future<task> {
#[doc = "Get a future representing the handle to the new task"];
let mut po = comm::port();
future::from_port(po)
}
-fn unsupervise(builder: task_builder) {
+fn unsupervise(builder: builder) {
#[doc = "Configures the new task to not propagate failure to its parent"];
set_opts(builder, {
});
}
-fn run_listener<A:send>(-builder: task_builder,
+fn run_listener<A:send>(-builder: builder,
+f: fn~(comm::port<A>)) -> comm::chan<A> {
#[doc = "
Runs a new task while providing a channel from the parent to the child
Sets up a new task with its own call stack and schedules it to run
the provided unique closure.
- This function is equivalent to `run(new_task_builder(), f)`.
+ This function is equivalent to `run(new_builder(), f)`.
"];
- run(task_builder(), f);
+ run(builder(), f);
}
fn spawn_listener<A:send>(+f: fn~(comm::port<A>)) -> comm::chan<A> {
};
// Likewise, the parent has both a 'po' and 'ch'
- This function is equivalent to `run_listener(new_task_builder(), f)`.
+ This function is equivalent to `run_listener(new_builder(), f)`.
"];
- run_listener(task_builder(), f)
+ run_listener(builder(), f)
}
fn spawn_sched(mode: sched_mode, +f: fn~()) {
greater than zero.
"];
- let mut builder = task_builder();
+ let mut builder = builder();
set_opts(builder, {
sched: some({
mode: mode,
let po = comm::port();
let ch = comm::chan(po);
- let mut builder = task_builder();
+ let mut builder = builder();
unsupervise(builder);
let result = future_result(builder);
run(builder) {||
}
};
- option::with_option_do(opts.notify_chan) {|c|
+ option::iter(opts.notify_chan) {|c|
// FIXME (1087): Would like to do notification in Rust
rustrt::rust_task_config_notify(new_task, c);
}
fn test_run_basic() {
let po = comm::port();
let ch = comm::chan(po);
- let builder = task_builder();
- run(builder) {||
+ let buildr = builder();
+ run(buildr) {||
comm::send(ch, ());
}
comm::recv(po);
fn test_add_wrapper() {
let po = comm::port();
let ch = comm::chan(po);
- let builder = task_builder();
- add_wrapper(builder) {|body|
+ let buildr = builder();
+ add_wrapper(buildr) {|body|
fn~() {
body();
comm::send(ch, ());
}
}
- run(builder) {||}
+ run(buildr) {||}
comm::recv(po);
}
#[test]
#[ignore(cfg(target_os = "win32"))]
fn test_future_result() {
- let builder = task_builder();
- let result = future_result(builder);
- run(builder) {||}
+ let buildr = builder();
+ let result = future_result(buildr);
+ run(buildr) {||}
assert future::get(result) == success;
- let builder = task_builder();
- let result = future_result(builder);
- unsupervise(builder);
- run(builder) {|| fail }
+ let buildr = builder();
+ let result = future_result(buildr);
+ unsupervise(buildr);
+ run(buildr) {|| fail }
assert future::get(result) == failure;
}
fn test_future_task() {
let po = comm::port();
let ch = comm::chan(po);
- let builder = task_builder();
- let task1 = future_task(builder);
- run(builder) {|| comm::send(ch, get_task()) }
+ let buildr = builder();
+ let task1 = future_task(buildr);
+ run(buildr) {|| comm::send(ch, get_task()) }
assert future::get(task1) == comm::recv(po);
}
#[test]
fn test_avoid_copying_the_body_run() {
avoid_copying_the_body {|f|
- let builder = task_builder();
- run(builder) {||
+ let buildr = builder();
+ run(buildr) {||
f();
}
}
#[test]
fn test_avoid_copying_the_body_run_listener() {
avoid_copying_the_body {|f|
- let builder = task_builder();
- run_listener(builder, fn~[move f](_po: comm::port<int>) {
+ let buildr = builder();
+ run_listener(buildr, fn~[move f](_po: comm::port<int>) {
f();
});
}
#[test]
fn test_avoid_copying_the_body_future_task() {
avoid_copying_the_body {|f|
- let builder = task_builder();
- future_task(builder);
- run(builder) {||
+ let buildr = builder();
+ future_task(buildr);
+ run(buildr) {||
f();
}
}
#[test]
fn test_avoid_copying_the_body_unsupervise() {
avoid_copying_the_body {|f|
- let builder = task_builder();
- unsupervise(builder);
- run(builder) {||
+ let buildr = builder();
+ unsupervise(buildr);
+ run(buildr) {||
f();
}
}
#[test]
fn test_osmain() {
- let builder = task_builder();
+ let buildr = builder();
let opts = {
sched: some({
mode: osmain,
native_stack_size: none
})
- with get_opts(builder)
+ with get_opts(buildr)
};
- set_opts(builder, opts);
+ set_opts(buildr, opts);
let po = comm::port();
let ch = comm::chan(po);
- run(builder) {||
+ run(buildr) {||
comm::send(ch, ());
}
comm::recv(po);
export swap;
export reverse;
export reversed;
-export iter, each, eachi;
+export iter, iter_between, each, eachi;
export iter2;
export iteri;
export riter;
expr_cast(@expr, @ty),
expr_if(@expr, blk, option<@expr>),
expr_while(@expr, blk),
- expr_for(@local, @expr, blk),
expr_do_while(blk, @expr),
/* Conditionless loop (can be exited with break, cont, ret, or fail)
Same semantics as while(true) { body }, but typestate knows that the
enum region_ {
re_inferred,
re_named(ident),
- re_self
+ re_self,
+ re_static
}
#[auto_serialize]
fn is_exported(i: ident, m: _mod) -> bool {
let mut local = false;
let mut parent_enum : option<ident> = none;
- for it: @item in m.items {
+ for m.items.each {|it|
if it.ident == i { local = true; }
alt it.node {
item_enum(variants, _) {
- for v: variant in variants {
+ for variants.each {|v|
if v.node.name == i {
local = true;
parent_enum = some(it.ident);
if local { break; }
}
let mut has_explicit_exports = false;
- for vi: @view_item in m.view_items {
+ for m.view_items.each {|vi|
alt vi.node {
view_item_export(vps) {
has_explicit_exports = true;
- for vp in vps {
+ for vps.each {|vp|
alt vp.node {
ast::view_path_simple(id, _, _) {
if id == i { ret true; }
ast::view_path_list(path, ids, _) {
if vec::len(*path) == 1u {
if i == path[0] { ret true; }
- for id in ids {
+ for ids.each {|id|
if id.node.name == i { ret true; }
}
} else {
fn split_class_items(cs: [@class_member]) -> ([ivar], [@method]) {
let mut vs = [], ms = [];
- for c in cs {
+ for cs.each {|c|
alt c.node {
instance_var(i, t, cm, id, privacy) {
vs += [{ident: i, ty: t, cm: cm, id: id, privacy: privacy}];
}
class_method(m) { ms += [m]; }
}
- }
+ };
(vs, ms)
}
export attr_meta;
export attr_metas;
+export find_linkage_attrs;
export find_linkage_metas;
export inline_attr;
export find_inline_attr;
// From a list of crate attributes get only the meta_items that impact crate
// linkage
fn find_linkage_metas(attrs: [ast::attribute]) -> [@ast::meta_item] {
- let mut metas: [@ast::meta_item] = [];
- for attr: ast::attribute in find_attrs_by_name(attrs, "link") {
+ find_linkage_attrs(attrs).flat_map {|attr|
+ alt check attr.node.value.node {
+ ast::meta_list(_, items) { items }
+ }
+ }
+}
+
+fn find_linkage_attrs(attrs: [ast::attribute]) -> [ast::attribute] {
+ let mut found = [];
+ for find_attrs_by_name(attrs, "link").each {|attr|
alt attr.node.value.node {
- ast::meta_list(_, items) { metas += items; }
+ ast::meta_list(_, _) { found += [attr] }
_ { #debug("ignoring link attribute that has incorrect type"); }
}
}
- ret metas;
+ ret found;
}
enum inline_attr {
// Get the meta_items from inside a vector of attributes
fn attr_metas(attrs: [ast::attribute]) -> [@ast::meta_item] {
let mut mitems = [];
- for a: ast::attribute in attrs { mitems += [attr_meta(a)]; }
+ for attrs.each {|a| mitems += [attr_meta(a)]; }
ret mitems;
}
fn contains(haystack: [@ast::meta_item], needle: @ast::meta_item) -> bool {
#debug("looking for %s",
print::pprust::meta_item_to_str(*needle));
- for item: @ast::meta_item in haystack {
+ for haystack.each {|item|
#debug("looking in %s",
print::pprust::meta_item_to_str(*item));
if eq(item, needle) { #debug("found it!"); ret true; }
// This is sort of stupid here, converting to a vec of mutables and back
let mut v: [mut @ast::meta_item] = [mut];
- for mi: @ast::meta_item in items { v += [mut mi]; }
+ for items.each {|mi| v += [mut mi]; }
std::sort::quick_sort(lteq, v);
let mut v2: [@ast::meta_item] = [];
- for mi: @ast::meta_item in v { v2 += [mi]; }
+ for v.each {|mi| v2 += [mi]; }
ret v2;
}
fn require_unique_names(diagnostic: span_handler,
metas: [@ast::meta_item]) {
let map = map::str_hash();
- for meta: @ast::meta_item in metas {
+ for metas.each {|meta|
let name = get_meta_item_name(meta);
if map.contains_key(name) {
diagnostic.span_fatal(meta.span,
}
fn get_filemap(cm: codemap, filename: str) -> filemap {
- for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
+ for cm.files.each {|fm| if fm.name == filename { ret fm; } }
//XXjdm the following triggers a mismatched type bug
// (or expected function, found _|_)
fail; // ("asking for " + filename + " which we don't know about");
elided = true;
}
// Print the offending lines
- for line: uint in display_lines {
+ for display_lines.each {|line|
io::stderr().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
let s = codemap::get_line(fm, line as int) + "\n";
io::stderr().write_str(s);
}
fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
- option::with_option_do (sp.expn_info) {|ei|
- let ss = option::with_option(ei.callie.span, "",
+ option::iter (sp.expn_info) {|ei|
+ let ss = option::map_default(ei.callie.span, "",
bind codemap::span_to_str(_, cm));
print_diagnostic(ss, note,
#fmt("in expansion of #%s", ei.callie.name));
fields: [{ident: ast::ident, ex: @ast::expr}]) ->
@ast::expr {
let mut astfields: [ast::field] = [];
- for field: {ident: ast::ident, ex: @ast::expr} in fields {
+ for fields.each {|field|
let ident = field.ident;
let val = field.ex;
let astfield =
}
};
let mut res: ast::ident = "";
- for e: @ast::expr in args {
+ for args.each {|e|
res += expr_to_ident(cx, e, "expected an ident");
}
fn make_rt_conv_expr(cx: ext_ctxt, sp: span, cnv: conv) -> @ast::expr {
fn make_flags(cx: ext_ctxt, sp: span, flags: [flag]) -> @ast::expr {
let mut flagexprs: [@ast::expr] = [];
- for f: flag in flags {
+ for flags.each {|f|
let mut fstr;
alt f {
flag_left_justify { fstr = "flag_left_justify"; }
option::none { }
_ { cx.span_unimpl(sp, unsupported); }
}
- for f: flag in cnv.flags {
+ for cnv.flags.each {|f|
alt f {
flag_left_justify { }
flag_sign_always {
some(p) { log(debug, "param: " + int::to_str(p, 10u)); }
_ { #debug("param: none"); }
}
- for f: flag in c.flags {
+ for c.flags.each {|f|
alt f {
flag_left_justify { #debug("flag: left justify"); }
flag_left_zero_pad { #debug("flag: left zero pad"); }
let mut n = 0u;
let mut tmp_expr = mk_str(cx, sp, "");
let nargs = vec::len::<@ast::expr>(args);
- for pc: piece in pieces {
+ for pieces.each {|pc|
alt pc {
piece_string(s) {
let s_expr = mk_str(cx, fmt_sp, s);
-> @ast::expr
{
let mut what = "expr";
- option::with_option_do(arg) {|arg|
+ option::iter(arg) {|arg|
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
-use std;
-
import codemap::span;
import std::map::{hashmap, str_hash};
{pre: [@expr], rep: option<@expr>, post: [@expr]} {
let mut idx: uint = 0u;
let mut res = none;
- for elt: @expr in elts {
+ for elts.each {|elt|
alt elt.node {
expr_mac(m) {
alt m.node {
fn option_flatten_map<T: copy, U: copy>(f: fn@(T) -> option<U>, v: [T]) ->
option<[U]> {
let mut res = [];
- for elem: T in v {
+ for v.each {|elem|
alt f(elem) { none { ret none; } some(fv) { res += [fv]; } }
}
ret some(res);
fn use_selectors_to_bind(b: binders, e: @expr) -> option<bindings> {
let res = str_hash::<arb_depth<matchable>>();
//need to do this first, to check vec lengths.
- for sel: selector in b.literal_ast_matchers {
+ for b.literal_ast_matchers.each {|sel|
alt sel(match_expr(e)) { none { ret none; } _ { } }
}
let mut never_mind: bool = false;
fn follow(m: arb_depth<matchable>, idx_path: @mut [uint]) ->
arb_depth<matchable> {
let mut res: arb_depth<matchable> = m;
- for idx: uint in *idx_path {
+ for vec::each(*idx_path) {|idx|
alt res {
leaf(_) { ret res;/* end of the line */ }
seq(new_ms, _) { res = new_ms[idx]; }
let mut macro_name: option<str> = none;
let mut clauses: [@clause] = [];
- for arg: @expr in args {
+ for args.each {|arg|
alt arg.node {
expr_vec(elts, mutbl) {
if vec::len(elts) != 2u {
fn generic_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
_body: ast::mac_body, clauses: [@clause]) -> @expr {
let arg = get_mac_arg(cx,sp,arg);
- for c: @clause in clauses {
+ for clauses.each {|c|
alt use_selectors_to_bind(c.params, arg) {
some(bindings) { ret transcribe(cx, bindings, c.body); }
none { cont; }
}
pat_rec(fields, etc) {
let mut fs = [];
- for f: ast::field_pat in fields {
+ for fields.each {|f|
fs += [{ident: f.ident, pat: fld.fold_pat(f.pat)}];
}
pat_rec(fs, etc)
expr_while(cond, body) {
expr_while(fld.fold_expr(cond), fld.fold_block(body))
}
- expr_for(decl, expr, blk) {
- expr_for(fld.fold_local(decl), fld.fold_expr(expr),
- fld.fold_block(blk))
- }
expr_do_while(blk, expr) {
expr_do_while(fld.fold_block(blk), fld.fold_expr(expr))
}
fn eval_crate_directives(cx: ctx, cdirs: [@ast::crate_directive], prefix: str,
&view_items: [@ast::view_item],
&items: [@ast::item]) {
- for sub_cdir: @ast::crate_directive in cdirs {
+ for cdirs.each {|sub_cdir|
eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
}
}
// interpreted as a specific kind of statement, which would be confusing.
fn bad_expr_word_table() -> hashmap<str, ()> {
let words = str_hash();
- for word in ["alt", "assert", "be", "break", "check", "claim",
- "class", "const", "cont", "copy", "crust", "do", "else",
- "enum", "export", "fail", "fn", "for", "if", "iface",
- "impl", "import", "let", "log", "loop", "mod", "mut",
- "mut", "native", "pure", "resource", "ret", "trait",
- "type", "unchecked", "unsafe", "while", "new"] {
+ let keys = ["alt", "assert", "be", "break", "check", "claim",
+ "class", "const", "cont", "copy", "crust", "do", "else",
+ "enum", "export", "fail", "fn", "for", "if", "iface",
+ "impl", "import", "let", "log", "loop", "mod", "mut",
+ "mut", "native", "pure", "resource", "ret", "trait",
+ "type", "unchecked", "unsafe", "while", "new"];
+ for keys.each {|word|
words.insert(word, ());
}
words
// otherwise, fail
fn ident_index(p: parser, args: [ast::arg], i: ast::ident) -> uint {
let mut j = 0u;
- for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
+ for args.each {|a| if a.ident == i { ret j; } j += 1u; }
p.fatal("unbound variable `" + i + "` in constraint arg");
}
p.bump(); p.bump();
if string == "self" {
ast::re_self
+ } else if string == "static" {
+ ast::re_static
} else {
ast::re_named(string)
}
let peeked = p.token;
if peeked == token::BINOP(token::OR) &&
p.restriction == RESTRICT_NO_BAR_OP { ret lhs; }
- for cur: op_spec in *p.precs {
+ for vec::each(*p.precs) {|cur|
if cur.prec > min_prec && cur.tok == peeked {
p.bump();
let expr = parse_prefix_expr(p);
fn parse_for_expr(p: parser) -> @ast::expr {
let lo = p.last_span;
- // FIXME remove this kludge after migration and snapshotting (#1619)
- let new_style = alt p.token {
- token::IDENT(_, false) { alt p.look_ahead(1u) {
- token::DOT | token::LPAREN { true }
- _ { false }
- } }
- token::IDENT(_, true) { true }
- _ { false }
- };
- if new_style {
- let call = parse_expr(p);
- alt call.node {
- ast::expr_call(f, args, true) {
- let b_arg = vec::last(args);
- let last = mk_expr(p, b_arg.span.lo, b_arg.span.hi,
- ast::expr_loop_body(b_arg));
- @{node: ast::expr_call(f, vec::init(args) + [last], true)
- with *call}
- }
- _ {
- p.span_fatal(lo, "`for` must be followed by a block call");
- }
- }
- } else {
- let decl = parse_local(p, false, false);
- expect_word(p, "in");
- let seq = parse_expr(p);
- let body = parse_block_no_value(p);
- mk_expr(p, lo.lo, body.span.hi, ast::expr_for(decl, seq, body))
+ let call = parse_expr_res(p, RESTRICT_STMT_EXPR);
+ alt call.node {
+ ast::expr_call(f, args, true) {
+ let b_arg = vec::last(args);
+ let last = mk_expr(p, b_arg.span.lo, b_arg.span.hi,
+ ast::expr_loop_body(b_arg));
+ @{node: ast::expr_call(f, vec::init(args) + [last], true)
+ with *call}
+ }
+ _ {
+ p.span_fatal(lo, "`for` must be followed by a block call");
+ }
}
}
ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
| ast::expr_alt(_, _, _) | ast::expr_block(_)
| ast::expr_do_while(_, _) | ast::expr_while(_, _)
- | ast::expr_loop(_) | ast::expr_for(_, _, _)
- | ast::expr_call(_, _, true) {
+ | ast::expr_loop(_) | ast::expr_call(_, _, true) {
false
}
_ { true }
let arg_tys = parse_seq(token::LPAREN, token::RPAREN,
seq_sep(token::COMMA),
{|p| parse_ty(p, false)}, p);
- for ty in arg_tys.node {
+ for arg_tys.node.each {|ty|
args += [{ty: ty, id: p.get_id()}];
}
} else if eat(p, token::EQ) {
fn commasep<IN>(s: ps, b: breaks, elts: [IN], op: fn(ps, IN)) {
box(s, 0u, b);
let mut first = true;
- for elt: IN in elts {
+ for elts.each {|elt|
if first { first = false; } else { word_space(s, ","); }
op(s, elt);
}
box(s, 0u, b);
let len = vec::len::<IN>(elts);
let mut i = 0u;
- for elt: IN in elts {
+ for elts.each {|elt|
maybe_print_comment(s, get_span(elt).hi);
op(s, elt);
i += 1u;
fn print_mod(s: ps, _mod: ast::_mod, attrs: [ast::attribute]) {
print_inner_attributes(s, attrs);
- for vitem: @ast::view_item in _mod.view_items {
+ for _mod.view_items.each {|vitem|
print_view_item(s, vitem);
}
- for item: @ast::item in _mod.items { print_item(s, item); }
+ for _mod.items.each {|item| print_item(s, item); }
}
fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) {
print_inner_attributes(s, attrs);
- for vitem: @ast::view_item in nmod.view_items {
+ for nmod.view_items.each {|vitem|
print_view_item(s, vitem);
}
- for item: @ast::native_item in nmod.items { print_native_item(s, item); }
+ for nmod.items.each {|item| print_native_item(s, item); }
}
fn print_region(s: ps, region: ast::region) {
ast::re_inferred { /* no-op */ }
ast::re_named(name) { word(s.s, name); word(s.s, "."); }
ast::re_self { word(s.s, "self"); word(s.s, "."); }
+ ast::re_static { word(s.s, "static"); word(s.s, "."); }
}
}
end(s);
} else {
bopen(s);
- for v: ast::variant in variants {
+ for variants.each {|v|
space_if_not_bol(s);
maybe_print_comment(s, v.span.lo);
print_outer_attributes(s, v.node.attrs);
print_fn_args_and_ret(s, ctor.node.dec);
space(s.s);
print_block(s, ctor.node.body);
- for ci in items {
+ for items.each {|ci|
/*
FIXME: collect all private items and print them
in a single "priv" section
print_type(s, ty);
space(s.s);
bopen(s);
- for meth in methods {
+ for methods.each {|meth|
print_method(s, meth);
}
bclose(s, item.span);
print_type_params(s, tps);
word(s.s, " ");
bopen(s);
- for meth in methods { print_ty_method(s, meth); }
+ for methods.each {|meth| print_ty_method(s, meth); }
bclose(s, item.span);
}
ast::item_res(decl, tps, body, dt_id, ct_id) {
fn print_outer_attributes(s: ps, attrs: [ast::attribute]) {
let mut count = 0;
- for attr: ast::attribute in attrs {
+ for attrs.each {|attr|
alt attr.node.style {
ast::attr_outer { print_attribute(s, attr); count += 1; }
_ {/* fallthrough */ }
fn print_inner_attributes(s: ps, attrs: [ast::attribute]) {
let mut count = 0;
- for attr: ast::attribute in attrs {
+ for attrs.each {|attr|
alt attr.node.style {
ast::attr_inner {
print_attribute(s, attr);
print_inner_attributes(s, attrs);
- for vi in blk.node.view_items { print_view_item(s, vi); }
- for st: @ast::stmt in blk.node.stmts {
+ for blk.node.view_items.each {|vi| print_view_item(s, vi); }
+ for blk.node.stmts.each {|st|
print_stmt(s, *st);
}
alt blk.node.expr {
some(@{node: ast::expr_vec(_, _), _}) { }
_ { word(s.s, " "); }
}
- option::with_option_do(arg, bind print_expr(s, _));
+ option::iter(arg, bind print_expr(s, _));
// FIXME: extension 'body'
}
ast::mac_embed_type(ty) {
space(s.s);
print_block(s, blk);
}
- ast::expr_for(decl, expr, blk) {
- head(s, "for");
- print_for_decl(s, decl, expr);
- space(s.s);
- print_block(s, blk);
- }
ast::expr_do_while(blk, expr) {
head(s, "do");
space(s.s);
print_maybe_parens_discrim(s, expr);
space(s.s);
bopen(s);
- for arm: ast::arm in arms {
+ for arms.each {|arm|
space(s.s);
cbox(s, alt_indent_unit);
ibox(s, 0u);
let mut first = true;
- for p: @ast::pat in arm.pats {
+ for arm.pats.each {|p|
if first {
first = false;
} else { space(s.s); word_space(s, "|"); }
maybe_print_comment(s, path.span.lo);
if path.node.global { word(s.s, "::"); }
let mut first = true;
- for id: ast::ident in path.node.idents {
+ for path.node.idents.each {|id|
if first { first = false; } else { word(s.s, "::"); }
word(s.s, id);
}
fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
if vec::len(*bounds) > 0u {
word(s.s, ":");
- for bound in *bounds {
+ for vec::each(*bounds) {|bound|
nbsp(s);
alt bound {
ast::bound_copy { word(s.s, "copy"); }
fn print_simple_path(s: ps, path: ast::simple_path) {
let mut first = true;
- for id in path {
+ for path.each {|id|
if first { first = false; } else { word(s.s, "::"); }
word(s.s, id);
}
// FIXME: The fact that this builds up the table anew for every call is
// not good. Eventually, table should be a const.
fn operator_prec(op: ast::binop) -> int {
- for spec: parse::parser::op_spec in *parse::parser::prec_table() {
+ for vec::each(*parse::parser::prec_table()) {|spec|
if spec.op == op { ret spec.prec; }
}
core::unreachable();
}
lexer::isolated {
pprust::hardbreak_if_not_bol(s);
- for line: str in cmnt.lines {
+ for cmnt.lines.each {|line|
// Don't print empty lines because they will end up as trailing
// whitespace
if str::is_not_empty(line) { word(s.s, line); }
hardbreak(s.s);
} else {
ibox(s, 0u);
- for line: str in cmnt.lines {
+ for cmnt.lines.each {|line|
if str::is_not_empty(line) { word(s.s, line); }
hardbreak(s.s);
}
str {
let mut comma = false;
let mut s = "(";
- for a: @ast::sp_constr_arg<T> in args {
+ for args.each {|a|
if comma { s += ", "; } else { comma = true; }
s += constr_arg_to_str::<T>(f, a.node);
}
fn constrs_str<T>(constrs: [T], elt: fn(T) -> str) -> str {
let mut s = "", colon = true;
- for c in constrs {
+ for constrs.each {|c|
if colon { s += " : "; colon = false; } else { s += ", "; }
s += elt(c);
}
#[crate_type = "lib"];
-use std;
+#[no_core];
+
+use core(vers = "0.2");
+use std(vers = "0.2");
+
+import core::*;
mod attr;
mod diagnostic;
alt cd.node {
cdir_src_mod(_, _) { }
cdir_dir_mod(_, cdirs, _) {
- for cdir: @crate_directive in cdirs {
+ for cdirs.each {|cdir|
visit_crate_directive(cdir, e, v);
}
}
}
fn visit_mod<E>(m: _mod, _sp: span, _id: node_id, e: E, v: vt<E>) {
- for vi: @view_item in m.view_items { v.visit_view_item(vi, e, v); }
- for i: @item in m.items { v.visit_item(i, e, v); }
+ for m.view_items.each {|vi| v.visit_view_item(vi, e, v); }
+ for m.items.each {|i| v.visit_item(i, e, v); }
}
fn visit_view_item<E>(_vi: @view_item, _e: E, _v: vt<E>) { }
}
item_mod(m) { v.visit_mod(m, i.span, i.id, e, v); }
item_native_mod(nm) {
- for vi: @view_item in nm.view_items { v.visit_view_item(vi, e, v); }
- for ni: @native_item in nm.items { v.visit_native_item(ni, e, v); }
+ for nm.view_items.each {|vi| v.visit_view_item(vi, e, v); }
+ for nm.items.each {|ni| v.visit_native_item(ni, e, v); }
}
item_ty(t, tps) { v.visit_ty(t, e, v); v.visit_ty_params(tps, e, v); }
item_res(decl, tps, body, dtor_id, _) {
}
item_enum(variants, tps) {
v.visit_ty_params(tps, e, v);
- for vr: variant in variants {
- for va: variant_arg in vr.node.args { v.visit_ty(va.ty, e, v); }
+ for variants.each {|vr|
+ for vr.node.args.each {|va| v.visit_ty(va.ty, e, v); }
}
}
item_impl(tps, ifce, ty, methods) {
v.visit_ty_params(tps, e, v);
alt ifce { some(ty) { v.visit_ty(ty, e, v); } none {} }
v.visit_ty(ty, e, v);
- for m in methods {
+ for methods.each {|m|
visit_method_helper(m, e, v)
}
}
item_class(tps, members, ctor) {
v.visit_ty_params(tps, e, v);
- for m in members {
+ for members.each {|m|
v.visit_class_item(m, e, v);
}
// make up a fake fn so as to call visit_fn on the ctor
}
item_iface(tps, methods) {
v.visit_ty_params(tps, e, v);
- for m in methods {
- for a in m.decl.inputs { v.visit_ty(a.ty, e, v); }
+ for methods.each {|m|
+ for m.decl.inputs.each {|a| v.visit_ty(a.ty, e, v); }
v.visit_ty(m.decl.output, e, v);
}
}
ty_ptr(mt) { v.visit_ty(mt.ty, e, v); }
ty_rptr(_, mt) { v.visit_ty(mt.ty, e, v); }
ty_rec(flds) {
- for f: ty_field in flds { v.visit_ty(f.node.mt.ty, e, v); }
+ for flds.each {|f| v.visit_ty(f.node.mt.ty, e, v); }
}
- ty_tup(ts) { for tt in ts { v.visit_ty(tt, e, v); } }
+ ty_tup(ts) { for ts.each {|tt| v.visit_ty(tt, e, v); } }
ty_fn(_, decl) {
- for a in decl.inputs { v.visit_ty(a.ty, e, v); }
- for c: @constr in decl.constraints {
+ for decl.inputs.each {|a| v.visit_ty(a.ty, e, v); }
+ for decl.constraints.each {|c|
v.visit_constr(c.node.path, c.span, c.node.id, e, v);
}
v.visit_ty(decl.output, e, v);
ty_path(p, _) { visit_path(p, e, v); }
ty_constr(t, cs) {
v.visit_ty(t, e, v);
- for tc: @spanned<constr_general_<@path, node_id>> in cs {
+ for cs.each {|tc|
v.visit_constr(tc.node.path, tc.span, tc.node.id, e, v);
}
}
}
fn visit_path<E>(p: @path, e: E, v: vt<E>) {
- for tp: @ty in p.node.types { v.visit_ty(tp, e, v); }
+ for p.node.types.each {|tp| v.visit_ty(tp, e, v); }
}
fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
alt p.node {
pat_enum(path, children) {
visit_path(path, e, v);
- for child: @pat in children { v.visit_pat(child, e, v); }
+ for children.each {|child| v.visit_pat(child, e, v); }
}
pat_rec(fields, _) {
- for f: field_pat in fields { v.visit_pat(f.pat, e, v); }
+ for fields.each {|f| v.visit_pat(f.pat, e, v); }
}
- pat_tup(elts) { for elt in elts { v.visit_pat(elt, e, v); } }
+ pat_tup(elts) { for elts.each {|elt| v.visit_pat(elt, e, v); } }
pat_box(inner) | pat_uniq(inner) {
v.visit_pat(inner, e, v);
}
pat_ident(path, inner) {
visit_path(path, e, v);
- option::with_option_do(inner, {|subpat| v.visit_pat(subpat, e, v)});
+ option::iter(inner, {|subpat| v.visit_pat(subpat, e, v)});
}
pat_lit(ex) { v.visit_expr(ex, e, v); }
pat_range(e1, e2) { v.visit_expr(e1, e, v); v.visit_expr(e2, e, v); }
}
fn visit_ty_params<E>(tps: [ty_param], e: E, v: vt<E>) {
- for tp in tps {
- for bound in *tp.bounds {
+ for tps.each {|tp|
+ for vec::each(*tp.bounds) {|bound|
alt bound {
bound_iface(t) { v.visit_ty(t, e, v); }
bound_copy | bound_send { }
}
fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
- for a: arg in fd.inputs { v.visit_ty(a.ty, e, v); }
- for c: @constr in fd.constraints {
+ for fd.inputs.each {|a| v.visit_ty(a.ty, e, v); }
+ for fd.constraints.each {|c|
v.visit_constr(c.node.path, c.span, c.node.id, e, v);
}
v.visit_ty(fd.output, e, v);
}
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
- for vi in b.node.view_items { v.visit_view_item(vi, e, v); }
- for s in b.node.stmts { v.visit_stmt(s, e, v); }
+ for b.node.view_items.each {|vi| v.visit_view_item(vi, e, v); }
+ for b.node.stmts.each {|s| v.visit_stmt(s, e, v); }
visit_expr_opt(b.node.expr, e, v);
}
fn visit_decl<E>(d: @decl, e: E, v: vt<E>) {
alt d.node {
decl_local(locs) {
- for loc in locs { v.visit_local(loc, e, v); }
+ for locs.each {|loc| v.visit_local(loc, e, v); }
}
decl_item(it) { v.visit_item(it, e, v); }
}
}
fn visit_exprs<E>(exprs: [@expr], e: E, v: vt<E>) {
- for ex: @expr in exprs { v.visit_expr(ex, e, v); }
+ for exprs.each {|ex| v.visit_expr(ex, e, v); }
}
fn visit_mac<E>(m: mac, e: E, v: vt<E>) {
}
expr_vec(es, _) { visit_exprs(es, e, v); }
expr_rec(flds, base) {
- for f: field in flds { v.visit_expr(f.node.expr, e, v); }
+ for flds.each {|f| v.visit_expr(f.node.expr, e, v); }
visit_expr_opt(base, e, v);
}
- expr_tup(elts) { for el in elts { v.visit_expr(el, e, v); } }
+ expr_tup(elts) { for elts.each {|el| v.visit_expr(el, e, v); } }
expr_call(callee, args, _) {
visit_exprs(args, e, v);
v.visit_expr(callee, e, v);
}
expr_bind(callee, args) {
v.visit_expr(callee, e, v);
- for eo: option<@expr> in args { visit_expr_opt(eo, e, v); }
+ for args.each {|eo| visit_expr_opt(eo, e, v); }
}
expr_binary(_, a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
expr_addr_of(_, x) | expr_unary(_, x) | expr_loop_body(x) |
}
expr_while(x, b) { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
expr_loop(b) { v.visit_block(b, e, v); }
- expr_for(dcl, x, b) {
- v.visit_local(dcl, e, v);
- v.visit_expr(x, e, v);
- v.visit_block(b, e, v);
- }
expr_do_while(b, x) { v.visit_block(b, e, v); v.visit_expr(x, e, v); }
expr_alt(x, arms, _) {
v.visit_expr(x, e, v);
- for a: arm in arms { v.visit_arm(a, e, v); }
+ for arms.each {|a| v.visit_arm(a, e, v); }
}
expr_fn(proto, decl, body, _) {
v.visit_fn(fk_anon(proto), decl, body, ex.span, ex.id, e, v);
}
expr_field(x, _, tys) {
v.visit_expr(x, e, v);
- for tp in tys { v.visit_ty(tp, e, v); }
+ for tys.each {|tp| v.visit_ty(tp, e, v); }
}
expr_index(a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
expr_path(p) { visit_path(p, e, v); }
}
fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
- for p: @pat in a.pats { v.visit_pat(p, e, v); }
+ for a.pats.each {|p| v.visit_pat(p, e, v); }
visit_expr_opt(a.guard, e, v);
v.visit_block(a.body, e, v);
}
impl <V: copy> of map::map<uint, V> for smallintmap<V> {
fn size() -> uint {
let mut sz = 0u;
- for item in self.v {
+ for vec::each(self.v) {|item|
alt item { some(_) { sz += 1u; } _ {} }
}
sz
fn find(&&key: uint) -> option<V> { find(self, key) }
fn rehash() { fail }
fn items(it: fn(&&uint, V)) {
- let mut idx = 0u;
- for item in self.v {
- alt item {
+ let mut idx = 0u, l = self.v.len();
+ while idx < l {
+ alt self.v[idx] {
some(elt) {
- it(idx, elt);
+ it(idx, copy elt);
}
none { }
}
}
}
fn keys(it: fn(&&uint)) {
- let mut idx = 0u;
- for item in self.v {
- if item != none { it(idx); }
+ let mut idx = 0u, l = self.v.len();
+ while idx < l {
+ if self.v[idx] != none { it(idx); }
idx += 1u;
}
}
fn values(it: fn(V)) {
- for item in self.v {
- alt item { some(elt) { it(elt); } _ {} }
- }
+ self.items({|_i, v| it(v)});
}
}
#[crate_type = "lib"];
#[doc = "The Rust standard library"];
+#[no_core];
+
+use core(vers = "0.2");
+import core::*;
+
export net, uv;
export c_vec, four, tri, util;
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
export ebml, dbg, getopts, json, rand, sha1, term, time, prettyprint;
export test, tempfile, serialization;
-
// General io and system-services modules
mod net;
+
+// libuv modules
mod uv;
+mod uv_ll;
+mod uv_hl;
// Utility modules
task::spawn {||
let testfn = test.fn;
- let mut builder = task::task_builder();
+ let mut builder = task::builder();
let result_future = task::future_result(builder);
task::unsupervise(builder);
task::run(builder, testfn);
// FIXME: The i64 values can be passed by-val when #2064 is fixed.
fn rust_gmtime(&&sec: i64, &&nsec: i32, &&result: tm);
- fn rust_localtime(&&sec: i64, &&nsec: i32, &result: tm);
+ fn rust_localtime(&&sec: i64, &&nsec: i32, &&result: tm);
fn rust_timegm(&&tm: tm, &sec: i64);
fn rust_mktime(&&tm: tm, &sec: i64);
}
+#[doc = "
+Rust bindings to libuv
+
+This is the base-module for various levels of bindings to
+the libuv library.
+
+These modules are seeing heavy work, currently, and the final
+API layout should not be inferred from its current form.
+
+This base module currently contains a historical, rust-based
+implementation of a few libuv operations that hews closely to
+the patterns of the libuv C-API. It was used, mostly, to explore
+some implementation details and will most likely be deprecated
+in the near future.
+
+The `ll` module contains low-level mappings for working directly
+with the libuv C-API.
+
+The `hl` module contains a set of tools library developers can
+use for interacting with an active libuv loop. This modules's
+API is meant to be used to write high-level,
+rust-idiomatic abstractions for utilizes libuv's asynchronous IO
+facilities.
+"];
+
import map::hashmap;
export loop_new, loop_delete, run, close, run_in_bg;
export async_init, async_send;
export timer_init, timer_start, timer_stop;
+import ll = uv_ll;
+export ll;
+
+import hl = uv_hl;
+export hl;
+
+#[nolink]
+native mod rustrt {
+ fn rust_uv_loop_new() -> *libc::c_void;
+ fn rust_uv_loop_delete(lp: *libc::c_void);
+ fn rust_uv_loop_set_data(
+ lp: *libc::c_void,
+ data: *uv_loop_data);
+ fn rust_uv_bind_op_cb(lp: *libc::c_void, cb: *u8)
+ -> *libc::c_void;
+ fn rust_uv_stop_op_cb(handle: *libc::c_void);
+ fn rust_uv_run(loop_handle: *libc::c_void);
+ fn rust_uv_hilvl_close(handle: *libc::c_void, cb: *u8);
+ fn rust_uv_hilvl_close_async(handle: *libc::c_void);
+ fn rust_uv_hilvl_close_timer(handle: *libc::c_void);
+ fn rust_uv_async_send(handle: *ll::uv_async_t);
+ fn rust_uv_hilvl_async_init(
+ loop_handle: *libc::c_void,
+ cb: *u8,
+ id: *u8) -> *libc::c_void;
+ fn rust_uv_timer_init(
+ loop_handle: *libc::c_void,
+ cb: *u8,
+ id: *u8) -> *libc::c_void;
+ fn rust_uv_timer_start(
+ timer_handle: *libc::c_void,
+ timeout: libc::c_uint,
+ repeat: libc::c_uint);
+ fn rust_uv_timer_stop(handle: *libc::c_void);
+ fn rust_uv_free(ptr: *libc::c_void);
+ // sizeof testing helpers
+ fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
+ fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint;
+ fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint;
+ fn rust_uv_helper_uv_write_t_size() -> libc::c_uint;
+ fn rust_uv_helper_uv_err_t_size() -> libc::c_uint;
+ fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint;
+ fn rust_uv_helper_uv_async_t_size() -> libc::c_uint;
+}
+
+
// these are processed solely in the
// process_operation() crust fn below
enum uv_operation {
enum uv_handle {
uv_async([u8], uv_loop),
- uv_timer([u8], uv_loop)
+ uv_timer([u8], uv_loop),
}
enum uv_msg {
uv_loop_new(comm::chan<uv_msg>, *libc::c_void)
}
-#[nolink]
-native mod rustrt {
- fn rust_uv_loop_new() -> *libc::c_void;
- fn rust_uv_loop_delete(lp: *libc::c_void);
- fn rust_uv_loop_set_data(
- lp: *libc::c_void,
- data: *uv_loop_data);
- fn rust_uv_bind_op_cb(lp: *libc::c_void, cb: *u8)
- -> *libc::c_void;
- fn rust_uv_stop_op_cb(handle: *libc::c_void);
- fn rust_uv_run(loop_handle: *libc::c_void);
- fn rust_uv_close(handle: *libc::c_void, cb: *u8);
- fn rust_uv_close_async(handle: *libc::c_void);
- fn rust_uv_close_timer(handle: *libc::c_void);
- fn rust_uv_async_send(handle: *libc::c_void);
- fn rust_uv_async_init(
- loop_handle: *libc::c_void,
- cb: *u8,
- id: *u8) -> *libc::c_void;
- fn rust_uv_timer_init(
- loop_handle: *libc::c_void,
- cb: *u8,
- id: *u8) -> *libc::c_void;
- fn rust_uv_timer_start(
- timer_handle: *libc::c_void,
- timeout: libc::c_uint,
- repeat: libc::c_uint);
- fn rust_uv_timer_stop(handle: *libc::c_void);
-}
-
// public functions
fn loop_new() -> uv_loop unsafe {
let ret_recv_port: comm::port<uv_loop> =
do_send(op_handle);
}
fn do_send(h: *libc::c_void) {
- rustrt::rust_uv_async_send(h);
+ rustrt::rust_uv_async_send(h as *ll::uv_async_t);
}
fn gen_handle_id() -> [u8] {
ret rand::rng().gen_bytes(16u);
alt comm::recv(op_port) {
op_async_init(id) {
let id_ptr = vec::unsafe::to_ptr(id);
- let async_handle = rustrt::rust_uv_async_init(
+ let async_handle = rustrt::rust_uv_hilvl_async_init(
lp,
process_async_send,
id_ptr);
alt handle {
uv_async(id, lp) {
let cb = process_close_async;
- rustrt::rust_uv_close(
+ rustrt::rust_uv_hilvl_close(
handle_ptr, cb);
}
uv_timer(id, lp) {
let cb = process_close_timer;
- rustrt::rust_uv_close(
+ rustrt::rust_uv_hilvl_close(
handle_ptr, cb);
}
_ {
data: *uv_loop_data)
unsafe {
let id = get_handle_id_from(id_buf);
- rustrt::rust_uv_close_async(handle_ptr);
+ rustrt::rust_uv_hilvl_close_async(handle_ptr);
// at this point, the handle and its data has been
// released. notify the rust loop to remove the
// handle and its data and call the user-supplied
data: *uv_loop_data)
unsafe {
let id = get_handle_id_from(id_buf);
- rustrt::rust_uv_close_timer(handle_ptr);
+ rustrt::rust_uv_hilvl_close_timer(handle_ptr);
process_close_common(id, data);
}
assert comm::recv(exit_port);
uv::loop_delete(test_loop);
}
+
+enum tcp_read_data {
+ tcp_read_eof,
+ tcp_read_more([u8]),
+ tcp_read_error
+}
+
+type request_wrapper = {
+ write_req: *ll::uv_write_t,
+ req_buf: *[ll::uv_buf_t],
+ read_chan: *comm::chan<str>
+};
+
+crust fn after_close_cb(handle: *libc::c_void) {
+ log(debug, #fmt("after uv_close! handle ptr: %?",
+ handle));
+}
+
+crust fn on_alloc_cb(handle: *libc::c_void,
+ ++suggested_size: libc::size_t)
+ -> ll::uv_buf_t unsafe {
+ log(debug, "on_alloc_cb!");
+ let char_ptr = ll::malloc_buf_base_of(suggested_size);
+ log(debug, #fmt("on_alloc_cb h: %? char_ptr: %u sugsize: %u",
+ handle,
+ char_ptr as uint,
+ suggested_size as uint));
+ ret ll::buf_init(char_ptr, suggested_size);
+}
+
+crust fn on_read_cb(stream: *ll::uv_stream_t,
+ nread: libc::ssize_t,
+ ++buf: ll::uv_buf_t) unsafe {
+ log(debug, #fmt("CLIENT entering on_read_cb nred: %d", nread));
+ if (nread > 0) {
+ // we have data
+ log(debug, #fmt("CLIENT read: data! nread: %d", nread));
+ ll::read_stop(stream);
+ let client_data = ll::
+ get_data_for_uv_handle(stream as *libc::c_void)
+ as *request_wrapper;
+ let buf_base = ll::get_base_from_buf(buf);
+ let buf_len = ll::get_len_from_buf(buf);
+ let bytes = vec::unsafe::from_buf(buf_base, buf_len);
+ let read_chan = *((*client_data).read_chan);
+ let msg_from_server = str::from_bytes(bytes);
+ comm::send(read_chan, msg_from_server);
+ ll::close(stream as *libc::c_void, after_close_cb)
+ }
+ else if (nread == -1) {
+ // err .. possibly EOF
+ log(debug, "read: eof!");
+ }
+ else {
+ // nread == 0 .. do nothing, just free buf as below
+ log(debug, "read: do nothing!");
+ }
+ // when we're done
+ ll::free_base_of_buf(buf);
+ log(debug, "CLIENT exiting on_read_cb");
+}
+
+crust fn on_write_complete_cb(write_req: *ll::uv_write_t,
+ status: libc::c_int) unsafe {
+ log(debug, #fmt("CLIENT beginning on_write_complete_cb status: %d",
+ status as int));
+ let stream = ll::get_stream_handle_from_write_req(write_req);
+ log(debug, #fmt("CLIENT on_write_complete_cb: tcp:%d write_handle:%d",
+ stream as int, write_req as int));
+ let result = ll::read_start(stream, on_alloc_cb, on_read_cb);
+ log(debug, #fmt("CLIENT ending on_write_complete_cb .. status: %d",
+ result as int));
+}
+
+crust fn on_connect_cb(connect_req_ptr: *ll::uv_connect_t,
+ status: libc::c_int) unsafe {
+ log(debug, #fmt("beginning on_connect_cb .. status: %d",
+ status as int));
+ let stream =
+ ll::get_stream_handle_from_connect_req(connect_req_ptr);
+ if (status == 0i32) {
+ log(debug, "on_connect_cb: in status=0 if..");
+ let client_data = ll::get_data_for_req(
+ connect_req_ptr as *libc::c_void)
+ as *request_wrapper;
+ let write_handle = (*client_data).write_req as *libc::c_void;
+ log(debug, #fmt("on_connect_cb: tcp stream: %d write_handle addr %d",
+ stream as int, write_handle as int));
+ let write_result = ll::write(write_handle,
+ stream as *libc::c_void,
+ (*client_data).req_buf,
+ on_write_complete_cb);
+ log(debug, #fmt("on_connect_cb: ll::write() status: %d",
+ write_result as int));
+ }
+ else {
+ let test_loop = ll::get_loop_for_uv_handle(
+ stream as *libc::c_void);
+ let err_msg = ll::get_last_err_info(test_loop);
+ log(debug, err_msg);
+ assert false;
+ }
+ log(debug, "finishing on_connect_cb");
+}
+
+fn impl_uv_tcp_request(ip: str, port: int, req_str: str,
+ client_chan: *comm::chan<str>) unsafe {
+ let test_loop = ll::loop_new();
+ let tcp_handle = ll::tcp_t();
+ let tcp_handle_ptr = ptr::addr_of(tcp_handle);
+ let connect_handle = ll::connect_t();
+ let connect_req_ptr = ptr::addr_of(connect_handle);
+
+ // this is the persistent payload of data that we
+ // need to pass around to get this example to work.
+ // In C, this would be a malloc'd or stack-allocated
+ // struct that we'd cast to a void* and store as the
+ // data field in our uv_connect_t struct
+ let req_str_bytes = str::bytes(req_str);
+ let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str_bytes);
+ log(debug, #fmt("req_msg ptr: %u", req_msg_ptr as uint));
+ let req_msg = [
+ ll::buf_init(req_msg_ptr, vec::len(req_str_bytes))
+ ];
+ // this is the enclosing record, we'll pass a ptr to
+ // this to C..
+ let write_handle = ll::write_t();
+ let write_handle_ptr = ptr::addr_of(write_handle);
+ log(debug, #fmt("tcp req: tcp stream: %d write_handle: %d",
+ tcp_handle_ptr as int,
+ write_handle_ptr as int));
+ let client_data = { writer_handle: write_handle_ptr,
+ req_buf: ptr::addr_of(req_msg),
+ read_chan: client_chan };
+
+ let tcp_init_result = ll::tcp_init(
+ test_loop as *libc::c_void, tcp_handle_ptr);
+ if (tcp_init_result == 0i32) {
+ log(debug, "sucessful tcp_init_result");
+
+ log(debug, "building addr...");
+ let addr = ll::ip4_addr(ip, port);
+ // FIXME ref #2064
+ let addr_ptr = ptr::addr_of(addr);
+ log(debug, #fmt("after build addr in rust. port: %u",
+ addr.sin_port as uint));
+
+ // this should set up the connection request..
+ log(debug, #fmt("before calling tcp_connect .. connect cb ptr: %u ",
+ on_connect_cb as uint));
+ let tcp_connect_result = ll::tcp_connect(
+ connect_req_ptr, tcp_handle_ptr,
+ addr_ptr, on_connect_cb);
+ if (tcp_connect_result == 0i32) {
+ // not set the data on the connect_req
+ // until its initialized
+ ll::set_data_for_req(
+ connect_req_ptr as *libc::c_void,
+ ptr::addr_of(client_data) as *libc::c_void);
+ ll::set_data_for_uv_handle(
+ tcp_handle_ptr as *libc::c_void,
+ ptr::addr_of(client_data) as *libc::c_void);
+ log(debug, "before run tcp req loop");
+ ll::run(test_loop);
+ log(debug, "after run tcp req loop");
+ }
+ else {
+ log(debug, "ll::tcp_connect() failure");
+ assert false;
+ }
+ }
+ else {
+ log(debug, "ll::tcp_init() failure");
+ assert false;
+ }
+ ll::loop_delete(test_loop);
+
+}
+
+crust fn server_after_close_cb(handle: *libc::c_void) unsafe {
+ log(debug, #fmt("SERVER server stream closed, should exit.. h: %?",
+ handle));
+}
+
+crust fn client_stream_after_close_cb(handle: *libc::c_void)
+ unsafe {
+ log(debug, "SERVER: closed client stream, now closing server stream");
+ let client_data = ll::get_data_for_uv_handle(
+ handle) as
+ *tcp_server_data;
+ ll::close((*client_data).server as *libc::c_void,
+ server_after_close_cb);
+}
+
+crust fn after_server_resp_write(req: *ll::uv_write_t) unsafe {
+ let client_stream_ptr =
+ ll::get_stream_handle_from_write_req(req);
+ log(debug, "SERVER: resp sent... closing client stream");
+ ll::close(client_stream_ptr as *libc::c_void,
+ client_stream_after_close_cb)
+}
+
+crust fn on_server_read_cb(client_stream_ptr: *ll::uv_stream_t,
+ nread: libc::ssize_t,
+ ++buf: ll::uv_buf_t) unsafe {
+ if (nread > 0) {
+ // we have data
+ log(debug, #fmt("SERVER read: data! nread: %d", nread));
+
+ // pull out the contents of the write from the client
+ let buf_base = ll::get_base_from_buf(buf);
+ let buf_len = ll::get_len_from_buf(buf);
+ log(debug, #fmt("SERVER buf base: %u, len: %u, nread: %d",
+ buf_base as uint,
+ buf_len as uint,
+ nread));
+ let bytes = vec::unsafe::from_buf(buf_base, buf_len);
+ let request_str = str::from_bytes(bytes);
+
+ let client_data = ll::get_data_for_uv_handle(
+ client_stream_ptr as *libc::c_void) as *tcp_server_data;
+
+ let server_kill_msg = (*client_data).server_kill_msg;
+ let write_req = (*client_data).server_write_req;
+ if (str::contains(request_str, server_kill_msg)) {
+ log(debug, "SERVER: client request contains server_kill_msg!");
+ log(debug, "SERVER: sending response to client");
+ ll::read_stop(client_stream_ptr);
+ let server_chan = *((*client_data).server_chan);
+ comm::send(server_chan, request_str);
+ let write_result = ll::write(
+ write_req as *libc::c_void,
+ client_stream_ptr as *libc::c_void,
+ (*client_data).server_resp_buf,
+ after_server_resp_write);
+ log(debug, #fmt("SERVER: resp write result: %d",
+ write_result as int));
+ if (write_result != 0i32) {
+ log(debug, "bad result for server resp ll::write()");
+ log(debug, ll::get_last_err_info(
+ ll::get_loop_for_uv_handle(client_stream_ptr
+ as *libc::c_void)));
+ assert false;
+ }
+ }
+ else {
+ log(debug, "SERVER: client req DOESNT contain server_kill_msg!");
+ }
+ }
+ else if (nread == -1) {
+ // err .. possibly EOF
+ log(debug, "read: eof!");
+ }
+ else {
+ // nread == 0 .. do nothing, just free buf as below
+ log(debug, "read: do nothing!");
+ }
+ // when we're done
+ ll::free_base_of_buf(buf);
+ log(debug, "SERVER exiting on_read_cb");
+}
+
+crust fn server_connection_cb(server_stream_ptr:
+ *ll::uv_stream_t,
+ status: libc::c_int) unsafe {
+ log(debug, "client connecting!");
+ let test_loop = ll::get_loop_for_uv_handle(
+ server_stream_ptr as *libc::c_void);
+ if status != 0i32 {
+ let err_msg = ll::get_last_err_info(test_loop);
+ log(debug, #fmt("server_connect_cb: non-zero status: %?",
+ err_msg));
+ ret;
+ }
+ let server_data = ll::get_data_for_uv_handle(
+ server_stream_ptr as *libc::c_void) as *tcp_server_data;
+ let client_stream_ptr = (*server_data).client;
+ let client_init_result = ll::tcp_init(test_loop,
+ client_stream_ptr);
+ ll::set_data_for_uv_handle(
+ client_stream_ptr as *libc::c_void,
+ server_data as *libc::c_void);
+ if (client_init_result == 0i32) {
+ log(debug, "successfully initialized client stream");
+ let accept_result = ll::accept(server_stream_ptr as
+ *libc::c_void,
+ client_stream_ptr as
+ *libc::c_void);
+ if (accept_result == 0i32) {
+ // start reading
+ let read_result = ll::read_start(
+ client_stream_ptr as *ll::uv_stream_t,
+ on_alloc_cb,
+ on_server_read_cb);
+ if (read_result == 0i32) {
+ log(debug, "successful server read start");
+ }
+ else {
+ log(debug, #fmt("server_connection_cb: bad read:%d",
+ read_result as int));
+ assert false;
+ }
+ }
+ else {
+ log(debug, #fmt("server_connection_cb: bad accept: %d",
+ accept_result as int));
+ assert false;
+ }
+ }
+ else {
+ log(debug, #fmt("server_connection_cb: bad client init: %d",
+ client_init_result as int));
+ assert false;
+ }
+}
+
+type tcp_server_data = {
+ client: *ll::uv_tcp_t,
+ server: *ll::uv_tcp_t,
+ server_kill_msg: str,
+ server_resp_buf: *[ll::uv_buf_t],
+ server_chan: *comm::chan<str>,
+ server_write_req: *ll::uv_write_t
+};
+
+type async_handle_data = {
+ continue_chan: *comm::chan<bool>
+};
+
+crust fn async_close_cb(handle: *libc::c_void) {
+ log(debug, #fmt("SERVER: closing async cb... h: %?",
+ handle));
+}
+
+crust fn continue_async_cb(async_handle: *ll::uv_async_t,
+ status: libc::c_int) unsafe {
+ // once we're in the body of this callback,
+ // the tcp server's loop is set up, so we
+ // can continue on to let the tcp client
+ // do its thang
+ let data = ll::get_data_for_uv_handle(
+ async_handle as *libc::c_void) as *async_handle_data;
+ let continue_chan = *((*data).continue_chan);
+ let should_continue = status == 0i32;
+ comm::send(continue_chan, should_continue);
+ ll::close(async_handle as *libc::c_void, async_close_cb);
+}
+
+fn impl_uv_tcp_server(server_ip: str,
+ server_port: int,
+ kill_server_msg: str,
+ server_resp_msg: str,
+ server_chan: *comm::chan<str>,
+ continue_chan: *comm::chan<bool>) unsafe {
+ let test_loop = ll::loop_new();
+ let tcp_server = ll::tcp_t();
+ let tcp_server_ptr = ptr::addr_of(tcp_server);
+
+ let tcp_client = ll::tcp_t();
+ let tcp_client_ptr = ptr::addr_of(tcp_client);
+
+ let server_write_req = ll::write_t();
+ let server_write_req_ptr = ptr::addr_of(server_write_req);
+
+ let resp_str_bytes = str::bytes(server_resp_msg);
+ let resp_msg_ptr: *u8 = vec::unsafe::to_ptr(resp_str_bytes);
+ log(debug, #fmt("resp_msg ptr: %u", resp_msg_ptr as uint));
+ let resp_msg = [
+ ll::buf_init(resp_msg_ptr, vec::len(resp_str_bytes))
+ ];
+
+ let continue_async_handle = ll::async_t();
+ let continue_async_handle_ptr =
+ ptr::addr_of(continue_async_handle);
+ let async_data =
+ { continue_chan: continue_chan };
+ let async_data_ptr = ptr::addr_of(async_data);
+
+ let server_data: tcp_server_data = {
+ client: tcp_client_ptr,
+ server: tcp_server_ptr,
+ server_kill_msg: kill_server_msg,
+ server_resp_buf: ptr::addr_of(resp_msg),
+ server_chan: server_chan,
+ server_write_req: server_write_req_ptr
+ };
+ let server_data_ptr = ptr::addr_of(server_data);
+ ll::set_data_for_uv_handle(tcp_server_ptr as *libc::c_void,
+ server_data_ptr as *libc::c_void);
+
+ // uv_tcp_init()
+ let tcp_init_result = ll::tcp_init(
+ test_loop as *libc::c_void, tcp_server_ptr);
+ if (tcp_init_result == 0i32) {
+ let server_addr = ll::ip4_addr(server_ip, server_port);
+ // FIXME ref #2064
+ let server_addr_ptr = ptr::addr_of(server_addr);
+
+ // uv_tcp_bind()
+ let bind_result = ll::tcp_bind(tcp_server_ptr,
+ server_addr_ptr);
+ if (bind_result == 0i32) {
+ log(debug, "successful uv_tcp_bind, listening");
+
+ // uv_listen()
+ let listen_result = ll::listen(tcp_server_ptr as
+ *libc::c_void,
+ 128i32,
+ server_connection_cb);
+ if (listen_result == 0i32) {
+ // let the test know it can set up the tcp server,
+ // now.. this may still present a race, not sure..
+ let async_result = ll::async_init(test_loop,
+ continue_async_handle_ptr,
+ continue_async_cb);
+ if (async_result == 0i32) {
+ ll::set_data_for_uv_handle(
+ continue_async_handle_ptr as *libc::c_void,
+ async_data_ptr as *libc::c_void);
+ ll::async_send(continue_async_handle_ptr);
+ // uv_run()
+ ll::run(test_loop);
+ log(debug, "server uv::run() has returned");
+ }
+ else {
+ log(debug, #fmt("uv_async_init failure: %d",
+ async_result as int));
+ assert false;
+ }
+ }
+ else {
+ log(debug, #fmt("non-zero result on uv_listen: %d",
+ listen_result as int));
+ assert false;
+ }
+ }
+ else {
+ log(debug, #fmt("non-zero result on uv_tcp_bind: %d",
+ bind_result as int));
+ assert false;
+ }
+ }
+ else {
+ log(debug, #fmt("non-zero result on uv_tcp_init: %d",
+ tcp_init_result as int));
+ assert false;
+ }
+ ll::loop_delete(test_loop);
+}
+
+// this is the impl for a test that is (maybe) ran on a
+// per-platform/arch basis below
+fn impl_uv_tcp_server_and_request() unsafe {
+ let bind_ip = "0.0.0.0";
+ let request_ip = "127.0.0.1";
+ let port = 8888;
+ let kill_server_msg = "does a dog have buddha nature?";
+ let server_resp_msg = "mu!";
+ let client_port = comm::port::<str>();
+ let client_chan = comm::chan::<str>(client_port);
+ let server_port = comm::port::<str>();
+ let server_chan = comm::chan::<str>(server_port);
+
+ let continue_port = comm::port::<bool>();
+ let continue_chan = comm::chan::<bool>(continue_port);
+ let continue_chan_ptr = ptr::addr_of(continue_chan);
+
+ task::spawn_sched(task::manual_threads(1u)) {||
+ impl_uv_tcp_server(bind_ip, port,
+ kill_server_msg,
+ server_resp_msg,
+ ptr::addr_of(server_chan),
+ continue_chan_ptr);
+ };
+
+ // block until the server up is.. possibly a race?
+ log(debug, "before receiving on server continue_port");
+ comm::recv(continue_port);
+ log(debug, "received on continue port, set up tcp client");
+
+ task::spawn_sched(task::manual_threads(1u)) {||
+ impl_uv_tcp_request(request_ip, port,
+ kill_server_msg,
+ ptr::addr_of(client_chan));
+ };
+
+ let msg_from_client = comm::recv(server_port);
+ let msg_from_server = comm::recv(client_port);
+
+ assert str::contains(msg_from_client, kill_server_msg);
+ assert str::contains(msg_from_server, server_resp_msg);
+}
+
+// don't run this test on fbsd or 32bit linux
+#[cfg(target_os="win32")]
+#[cfg(target_os="darwin")]
+#[cfg(target_os="linux")]
+mod tcp_and_server_client_test {
+ #[cfg(target_arch="x86_64")]
+ mod impl64 {
+ #[test]
+ fn test_uv_tcp_server_and_request() unsafe {
+ impl_uv_tcp_server_and_request();
+ }
+ }
+ #[cfg(target_arch="x86")]
+ mod impl32 {
+ #[test]
+ #[ignore(cfg(target_os = "linux"))]
+ fn test_uv_tcp_server_and_request() unsafe {
+ impl_uv_tcp_server_and_request();
+ }
+ }
+}
+
+// struct size tests
+#[test]
+#[ignore(cfg(target_os = "freebsd"))]
+fn test_uv_struct_size_uv_tcp_t() {
+ let native_handle_size = rustrt::rust_uv_helper_uv_tcp_t_size();
+ let rust_handle_size = sys::size_of::<ll::uv_tcp_t>();
+ let output = #fmt("uv_tcp_t -- native: %u rust: %u",
+ native_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert native_handle_size as uint == rust_handle_size;
+}
+#[test]
+#[ignore(cfg(target_os = "freebsd"))]
+fn test_uv_struct_size_uv_connect_t() {
+ let native_handle_size =
+ rustrt::rust_uv_helper_uv_connect_t_size();
+ let rust_handle_size = sys::size_of::<ll::uv_connect_t>();
+ let output = #fmt("uv_connect_t -- native: %u rust: %u",
+ native_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert native_handle_size as uint == rust_handle_size;
+}
+#[test]
+#[ignore(cfg(target_os = "freebsd"))]
+fn test_uv_struct_size_uv_buf_t() {
+ let native_handle_size =
+ rustrt::rust_uv_helper_uv_buf_t_size();
+ let rust_handle_size = sys::size_of::<ll::uv_buf_t>();
+ let output = #fmt("uv_buf_t -- native: %u rust: %u",
+ native_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert native_handle_size as uint == rust_handle_size;
+}
+#[test]
+#[ignore(cfg(target_os = "freebsd"))]
+fn test_uv_struct_size_uv_write_t() {
+ let native_handle_size =
+ rustrt::rust_uv_helper_uv_write_t_size();
+ let rust_handle_size = sys::size_of::<ll::uv_write_t>();
+ let output = #fmt("uv_write_t -- native: %u rust: %u",
+ native_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert native_handle_size as uint == rust_handle_size;
+}
+
+#[test]
+#[ignore(cfg(target_os = "freebsd"))]
+fn test_uv_struct_size_sockaddr_in() {
+ let native_handle_size =
+ rustrt::rust_uv_helper_sockaddr_in_size();
+ let rust_handle_size = sys::size_of::<ll::sockaddr_in>();
+ let output = #fmt("sockaddr_in -- native: %u rust: %u",
+ native_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert native_handle_size as uint == rust_handle_size;
+}
+
+#[test]
+#[ignore(cfg(target_os = "freebsd"))]
+fn test_uv_struct_size_uv_async_t() {
+ let native_handle_size =
+ rustrt::rust_uv_helper_uv_async_t_size();
+ let rust_handle_size = sys::size_of::<ll::uv_async_t>();
+ let output = #fmt("uv_async_t -- native: %u rust: %u",
+ native_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert native_handle_size as uint == rust_handle_size;
+}
+
--- /dev/null
+#[doc = "
+High-level bindings to work with the libuv library.
+
+This module is geared towards library developers who want to
+provide a high-level, abstracted interface to some set of
+libuv functionality.
+"];
+
+import ll = uv_ll;
+
+export high_level_loop;
+export interact, prepare_loop;
+
+#[doc = "
+Used to abstract-away direct interaction with a libuv loop.
+
+# Fields
+
+* async_handle - 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
+"]
+type high_level_loop = {
+ async_handle: *ll::uv_async_t,
+ op_chan: comm::chan<fn~(*libc::c_void)>
+};
+
+#[doc = "
+Pass in a callback to be processed on the running libuv loop's thread
+
+# Fields
+
+* a_loop - a high_level_loop record that represents a channel of
+communication with an active libuv loop running on a thread
+somwhere in the current process
+
+* 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. You can use this pointer to initiate or continue any
+operations against the loop
+"]
+unsafe fn interact(a_loop: high_level_loop,
+ -cb: fn~(*libc::c_void)) {
+ comm::send(a_loop.op_chan, cb);
+ ll::async_send(a_loop.async_handle);
+}
+
+#[doc = "
+Prepares a clean, inactive uv_loop_t* to be used with any of the
+functions in the `uv::hl` module.
+
+Library developers can use this function to prepare a given
+`uv_loop_t*`, whose lifecycle they manage, to be used, ran
+and controlled with the tools in this module.
+
+After this is ran against a loop, a library developer can run
+the loop in its own thread and then use the returned
+`high_level_loop` to interact with it.
+
+# Fields
+
+* loop_ptr - a pointer to a newly created `uv_loop_t*` with no
+handles registered (this will interfere with the internal lifecycle
+management this module provides). Ideally, this should be called
+immediately after using `uv::ll::loop_new()`
+
+# Returns
+
+A `high_level_loop` record that can be used to interact with the
+loop (after you use `uv::ll::run()` on the `uv_loop_t*`, of course
+"]
+unsafe fn prepare_loop(loop_ptr: *libc::c_void)
+ -> high_level_loop {
+ // will probably need to stake out a data record
+ // here, as well, to keep whatever state we want to
+ // use with the loop
+
+ // move this into a malloc
+ let async = ll::async_t();
+ let async_ptr = ptr::addr_of(async);
+ let op_port = comm::port::<fn~(*libc::c_void)>();
+ let async_result = ll::async_init(loop_ptr,
+ async_ptr,
+ interact_poke);
+ if (async_result != 0i32) {
+ fail ll::get_last_err_info(loop_ptr);
+ }
+ // need to store the port and async_ptr in the top-level
+ // of the provided loop ..
+ ret { async_handle: async_ptr,
+ op_chan: comm::chan::<fn~(*libc::c_void)>(op_port)
+ };
+}
+
+// this will be invoked by a called to uv::hl::interact(), so
+// we'll drain the port of pending callbacks, processing each
+crust fn interact_poke(async_handle: *libc::c_void) {
+ // nothing here, yet.
+ log(debug, #fmt("interact_poke crust.. handle: %?",
+ async_handle));
+}
\ No newline at end of file
--- /dev/null
+#[doc = "
+Low-level bindings to the libuv library.
+
+This module contains a set of direct, 'bare-metal' wrappers around
+the libuv C-API.
+
+Also contained herein are a set of rust records that map, in
+approximate memory-size, to the libuv data structures. The record
+implementations are adjusted, per-platform, to match their respective
+representations.
+
+There are also a collection of helper functions to ease interacting
+with the low-level API (such as a function to return the latest
+libuv error as a rust-formatted string).
+
+As new functionality, existant in uv.h, is added to the rust stdlib,
+the mappings should be added in this module.
+
+This module's implementation will hopefully be, eventually, replaced
+with per-platform, generated source files from rust-bindgen.
+"];
+
+// libuv struct mappings
+type uv_ip4_addr = {
+ ip: [u8],
+ port: int
+};
+type uv_ip6_addr = uv_ip4_addr;
+
+enum uv_handle_type {
+ UNKNOWN_HANDLE = 0,
+ UV_TCP,
+ UV_UDP,
+ UV_NAMED_PIPE,
+ UV_TTY,
+ UV_FILE,
+ UV_TIMER,
+ UV_PREPARE,
+ UV_CHECK,
+ UV_IDLE,
+ UV_ASYNC,
+ UV_ARES_TASK,
+ UV_ARES_EVENT,
+ UV_PROCESS,
+ UV_FS_EVENT
+}
+
+type handle_type = libc::c_uint;
+
+type uv_handle_fields = {
+ loop_handle: *libc::c_void,
+ type_: handle_type,
+ close_cb: *u8,
+ mut data: *libc::c_void,
+};
+
+// unix size: 8
+type uv_err_t = {
+ code: libc::c_int,
+ sys_errno_: libc::c_int
+};
+
+// don't create one of these directly. instead,
+// count on it appearing in libuv callbacks or embedded
+// in other types as a pointer to be used in other
+// operations (so mostly treat it as opaque, once you
+// have it in this form..)
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "win32")]
+type uv_stream_t = {
+ fields: uv_handle_fields
+};
+
+// 64bit unix size: 272
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+type uv_tcp_t = {
+ fields: uv_handle_fields,
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8, a10: *u8, a11: *u8,
+ a12: *u8, a13: *u8, a14: *u8, a15: *u8,
+ a16: *u8, a17: *u8, a18: *u8, a19: *u8,
+ a20: *u8, a21: *u8, a22: *u8, a23: *u8,
+ a24: *u8, a25: *u8, a26: *u8, a27: *u8,
+ a28: *u8,
+ a30: uv_tcp_t_32bit_unix_riders
+};
+// 32bit unix size: 328 (164)
+#[cfg(target_arch="x86_64")]
+type uv_tcp_t_32bit_unix_riders = {
+ a29: *u8
+};
+#[cfg(target_arch="x86")]
+type uv_tcp_t_32bit_unix_riders = {
+ a29: *u8, a30: *u8, a31: *u8,
+ a32: *u8, a33: *u8, a34: *u8,
+ a35: *u8, a36: *u8
+};
+
+// 32bit win32 size: 240 (120)
+#[cfg(target_os = "win32")]
+type uv_tcp_t = {
+ fields: uv_handle_fields,
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8, a10: *u8, a11: *u8,
+ a12: *u8, a13: *u8, a14: *u8, a15: *u8,
+ a16: *u8, a17: *u8, a18: *u8, a19: *u8,
+ a20: *u8, a21: *u8, a22: *u8, a23: *u8,
+ a24: *u8, a25: *u8
+};
+
+// unix size: 48
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+type uv_connect_t = {
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8
+};
+// win32 size: 88 (44)
+#[cfg(target_os = "win32")]
+type uv_connect_t = {
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8, a10: *u8
+};
+
+// unix size: 16
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "win32")]
+type uv_buf_t = {
+ base: *u8,
+ len: libc::size_t
+};
+// no gen stub method.. should create
+// it via uv::direct::buf_init()
+
+// unix size: 144
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+type uv_write_t = {
+ fields: uv_handle_fields,
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8, a10: *u8, a11: *u8,
+ a12: *u8,
+ a14: uv_write_t_32bit_unix_riders
+};
+#[cfg(target_arch="x86_64")]
+type uv_write_t_32bit_unix_riders = {
+ a13: *u8
+};
+#[cfg(target_arch="x86")]
+type uv_write_t_32bit_unix_riders = {
+ a13: *u8, a14: *u8
+};
+// win32 size: 136 (68)
+#[cfg(target_os = "win32")]
+type uv_write_t = {
+ fields: uv_handle_fields,
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8, a10: *u8, a11: *u8,
+ a12: *u8
+};
+// 64bit unix size: 120
+// 32bit unix size: 152 (76)
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+type uv_async_t = {
+ fields: uv_handle_fields,
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8,
+ a11: uv_async_t_32bit_unix_riders
+};
+#[cfg(target_arch="x86_64")]
+type uv_async_t_32bit_unix_riders = {
+ a10: *u8
+};
+#[cfg(target_arch="x86")]
+type uv_async_t_32bit_unix_riders = {
+ a10: *u8, a11: *u8, a12: *u8, a13: *u8
+};
+// win32 size 132 (68)
+#[cfg(target_os = "win32")]
+type uv_async_t = {
+ fields: uv_handle_fields,
+ a00: *u8, a01: *u8, a02: *u8, a03: *u8,
+ a04: *u8, a05: *u8, a06: *u8, a07: *u8,
+ a08: *u8, a09: *u8, a10: *u8, a11: *u8,
+ a12: *u8
+};
+
+// unix size: 16
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "win32")]
+type sockaddr_in = {
+ mut sin_family: u16,
+ mut sin_port: u16,
+ mut sin_addr: u32, // in_addr: this is an opaque, per-platform struct
+ mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8)
+};
+
+// unix size: 28 .. make due w/ 32
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "win32")]
+type sockaddr_in6 = {
+ a0: *u8, a1: *u8,
+ a2: *u8, a3: *u8
+};
+
+mod uv_ll_struct_stubgen {
+ fn gen_stub_uv_tcp_t() -> uv_tcp_t {
+ ret gen_stub_os();
+ #[cfg(target_os = "linux")]
+ #[cfg(target_os = "macos")]
+ #[cfg(target_os = "freebsd")]
+ fn gen_stub_os() -> uv_tcp_t {
+ ret gen_stub_arch();
+ #[cfg(target_arch="x86_64")]
+ fn gen_stub_arch() -> uv_tcp_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
+ a15: 0 as *u8,
+ a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
+ a19: 0 as *u8,
+ a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
+ a23: 0 as *u8,
+ a24: 0 as *u8, a25: 0 as *u8, a26: 0 as *u8,
+ a27: 0 as *u8,
+ a28: 0 as *u8,
+ a30: {
+ a29: 0 as *u8
+ }
+ };
+ }
+ #[cfg(target_arch="x86")]
+ fn gen_stub_arch() -> uv_tcp_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
+ a15: 0 as *u8,
+ a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
+ a19: 0 as *u8,
+ a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
+ a23: 0 as *u8,
+ a24: 0 as *u8, a25: 0 as *u8, a26: 0 as *u8,
+ a27: 0 as *u8,
+ a28: 0 as *u8,
+ a30: {
+ a29: 0 as *u8, a30: 0 as *u8, a31: 0 as *u8,
+ a32: 0 as *u8, a33: 0 as *u8, a34: 0 as *u8,
+ a35: 0 as *u8, a36: 0 as *u8
+ }
+ };
+ }
+ }
+ #[cfg(target_os = "win32")]
+ fn gen_stub_os() -> uv_tcp_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
+ a15: 0 as *u8,
+ a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
+ a19: 0 as *u8,
+ a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
+ a23: 0 as *u8,
+ a24: 0 as *u8, a25: 0 as *u8
+ };
+ }
+ }
+ #[cfg(target_os = "linux")]
+ #[cfg(target_os = "macos")]
+ #[cfg(target_os = "freebsd")]
+ fn gen_stub_uv_connect_t() -> uv_connect_t {
+ ret {
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8
+ };
+ }
+ #[cfg(target_os = "win32")]
+ fn gen_stub_uv_connect_t() -> uv_connect_t {
+ ret {
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8
+ };
+ }
+ #[cfg(target_os = "linux")]
+ #[cfg(target_os = "macos")]
+ #[cfg(target_os = "freebsd")]
+ fn gen_stub_uv_async_t() -> uv_async_t {
+ ret gen_stub_arch();
+ #[cfg(target_arch = "x86_64")]
+ fn gen_stub_arch() -> uv_async_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8,
+ a11: {
+ a10: 0 as *u8
+ }
+ };
+ }
+ #[cfg(target_arch = "x86")]
+ fn gen_stub_arch() -> uv_async_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8,
+ a11: {
+ a10: 0 as *u8, a11: 0 as *u8,
+ a12: 0 as *u8, a13: 0 as *u8
+ }
+ };
+ }
+ }
+ #[cfg(target_os = "win32")]
+ fn gen_stub_uv_async_t() -> uv_async_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8
+ };
+ }
+ #[cfg(target_os = "linux")]
+ #[cfg(target_os = "macos")]
+ #[cfg(target_os = "freebsd")]
+ fn gen_stub_uv_write_t() -> uv_write_t {
+ ret gen_stub_arch();
+ #[cfg(target_arch="x86_64")]
+ fn gen_stub_arch() -> uv_write_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8, a14: { a13: 0 as *u8 }
+ };
+ }
+ #[cfg(target_arch="x86")]
+ fn gen_stub_arch() -> uv_write_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8, a14: { a13: 0 as *u8, a14: 0 as *u8 }
+ };
+ }
+ }
+ #[cfg(target_os = "win32")]
+ fn gen_stub_uv_write_t() -> uv_write_t {
+ ret { fields: { loop_handle: ptr::null(), type_: 0u32,
+ close_cb: ptr::null(),
+ mut data: ptr::null() },
+ a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
+ a03: 0 as *u8,
+ a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
+ a07: 0 as *u8,
+ a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
+ a11: 0 as *u8,
+ a12: 0 as *u8
+ };
+ }
+}
+
+#[nolink]
+native mod rustrt {
+ fn rust_uv_loop_new() -> *libc::c_void;
+ fn rust_uv_loop_delete(lp: *libc::c_void);
+ 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);
+ fn rust_uv_async_init(loop_handle: *libc::c_void,
+ async_handle: *uv_async_t,
+ cb: *u8) -> libc::c_int;
+ fn rust_uv_tcp_init(
+ loop_handle: *libc::c_void,
+ handle_ptr: *uv_tcp_t) -> libc::c_int;
+ // FIXME ref #2604 .. ?
+ fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8,
+ len: libc::size_t);
+ fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t;
+ // FIXME ref #2064
+ fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char;
+ // FIXME ref #2064
+ fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char;
+ fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int)
+ -> sockaddr_in;
+ // FIXME ref #2064
+ fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
+ tcp_handle_ptr: *uv_tcp_t,
+ ++after_cb: *u8,
+ ++addr: *sockaddr_in) -> libc::c_int;
+ // FIXME ref 2064
+ fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t,
+ ++addr: *sockaddr_in) -> libc::c_int;
+ fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int,
+ cb: *u8) -> libc::c_int;
+ fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void)
+ -> libc::c_int;
+ fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void,
+ ++buf_in: *uv_buf_t, buf_cnt: libc::c_int,
+ cb: *u8) -> libc::c_int;
+ fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8,
+ on_read: *u8) -> libc::c_int;
+ fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int;
+ fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8;
+ fn rust_uv_free_base_of_buf(++buf: uv_buf_t);
+
+ // data accessors for rust-mapped uv structs
+ fn rust_uv_get_stream_handle_from_connect_req(
+ connect_req: *uv_connect_t)
+ -> *uv_stream_t;
+ fn rust_uv_get_stream_handle_from_write_req(
+ write_req: *uv_write_t)
+ -> *uv_stream_t;
+ fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void)
+ -> *libc::c_void;
+ fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void)
+ -> *libc::c_void;
+ fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void,
+ data: *libc::c_void);
+ fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void;
+ fn rust_uv_set_data_for_req(req: *libc::c_void,
+ data: *libc::c_void);
+ fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8;
+ fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> libc::size_t;
+}
+
+unsafe fn loop_new() -> *libc::c_void {
+ ret rustrt::rust_uv_loop_new();
+}
+
+unsafe fn loop_delete(loop_handle: *libc::c_void) {
+ rustrt::rust_uv_loop_delete(loop_handle);
+}
+
+unsafe fn run(loop_handle: *libc::c_void) {
+ rustrt::rust_uv_run(loop_handle);
+}
+
+unsafe fn close(handle: *libc::c_void, cb: *u8) {
+ rustrt::rust_uv_close(handle, cb);
+}
+
+unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t)
+ -> libc::c_int {
+ ret rustrt::rust_uv_tcp_init(loop_handle, handle);
+}
+// FIXME ref #2064
+unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
+ tcp_handle_ptr: *uv_tcp_t,
+ addr_ptr: *sockaddr_in,
+ ++after_connect_cb: *u8)
+-> libc::c_int {
+ let address = *addr_ptr;
+ log(debug, #fmt("b4 native tcp_connect--addr port: %u cb: %u",
+ address.sin_port as uint, after_connect_cb as uint));
+ ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr,
+ after_connect_cb, addr_ptr);
+}
+// FIXME ref #2064
+unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t,
+ addr_ptr: *sockaddr_in) -> libc::c_int {
+ ret rustrt::rust_uv_tcp_bind(tcp_server_ptr,
+ addr_ptr);
+}
+
+unsafe fn listen(stream: *libc::c_void, backlog: libc::c_int,
+ cb: *u8) -> libc::c_int {
+ ret rustrt::rust_uv_listen(stream, backlog, cb);
+}
+
+unsafe fn accept(server: *libc::c_void, client: *libc::c_void)
+ -> libc::c_int {
+ ret rustrt::rust_uv_accept(server, client);
+}
+
+unsafe fn write(req: *libc::c_void, stream: *libc::c_void,
+ buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int {
+ let buf_ptr = vec::unsafe::to_ptr(*buf_in);
+ let buf_cnt = vec::len(*buf_in) as i32;
+ ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb);
+}
+unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8,
+ on_read: *u8) -> libc::c_int {
+ ret rustrt::rust_uv_read_start(stream as *libc::c_void,
+ on_alloc, on_read);
+}
+
+unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int {
+ ret rustrt::rust_uv_read_stop(stream as *libc::c_void);
+}
+
+unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t {
+ ret rustrt::rust_uv_last_error(loop_handle);
+}
+
+unsafe fn strerror(err: *uv_err_t) -> *libc::c_char {
+ ret rustrt::rust_uv_strerror(err);
+}
+unsafe fn err_name(err: *uv_err_t) -> *libc::c_char {
+ ret rustrt::rust_uv_err_name(err);
+}
+
+unsafe fn async_init(loop_handle: *libc::c_void,
+ async_handle: *uv_async_t,
+ cb: *u8) -> libc::c_int {
+ ret rustrt::rust_uv_async_init(loop_handle,
+ async_handle,
+ cb);
+}
+
+unsafe fn async_send(async_handle: *uv_async_t) {
+ ret rustrt::rust_uv_async_send(async_handle);
+}
+
+// libuv struct initializers
+unsafe fn tcp_t() -> uv_tcp_t {
+ ret uv_ll_struct_stubgen::gen_stub_uv_tcp_t();
+}
+unsafe fn connect_t() -> uv_connect_t {
+ ret uv_ll_struct_stubgen::gen_stub_uv_connect_t();
+}
+unsafe fn write_t() -> uv_write_t {
+ ret uv_ll_struct_stubgen::gen_stub_uv_write_t();
+}
+unsafe fn async_t() -> uv_async_t {
+ ret uv_ll_struct_stubgen::gen_stub_uv_async_t();
+}
+unsafe fn get_loop_for_uv_handle(handle: *libc::c_void)
+ -> *libc::c_void {
+ ret rustrt::rust_uv_get_loop_for_uv_handle(handle);
+}
+unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t)
+ -> *uv_stream_t {
+ ret rustrt::rust_uv_get_stream_handle_from_connect_req(
+ connect);
+}
+unsafe fn get_stream_handle_from_write_req(
+ write_req: *uv_write_t)
+ -> *uv_stream_t {
+ ret rustrt::rust_uv_get_stream_handle_from_write_req(
+ write_req);
+}
+
+unsafe fn get_data_for_uv_handle(handle: *libc::c_void) -> *libc::c_void {
+ ret rustrt::rust_uv_get_data_for_uv_handle(handle);
+}
+unsafe fn set_data_for_uv_handle(handle: *libc::c_void,
+ data: *libc::c_void) {
+ rustrt::rust_uv_set_data_for_uv_handle(handle, data);
+}
+unsafe fn get_data_for_req(req: *libc::c_void) -> *libc::c_void {
+ ret rustrt::rust_uv_get_data_for_req(req);
+}
+unsafe fn set_data_for_req(req: *libc::c_void,
+ data: *libc::c_void) {
+ rustrt::rust_uv_set_data_for_req(req, data);
+}
+unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
+ ret rustrt::rust_uv_get_base_from_buf(buf);
+}
+unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t {
+ ret rustrt::rust_uv_get_len_from_buf(buf);
+}
+unsafe fn buf_init(++input: *u8, len: uint) -> uv_buf_t {
+ let out_buf = { base: ptr::null(), len: 0 as libc::size_t };
+ let out_buf_ptr = ptr::addr_of(out_buf);
+ log(debug, #fmt("ll::buf_init - input %u len %u out_buf: %u",
+ input as uint,
+ len as uint,
+ out_buf_ptr as uint));
+ // yuck :/
+ rustrt::rust_uv_buf_init(out_buf_ptr, input, len);
+ //let result = rustrt::rust_uv_buf_init_2(input, len);
+ log(debug, "after rust_uv_buf_init");
+ let res_base = get_base_from_buf(out_buf);
+ let res_len = get_len_from_buf(out_buf);
+ //let res_base = get_base_from_buf(result);
+ log(debug, #fmt("ll::buf_init - result %u len %u",
+ res_base as uint,
+ res_len as uint));
+ ret out_buf;
+ //ret result;
+}
+unsafe fn ip4_addr(ip: str, port: int)
+-> sockaddr_in {
+ let mut addr_vec = str::bytes(ip);
+ addr_vec += [0u8]; // add null terminator
+ let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec);
+ let ip_back = str::from_bytes(addr_vec);
+ log(debug, #fmt("vec val: '%s' length: %u",
+ ip_back, vec::len(addr_vec)));
+ ret rustrt::rust_uv_ip4_addr(addr_vec_ptr,
+ port as libc::c_int);
+}
+unsafe fn malloc_buf_base_of(suggested_size: libc::size_t)
+ -> *u8 {
+ ret rustrt::rust_uv_malloc_buf_base_of(suggested_size);
+}
+unsafe fn free_base_of_buf(buf: uv_buf_t) {
+ rustrt::rust_uv_free_base_of_buf(buf);
+}
+
+unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> str {
+ let err = last_error(uv_loop);
+ let err_ptr = ptr::addr_of(err);
+ let err_name = str::unsafe::from_c_str(err_name(err_ptr));
+ let err_msg = str::unsafe::from_c_str(strerror(err_ptr));
+ ret #fmt("LIBUV ERROR: name: %s msg: %s",
+ err_name, err_msg);
+}
\ No newline at end of file
}
extern "C" CDECL uintptr_t
-rust_port_id_send(type_desc *t, rust_port_id target_port_id, void *sptr) {
- bool sent = false;
+rust_port_id_send(rust_port_id target_port_id, void *sptr) {
rust_task *task = rust_get_current_task();
-
- LOG(task, comm, "rust_port_id*_send port: 0x%" PRIxPTR,
- (uintptr_t) target_port_id);
-
- rust_port *port = task->kernel->get_port_by_id(target_port_id);
- if(port) {
- port->send(sptr);
- port->deref();
- sent = true;
- } else {
- LOG(task, comm, "didn't get the port");
- }
- return (uintptr_t)sent;
+ return (uintptr_t)task->kernel->send_to_port(target_port_id, sptr);
}
// This is called by an intrinsic on the Rust stack and must run
return task->kernel->osmain_sched_id();
}
+extern "C" CDECL bool
+rust_compare_and_swap_ptr(intptr_t *address,
+ intptr_t oldval, intptr_t newval) {
+ return sync::compare_and_swap(address, oldval, newval);
+}
+
+extern "C" CDECL void
+rust_task_weaken(rust_port_id chan) {
+ rust_task *task = rust_get_current_task();
+ task->kernel->weaken_task(chan);
+}
+
+extern "C" CDECL void
+rust_task_unweaken(rust_port_id chan) {
+ rust_task *task = rust_get_current_task();
+ task->kernel->unweaken_task(chan);
+}
+
//
// Local Variables:
// mode: C++
-
#include "rust_kernel.h"
#include "rust_port.h"
#include "rust_util.h"
#include "rust_scheduler.h"
#include "rust_sched_launcher.h"
+#include <algorithm>
#define KLOG_(...) \
KLOG(this, kern, __VA_ARGS__)
max_sched_id(0),
sched_reaper(this),
osmain_driver(NULL),
+ non_weak_tasks(0),
env(env)
{
// Create the single threaded scheduler that will run on the platform's
}
}
+void
+rust_kernel::register_task() {
+ KLOG_("Registering task");
+ uintptr_t new_non_weak_tasks = sync::increment(non_weak_tasks);
+ KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+}
+
+void
+rust_kernel::unregister_task() {
+ KLOG_("Unregistering task");
+ uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
+ KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+ if (new_non_weak_tasks == 0) {
+ end_weak_tasks();
+ }
+}
+
+void
+rust_kernel::weaken_task(rust_port_id chan) {
+ {
+ scoped_lock with(weak_task_lock);
+ KLOG_("Weakening task with channel %" PRIdPTR, chan);
+ weak_task_chans.push_back(chan);
+ }
+ uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
+ KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+ if (new_non_weak_tasks == 0) {
+ end_weak_tasks();
+ }
+}
+
+void
+rust_kernel::unweaken_task(rust_port_id chan) {
+ uintptr_t new_non_weak_tasks = sync::increment(non_weak_tasks);
+ KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
+ {
+ scoped_lock with(weak_task_lock);
+ KLOG_("Unweakening task with channel %" PRIdPTR, chan);
+ std::vector<rust_port_id>::iterator iter =
+ std::find(weak_task_chans.begin(), weak_task_chans.end(), chan);
+ if (iter != weak_task_chans.end()) {
+ weak_task_chans.erase(iter);
+ }
+ }
+}
+
+void
+rust_kernel::end_weak_tasks() {
+ std::vector<rust_port_id> chancopies;
+ {
+ //scoped_lock with(weak_task_lock);
+ chancopies = weak_task_chans;
+ weak_task_chans.clear();
+ }
+ while (!chancopies.empty()) {
+ rust_port_id chan = chancopies.back();
+ chancopies.pop_back();
+ KLOG_("Notifying weak task " PRIdPTR, chan);
+ uintptr_t token = 0;
+ send_to_port(chan, &token);
+ }
+}
+
+bool
+rust_kernel::send_to_port(rust_port_id chan, void *sptr) {
+ KLOG_("rust_port_id*_send port: 0x%" PRIxPTR, (uintptr_t) chan);
+
+ rust_port *port = get_port_by_id(chan);
+ if(port) {
+ port->send(sptr);
+ port->deref();
+ return true;
+ } else {
+ KLOG_("didn't get the port");
+ return false;
+ }
+}
+
//
// Local Variables:
// mode: C++
// on the main thread
rust_sched_driver *osmain_driver;
+ // An atomically updated count of the live, 'non-weak' tasks
+ uintptr_t non_weak_tasks;
+ // Protects weak_task_chans
+ lock_and_signal weak_task_lock;
+ // A list of weak tasks that need to be told when to exit
+ std::vector<rust_port_id> weak_task_chans;
+
rust_scheduler* get_scheduler_by_id_nolock(rust_sched_id id);
+ void end_weak_tasks();
public:
struct rust_env *env;
void set_exit_status(int code);
rust_sched_id osmain_sched_id() { return osmain_scheduler; }
+
+ void register_task();
+ void unregister_task();
+ void weaken_task(rust_port_id chan);
+ void unweaken_task(rust_port_id chan);
+
+ bool send_to_port(rust_port_id chan, void *sptr);
};
template <typename T> struct kernel_owned {
if (cur_thread >= num_threads)
cur_thread = 0;
}
+ kernel->register_task();
rust_sched_launcher *thread = threads[thread_no];
return thread->get_loop()->create_task(spawner, name);
}
need_exit = true;
}
}
+ kernel->unregister_task();
if (need_exit) {
exit();
}
// crust fn pointers
typedef void (*crust_async_op_cb)(uv_loop_t* loop, void* data,
- uv_async_t* op_handle);
+ uv_async_t* op_handle);
typedef void (*crust_simple_cb)(uint8_t* id_buf, void* loop_data);
typedef void (*crust_close_cb)(uint8_t* id_buf, void* handle,
- void* data);
+ void* data);
// data types
#define RUST_UV_HANDLE_LEN 16
struct handle_data {
- uint8_t id_buf[RUST_UV_HANDLE_LEN];
- crust_simple_cb cb;
- crust_close_cb close_cb;
+ uint8_t id_buf[RUST_UV_HANDLE_LEN];
+ crust_simple_cb cb;
+ crust_close_cb close_cb;
};
// helpers
static handle_data*
new_handle_data_from(uint8_t* buf, crust_simple_cb cb) {
- handle_data* data = (handle_data*)current_kernel_malloc(
- sizeof(handle_data),
- "handle_data");
- memcpy(data->id_buf, buf, RUST_UV_HANDLE_LEN);
- data->cb = cb;
- return data;
+ handle_data* data = (handle_data*)current_kernel_malloc(
+ sizeof(handle_data),
+ "handle_data");
+ memcpy(data->id_buf, buf, RUST_UV_HANDLE_LEN);
+ data->cb = cb;
+ return data;
}
// libuv callback impls
static void
native_crust_async_op_cb(uv_async_t* handle, int status) {
crust_async_op_cb cb = (crust_async_op_cb)handle->data;
- void* loop_data = handle->loop->data;
- cb(handle->loop, loop_data, handle);
+ void* loop_data = handle->loop->data;
+ cb(handle->loop, loop_data, handle);
}
static void
native_async_cb(uv_async_t* handle, int status) {
- handle_data* handle_d = (handle_data*)handle->data;
- void* loop_data = handle->loop->data;
- handle_d->cb(handle_d->id_buf, loop_data);
+ handle_data* handle_d = (handle_data*)handle->data;
+ void* loop_data = handle->loop->data;
+ handle_d->cb(handle_d->id_buf, loop_data);
}
static void
native_timer_cb(uv_timer_t* handle, int status) {
- handle_data* handle_d = (handle_data*)handle->data;
- void* loop_data = handle->loop->data;
- handle_d->cb(handle_d->id_buf, loop_data);
+ handle_data* handle_d = (handle_data*)handle->data;
+ void* loop_data = handle->loop->data;
+ handle_d->cb(handle_d->id_buf, loop_data);
}
static void
native_close_cb(uv_handle_t* handle) {
- handle_data* data = (handle_data*)handle->data;
- data->close_cb(data->id_buf, handle, handle->loop->data);
+ handle_data* data = (handle_data*)handle->data;
+ data->close_cb(data->id_buf, handle, handle->loop->data);
}
static void
native_close_op_cb(uv_handle_t* op_handle) {
- current_kernel_free(op_handle);
- // uv_run() should return after this..
+ current_kernel_free(op_handle);
+ // uv_run() should return after this..
}
// native fns bound in rust
+extern "C" void
+rust_uv_free(void* ptr) {
+ current_kernel_free(ptr);
+}
extern "C" void*
rust_uv_loop_new() {
return (void*)uv_loop_new();
extern "C" void*
rust_uv_bind_op_cb(uv_loop_t* loop, crust_async_op_cb cb) {
- uv_async_t* async = (uv_async_t*)current_kernel_malloc(
- sizeof(uv_async_t),
- "uv_async_t");
- uv_async_init(loop, async, native_crust_async_op_cb);
- async->data = (void*)cb;
- // decrement the ref count, so that our async bind
- // doesn't count towards keeping the loop alive
- //uv_unref(loop);
- return async;
+ uv_async_t* async = (uv_async_t*)current_kernel_malloc(
+ sizeof(uv_async_t),
+ "uv_async_t");
+ uv_async_init(loop, async, native_crust_async_op_cb);
+ async->data = (void*)cb;
+ // decrement the ref count, so that our async bind
+ // doesn't count towards keeping the loop alive
+ //uv_unref(loop);
+ return async;
}
extern "C" void
rust_uv_stop_op_cb(uv_handle_t* op_handle) {
- uv_close(op_handle, native_close_op_cb);
+ uv_close(op_handle, native_close_op_cb);
}
extern "C" void
rust_uv_run(uv_loop_t* loop) {
- uv_run(loop);
+ uv_run(loop);
+}
+
+extern "C" void
+rust_uv_close(uv_handle_t* handle, uv_close_cb cb) {
+ uv_close(handle, cb);
}
extern "C" void
-rust_uv_close(uv_handle_t* handle, crust_close_cb cb) {
- handle_data* data = (handle_data*)handle->data;
- data->close_cb = cb;
- uv_close(handle, native_close_cb);
+rust_uv_hilvl_close(uv_handle_t* handle, crust_close_cb cb) {
+ handle_data* data = (handle_data*)handle->data;
+ data->close_cb = cb;
+ uv_close(handle, native_close_cb);
}
extern "C" void
-rust_uv_close_async(uv_async_t* handle) {
- current_kernel_free(handle->data);
- current_kernel_free(handle);
+rust_uv_hilvl_close_async(uv_async_t* handle) {
+ current_kernel_free(handle->data);
+ current_kernel_free(handle);
}
extern "C" void
-rust_uv_close_timer(uv_async_t* handle) {
- current_kernel_free(handle->data);
- current_kernel_free(handle);
+rust_uv_hilvl_close_timer(uv_async_t* handle) {
+ current_kernel_free(handle->data);
+ current_kernel_free(handle);
}
extern "C" void
uv_async_send(handle);
}
+extern "C" int
+rust_uv_async_init(uv_loop_t* loop_handle,
+ uv_async_t* async_handle,
+ uv_async_cb cb) {
+ return uv_async_init(loop_handle, async_handle, cb);
+}
+
extern "C" void*
-rust_uv_async_init(uv_loop_t* loop, crust_simple_cb cb,
- uint8_t* buf) {
- uv_async_t* async = (uv_async_t*)current_kernel_malloc(
- sizeof(uv_async_t),
- "uv_async_t");
- uv_async_init(loop, async, native_async_cb);
- handle_data* data = new_handle_data_from(buf, cb);
- async->data = data;
+rust_uv_hilvl_async_init(uv_loop_t* loop, crust_simple_cb cb,
+ uint8_t* buf) {
+ uv_async_t* async = (uv_async_t*)current_kernel_malloc(
+ sizeof(uv_async_t),
+ "uv_async_t");
+ uv_async_init(loop, async, native_async_cb);
+ handle_data* data = new_handle_data_from(buf, cb);
+ async->data = data;
- return async;
+ return async;
}
extern "C" void*
rust_uv_timer_init(uv_loop_t* loop, crust_simple_cb cb,
- uint8_t* buf) {
- uv_timer_t* new_timer = (uv_timer_t*)current_kernel_malloc(
- sizeof(uv_timer_t),
- "uv_timer_t");
- uv_timer_init(loop, new_timer);
- handle_data* data = new_handle_data_from(buf, cb);
- new_timer->data = data;
+ uint8_t* buf) {
+ uv_timer_t* new_timer = (uv_timer_t*)current_kernel_malloc(
+ sizeof(uv_timer_t),
+ "uv_timer_t");
+ uv_timer_init(loop, new_timer);
+ handle_data* data = new_handle_data_from(buf, cb);
+ new_timer->data = data;
- return new_timer;
+ return new_timer;
}
extern "C" void
rust_uv_timer_start(uv_timer_t* the_timer, uint32_t timeout,
- uint32_t repeat) {
- uv_timer_start(the_timer, native_timer_cb, timeout, repeat);
+ uint32_t repeat) {
+ uv_timer_start(the_timer, native_timer_cb, timeout, repeat);
}
extern "C" void
rust_uv_timer_stop(uv_timer_t* the_timer) {
- uv_timer_stop(the_timer);
+ uv_timer_stop(the_timer);
+}
+
+extern "C" int
+rust_uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
+ return uv_tcp_init(loop, handle);
+}
+
+extern "C" int
+rust_uv_tcp_connect(uv_connect_t* connect_ptr,
+ uv_tcp_t* tcp_ptr,
+ uv_connect_cb cb,
+ sockaddr_in* addr_ptr) {
+ printf("inside rust_uv_tcp_connect\n");
+ // FIXME ref #2064
+ sockaddr_in addr = *addr_ptr;
+ printf("before tcp_connect .. port: %d\n", addr.sin_port);
+ printf("before tcp_connect.. tcp stream: %lu cb ptr: %lu\n",
+ (unsigned long int)tcp_ptr, (unsigned long int)cb);
+ int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb);
+ printf ("leaving rust_uv_tcp_connect.. and result: %d\n",
+ result);
+ return result;
+}
+
+extern "C" int
+rust_uv_tcp_bind(uv_tcp_t* tcp_server, sockaddr_in* addr_ptr) {
+ // FIXME ref #2064
+ sockaddr_in addr = *addr_ptr;
+ printf("before uv_tcp_bind .. tcp_server: %lu port: %d\n",
+ (unsigned long int)tcp_server, addr.sin_port);
+ return uv_tcp_bind(tcp_server, addr);
+}
+
+extern "C" int
+rust_uv_listen(uv_stream_t* stream, int backlog,
+ uv_connection_cb cb) {
+ return uv_listen(stream, backlog, cb);
+}
+
+extern "C" int
+rust_uv_accept(uv_stream_t* server, uv_stream_t* client) {
+ return uv_accept(server, client);
}
+extern "C" size_t
+rust_uv_helper_uv_tcp_t_size() {
+ return sizeof(uv_tcp_t);
+}
+extern "C" size_t
+rust_uv_helper_uv_connect_t_size() {
+ return sizeof(uv_connect_t);
+}
+extern "C" size_t
+rust_uv_helper_uv_buf_t_size() {
+ return sizeof(uv_buf_t);
+}
+extern "C" size_t
+rust_uv_helper_uv_write_t_size() {
+ return sizeof(uv_write_t);
+}
+extern "C" size_t
+rust_uv_helper_uv_err_t_size() {
+ return sizeof(uv_err_t);
+}
+extern "C" size_t
+rust_uv_helper_sockaddr_in_size() {
+ return sizeof(sockaddr_in);
+}
+extern "C" size_t
+rust_uv_helper_uv_async_t_size() {
+ return sizeof(uv_async_t);
+}
+
+extern "C" uv_stream_t*
+rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) {
+ return connect->handle;
+}
+extern "C" uv_stream_t*
+rust_uv_get_stream_handle_from_write_req(uv_write_t* write_req) {
+ return write_req->handle;
+}
+
+extern "C" uv_buf_t
+current_kernel_malloc_alloc_cb(uv_handle_t* handle,
+ size_t suggested_size) {
+ char* base_ptr = (char*)current_kernel_malloc(sizeof(char)
+ * suggested_size,
+ "uv_buf_t_base_val");
+ return uv_buf_init(base_ptr, suggested_size);
+}
+
+extern "C" void
+rust_uv_buf_init(uv_buf_t* out_buf, char* base, size_t len) {
+ printf("rust_uv_buf_init: base: %lu len: %lu\n",
+ (long unsigned int)base,
+ (long unsigned int)len);
+ *out_buf = uv_buf_init(base, len);
+ printf("rust_uv_buf_init: after: result->base: %lu len: %lu\n",
+ (unsigned long int)(*out_buf).base,
+ (unsigned long int)(*out_buf).len);
+}
+
+extern "C" uv_loop_t*
+rust_uv_get_loop_for_uv_handle(uv_handle_t* handle) {
+ return handle->loop;
+}
+
+extern "C" void*
+rust_uv_get_data_for_uv_handle(uv_handle_t* handle) {
+ return handle->data;
+}
+
+extern "C" void
+rust_uv_set_data_for_uv_handle(uv_handle_t* handle,
+ void* data) {
+ handle->data = data;
+}
+
+extern "C" void*
+rust_uv_get_data_for_req(uv_req_t* req) {
+ return req->data;
+}
+
+extern "C" void
+rust_uv_set_data_for_req(uv_req_t* req, void* data) {
+ req->data = data;
+}
+
+extern "C" char*
+rust_uv_get_base_from_buf(uv_buf_t buf) {
+ return buf.base;
+}
+
+extern "C" size_t
+rust_uv_get_len_from_buf(uv_buf_t buf) {
+ return buf.len;
+}
+
+extern "C" uv_err_t
+rust_uv_last_error(uv_loop_t* loop) {
+ return uv_last_error(loop);
+}
+
+extern "C" const char*
+rust_uv_strerror(uv_err_t* err_ptr) {
+ uv_err_t err = *err_ptr;
+ return uv_strerror(err);
+}
+
+extern "C" const char*
+rust_uv_err_name(uv_err_t* err_ptr) {
+ uv_err_t err = *err_ptr;
+ return uv_err_name(err);
+}
+
+extern "C" int
+rust_uv_write(uv_write_t* req, uv_stream_t* handle,
+ uv_buf_t* bufs, int buf_cnt,
+ uv_write_cb cb) {
+ return uv_write(req, handle, bufs, buf_cnt, cb);
+}
+extern "C" int
+rust_uv_read_start(uv_stream_t* stream, uv_alloc_cb on_alloc,
+ uv_read_cb on_read) {
+ return uv_read_start(stream, on_alloc, on_read);
+}
+
+extern "C" int
+rust_uv_read_stop(uv_stream_t* stream) {
+ return uv_read_stop(stream);
+}
+
+extern "C" char*
+rust_uv_malloc_buf_base_of(size_t suggested_size) {
+ return (char*) current_kernel_malloc(sizeof(char)*suggested_size,
+ "uv_buf_t base");
+}
+extern "C" void
+rust_uv_free_base_of_buf(uv_buf_t buf) {
+ current_kernel_free(buf.base);
+}
+
+extern "C" struct sockaddr_in
+rust_uv_ip4_addr(const char* ip, int port) {
+ printf("before creating addr_ptr.. ip %s port %d\n", ip, port);
+ struct sockaddr_in addr = uv_ip4_addr(ip, port);
+ printf("after creating .. port: %d\n", addr.sin_port);
+ return addr;
+}
rust_task_is_unwinding
rust_get_task
rust_task_config_notify
+rust_task_weaken
+rust_task_unweaken
sched_threads
shape_log_str
start_task
rust_uv_stop_op_cb
rust_uv_run
rust_uv_close
-rust_uv_close_async
-rust_uv_close_timer
+rust_uv_hilvl_close
+rust_uv_hilvl_close_async
+rust_uv_hilvl_close_timer
rust_uv_async_send
rust_uv_async_init
+rust_uv_hilvl_async_init
rust_uv_timer_init
rust_uv_timer_start
rust_uv_timer_stop
+rust_uv_free
+rust_uv_tcp_init
+rust_uv_buf_init
+rust_uv_last_error
+rust_uv_strerror
+rust_uv_err_name
+rust_uv_ip4_addr
+rust_uv_tcp_connect
+rust_uv_tcp_bind
+rust_uv_listen
+rust_uv_accept
+rust_uv_write
+rust_uv_read_start
+rust_uv_read_stop
+rust_uv_malloc_buf_base_of
+rust_uv_free_base_of_buf
+rust_uv_helper_uv_tcp_t_size
+rust_uv_helper_uv_connect_t_size
+rust_uv_helper_uv_buf_t_size
+rust_uv_helper_uv_write_t_size
+rust_uv_helper_uv_err_t_size
+rust_uv_helper_sockaddr_in_size
+rust_uv_helper_uv_async_t_size
+rust_uv_get_stream_handle_from_connect_req
+rust_uv_get_stream_handle_from_write_req
+rust_uv_get_loop_for_uv_handle
+rust_uv_get_data_for_uv_handle
+rust_uv_set_data_for_uv_handle
+rust_uv_get_data_for_req
+rust_uv_set_data_for_req
+rust_uv_get_base_from_buf
+rust_uv_get_len_from_buf
rust_dbg_lock_create
rust_dbg_lock_destroy
rust_dbg_lock_lock
rust_dbg_lock_signal
rust_dbg_call
rust_osmain_sched_id
+rust_compare_and_swap_ptr
\ No newline at end of file
let mut cmh_items: [@ast::meta_item] = [];
let linkage_metas = attr::find_linkage_metas(c.node.attrs);
attr::require_unique_names(sess.diagnostic(), linkage_metas);
- for meta: @ast::meta_item in linkage_metas {
+ for linkage_metas.each {|meta|
if attr::get_meta_item_name(meta) == "name" {
alt attr::get_meta_item_value_str(meta) {
some(v) { name = some(v); }
let cmh_items = attr::sort_meta_items(metas.cmh_items);
sha.reset();
- for m_: @ast::meta_item in cmh_items {
+ for cmh_items.each {|m_|
let m = m_;
alt m.node {
ast::meta_name_value(key, value) {
}
}
- for dh in dep_hashes {
+ for dep_hashes.each {|dh|
sha.input_str(len_and_str(dh));
}
sha.reset();
sha.input_str(link_meta.name);
sha.input_str("-");
- // FIXME: This wants to be link_meta.meta_hash
- sha.input_str(link_meta.name);
+ sha.input_str(link_meta.extras_hash);
sha.input_str("-");
sha.input_str(encoder::encoded_ty(tcx, t));
let hash = truncated_sha1_result(sha);
let mut n = "_ZN"; // Begin name-sequence.
- for s in ss {
+ for ss.each {|s|
alt s { path_name(s) | path_mod(s) {
let sani = sanitize(s);
n += #fmt["%u%s", str::len(sani), sani];
n
}
-fn exported_name(path: path, hash: str, _vers: str) -> str {
- // FIXME: versioning isn't working yet
- ret mangle(path + [path_name(hash)]); // + "@" + vers;
-
+fn exported_name(path: path, hash: str, vers: str) -> str {
+ ret mangle(path + [path_name(hash)] + [path_name(vers)]);
}
fn mangle_exported_name(ccx: @crate_ctxt, path: path, t: ty::t) -> str {
} else { lib_cmd = "-shared"; }
let cstore = sess.cstore;
- for cratepath: str in cstore::get_used_crate_files(cstore) {
+ for cstore::get_used_crate_files(cstore).each {|cratepath|
if str::ends_with(cratepath, ".rlib") {
cc_args += [cratepath];
cont;
}
let ula = cstore::get_used_link_args(cstore);
- for arg: str in ula { cc_args += [arg]; }
+ for ula.each {|arg| cc_args += [arg]; }
let used_libs = cstore::get_used_libraries(cstore);
- for l: str in used_libs { cc_args += ["-l" + l]; }
+ for used_libs.each {|l| cc_args += ["-l" + l]; }
if sess.building_library {
cc_args += [lib_cmd];
#debug("sysroot: %s", sysroot);
#debug("output: %s", output);
#debug("libs:");
- for libpath in libs {
+ for libs.each {|libpath|
#debug(" %s", libpath);
}
#debug("target_triple: %s", target_triple);
fn log_rpaths(desc: str, rpaths: [str]) {
#debug("%s rpaths:", desc);
- for rpath in rpaths {
+ for rpaths.each {|rpath|
#debug(" %s", rpath);
}
}
fn minimize_rpaths(rpaths: [str]) -> [str] {
let set = map::str_hash::<()>();
let mut minimized = [];
- for rpath in rpaths {
+ for rpaths.each {|rpath|
if !set.contains_key(rpath) {
minimized += [rpath];
set.insert(rpath, ());
tys: [TypeRef], rv: TypeRef) ->
ValueRef {
let mut arg_tys: [TypeRef] = [];
- for t: TypeRef in tys { arg_tys += [t]; }
+ for tys.each {|t| arg_tys += [t]; }
let fn_ty = T_fn(arg_tys, rv);
ret base::decl_cdecl_fn(llmod, prefix + name, fn_ty);
}
// FIXME: It would be nice to use the parser to parse all varieties of
// meta_item here. At the moment we just support the meta_word variant.
let mut words = [];
- for s: str in cfgspecs { words += [attr::mk_word_item(s)]; }
+ for cfgspecs.each {|s| words += [attr::mk_word_item(s)]; }
ret words;
}
-use std;
-use rustc;
+#[no_core];
+
+use core(vers = "0.2");
+use std(vers = "0.2");
+use rustc(vers = "0.2");
+
+import core::*;
// -*- rust -*-
import result::{ok, err};
let has_cfg_metas = vec::len(cfg_metas) > 0u;
if !has_cfg_metas { ret true; }
- for cfg_mi: @ast::meta_item in cfg_metas {
+ for cfg_metas.each {|cfg_mi|
if attr::contains(cfg, cfg_mi) { ret true; }
}
fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
#debug("building test vector from %u tests", vec::len(cx.testfns));
let mut descs = [];
- for test: test in cx.testfns {
+ for cx.testfns.each {|test|
let test_ = test; // Satisfy alias analysis
descs += [mk_test_desc_rec(cx, test_)];
}
fn tys_str(names: type_names, outer: [TypeRef], tys: [TypeRef]) -> str {
let mut s: str = "";
let mut first: bool = true;
- for t: TypeRef in tys {
+ for tys.each {|t|
if first { first = false; } else { s += ", "; }
s += type_to_str_inner(names, outer, t);
}
}
12 {
let mut i: uint = 0u;
- for tout: TypeRef in outer0 {
+ for outer0.each {|tout|
i += 1u;
if tout as int == ty as int {
let n: uint = vec::len::<TypeRef>(outer0) - i;
vfn(i.id);
alt i.node {
ast::item_res(_, _, _, d_id, c_id) { vfn(d_id); vfn(c_id); }
- ast::item_enum(vs, _) { for v in vs { vfn(v.node.id); } }
+ ast::item_enum(vs, _) { for vs.each {|v| vfn(v.node.id); } }
_ {}
}
},
#debug["Encoding side tables for id %d", id];
- option::with_option_do(tcx.def_map.find(id)) {|def|
+ option::iter(tcx.def_map.find(id)) {|def|
ebml_w.tag(c::tag_table_def) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
}
}
}
- option::with_option_do((*tcx.node_types).find(id as uint)) {|ty|
+ option::iter((*tcx.node_types).find(id as uint)) {|ty|
ebml_w.tag(c::tag_table_node_type) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
}
}
- option::with_option_do(tcx.node_type_substs.find(id)) {|tys|
+ option::iter(tcx.node_type_substs.find(id)) {|tys|
ebml_w.tag(c::tag_table_node_type_subst) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
}
}
- option::with_option_do(tcx.freevars.find(id)) {|fv|
+ option::iter(tcx.freevars.find(id)) {|fv|
ebml_w.tag(c::tag_table_freevars) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
}
let lid = {crate: ast::local_crate, node: id};
- option::with_option_do(tcx.tcache.find(lid)) {|tpbt|
+ option::iter(tcx.tcache.find(lid)) {|tpbt|
ebml_w.tag(c::tag_table_tcache) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
}
}
- option::with_option_do(tcx.ty_param_bounds.find(id)) {|pbs|
+ option::iter(tcx.ty_param_bounds.find(id)) {|pbs|
ebml_w.tag(c::tag_table_param_bounds) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
// is what we actually use in trans, all modes will have been
// resolved.
//
- //option::with_option_do(tcx.inferred_modes.find(id)) {|m|
+ //option::iter(tcx.inferred_modes.find(id)) {|m|
// ebml_w.tag(c::tag_table_inferred_modes) {||
// ebml_w.id(id);
// ebml_w.tag(c::tag_table_val) {||
// }
//}
- option::with_option_do(ccx.maps.mutbl_map.find(id)) {|_m|
+ option::iter(ccx.maps.mutbl_map.find(id)) {|_m|
ebml_w.tag(c::tag_table_mutbl) {||
ebml_w.id(id);
}
}
- option::with_option_do(ccx.maps.copy_map.find(id)) {|_m|
+ option::iter(ccx.maps.copy_map.find(id)) {|_m|
ebml_w.tag(c::tag_table_copy) {||
ebml_w.id(id);
}
}
- option::with_option_do(ccx.maps.spill_map.find(id)) {|_m|
+ option::iter(ccx.maps.spill_map.find(id)) {|_m|
ebml_w.tag(c::tag_table_spill) {||
ebml_w.id(id);
}
}
- option::with_option_do(ccx.maps.last_uses.find(id)) {|m|
+ option::iter(ccx.maps.last_uses.find(id)) {|m|
ebml_w.tag(c::tag_table_last_use) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
// impl_map is not used except when emitting metadata,
// don't need to keep it.
- option::with_option_do(ccx.maps.method_map.find(id)) {|mo|
+ option::iter(ccx.maps.method_map.find(id)) {|mo|
ebml_w.tag(c::tag_table_method_map) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
}
}
- option::with_option_do(ccx.maps.vtable_map.find(id)) {|dr|
+ option::iter(ccx.maps.vtable_map.find(id)) {|dr|
ebml_w.tag(c::tag_table_vtable_map) {||
ebml_w.id(id);
ebml_w.tag(c::tag_table_val) {||
const tag_parent_item: uint = 0x29u;
+const tag_crate_dep_name: uint = 0x2au;
+const tag_crate_dep_hash: uint = 0x2bu;
+const tag_crate_dep_vers: uint = 0x2cu;
+
const tag_mod_impl: uint = 0x30u;
const tag_item_method: uint = 0x31u;
fn hash_path(&&s: str) -> uint {
let mut h = 5381u;
- for ch: u8 in str::bytes(s) { h = (h << 5u) + h ^ (ch as uint); }
+ for str::each(s) {|ch| h = (h << 5u) + h ^ (ch as uint); }
ret h;
}
// libraries necessary for later resolving, typechecking, linking, etc.
fn read_crates(sess: session::session, crate: ast::crate) {
let e = @{sess: sess,
- crate_cache: std::map::str_hash::<int>(),
+ mut crate_cache: [],
mut next_crate_num: 1};
let v =
visit::mk_simple_visitor(@{visit_view_item:
visit_item: bind visit_item(e, _)
with *visit::default_simple_visitor()});
visit::visit_crate(crate, (), v);
+ warn_if_multiple_versions(sess, copy e.crate_cache);
+}
+
+type cache_entry = {
+ cnum: int,
+ span: span,
+ hash: str,
+ metas: @[@ast::meta_item]
+};
+
+fn warn_if_multiple_versions(sess: session::session,
+ crate_cache: [cache_entry]) {
+ import either::*;
+
+ if crate_cache.is_not_empty() {
+ let name = crate_name_from_metas(*crate_cache.last().metas);
+ let {lefts: matches, rights: non_matches} =
+ partition(crate_cache.map {|entry|
+ let othername = crate_name_from_metas(*entry.metas);
+ if name == othername {
+ left(entry)
+ } else {
+ right(entry)
+ }
+ });
+
+ assert matches.is_not_empty();
+
+ if matches.len() != 1u {
+ sess.warn(#fmt("using multiple versions of crate `%s`", name));
+ for matches.each {|match|
+ sess.span_note(match.span, "used here");
+ let attrs = [
+ attr::mk_attr(attr::mk_list_item("link", *match.metas))
+ ];
+ note_linkage_attrs(sess, attrs);
+ }
+ }
+
+ warn_if_multiple_versions(sess, non_matches);
+ }
}
type env = @{sess: session::session,
- crate_cache: hashmap<str, int>,
+ mut crate_cache: [cache_entry],
mut next_crate_num: ast::crate_num};
fn visit_view_item(e: env, i: @ast::view_item) {
alt i.node {
ast::view_item_use(ident, meta_items, id) {
- let cnum = resolve_crate(e, ident, meta_items, i.span);
+ let cnum = resolve_crate(e, ident, meta_items, "", i.span);
cstore::add_use_stmt_cnum(e.sess.cstore, id, cnum);
}
_ { }
e.sess.span_fatal(i.span, "library '" + native_name +
"' already added: can't specify link_args.");
}
- for a: ast::attribute in link_args {
+ for link_args.each {|a|
alt attr::get_meta_item_value_str(attr::attr_meta(a)) {
some(linkarg) {
cstore::add_used_link_args(cstore, linkarg);
}
}
-fn metadata_matches(crate_data: @[u8], metas: [@ast::meta_item]) -> bool {
+fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
+ bool {
let attrs = decoder::get_crate_attributes(crate_data);
let linkage_metas = attr::find_linkage_metas(attrs);
+ if hash.is_not_empty() {
+ let chash = decoder::get_crate_hash(crate_data);
+ if chash != hash { ret false; }
+ }
+ metadata_matches(linkage_metas, metas)
+}
+
+fn metadata_matches(extern_metas: [@ast::meta_item],
+ local_metas: [@ast::meta_item]) -> bool {
#debug("matching %u metadata requirements against %u items",
- vec::len(metas), vec::len(linkage_metas));
+ vec::len(local_metas), vec::len(extern_metas));
#debug("crate metadata:");
- for have: @ast::meta_item in linkage_metas {
+ for extern_metas.each {|have|
#debug(" %s", pprust::meta_item_to_str(*have));
}
- for needed: @ast::meta_item in metas {
+ for local_metas.each {|needed|
#debug("looking for %s", pprust::meta_item_to_str(*needed));
- if !attr::contains(linkage_metas, needed) {
+ if !attr::contains(extern_metas, needed) {
#debug("missing %s", pprust::meta_item_to_str(*needed));
ret false;
}
}
}
-fn find_library_crate(sess: session::session, ident: ast::ident,
- metas: [@ast::meta_item])
+fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
+ let name_items = attr::find_meta_items_by_name(metas, "name");
+ alt vec::last_opt(name_items) {
+ some(i) {
+ alt attr::get_meta_item_value_str(i) {
+ some(n) { n }
+ // FIXME: Probably want a warning here since the user
+ // is using the wrong type of meta item
+ _ { fail }
+ }
+ }
+ none { fail "expected to find the crate name" }
+ }
+}
+
+fn find_library_crate(sess: session::session, span: span,
+ metas: [@ast::meta_item], hash: str)
-> option<{ident: str, data: @[u8]}> {
attr::require_unique_names(sess.diagnostic(), metas);
let metas = metas;
- let crate_name =
- {
- let name_items = attr::find_meta_items_by_name(metas, "name");
- alt vec::last_opt(name_items) {
- some(i) {
- alt attr::get_meta_item_value_str(i) {
- some(n) { n }
- // FIXME: Probably want a warning here since the user
- // is using the wrong type of meta item
- _ { ident }
- }
- }
- none { ident }
- }
- };
-
let nn = default_native_lib_naming(sess, sess.opts.static);
let x =
- find_library_crate_aux(sess, nn, crate_name,
- metas, sess.filesearch);
+ find_library_crate_aux(sess, span, nn,
+ metas, hash, sess.filesearch);
if x != none || sess.opts.static { ret x; }
let nn2 = default_native_lib_naming(sess, true);
- ret find_library_crate_aux(sess, nn2, crate_name, metas,
+ ret find_library_crate_aux(sess, span, nn2, metas, hash,
sess.filesearch);
}
fn find_library_crate_aux(sess: session::session,
+ span: span,
nn: {prefix: str, suffix: str},
- crate_name: str,
metas: [@ast::meta_item],
+ hash: str,
filesearch: filesearch::filesearch) ->
option<{ident: str, data: @[u8]}> {
+ let crate_name = crate_name_from_metas(metas);
let prefix: str = nn.prefix + crate_name + "-";
let suffix: str = nn.suffix;
- ret filesearch::search(filesearch, { |path|
+ let mut matches = [];
+ filesearch::search(filesearch, { |path|
#debug("inspecting file %s", path);
let f: str = path::basename(path);
if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
#debug("%s is a candidate", path);
alt get_metadata_section(sess, path) {
option::some(cvec) {
- if !metadata_matches(cvec, metas) {
+ if !crate_matches(cvec, metas, hash) {
#debug("skipping %s, metadata doesn't match", path);
option::none
} else {
#debug("found %s with matching metadata", path);
- option::some({ident: path, data: cvec})
+ matches += [{ident: path, data: cvec}];
+ option::none
}
}
_ {
}
}
});
+
+ if matches.is_empty() {
+ none
+ } else if matches.len() == 1u {
+ some(matches[0])
+ } else {
+ sess.span_err(
+ span, #fmt("multiple matching crates for `%s`", crate_name));
+ sess.note("candidates:");
+ for matches.each {|match|
+ sess.note(#fmt("path: %s", match.ident));
+ let attrs = decoder::get_crate_attributes(match.data);
+ note_linkage_attrs(sess, attrs);
+ }
+ sess.abort_if_errors();
+ none
+ }
+}
+
+fn note_linkage_attrs(sess: session::session, attrs: [ast::attribute]) {
+ for attr::find_linkage_attrs(attrs).each {|attr|
+ sess.note(#fmt("meta: %s", pprust::attr_to_str(attr)));
+ }
}
fn get_metadata_section(sess: session::session,
ret option::none::<@[u8]>;
}
-fn load_library_crate(sess: session::session, span: span, ident: ast::ident,
- metas: [@ast::meta_item])
+fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
+ metas: [@ast::meta_item], hash: str)
-> {ident: str, data: @[u8]} {
- alt find_library_crate(sess, ident, metas) {
+ alt find_library_crate(sess, span, metas, hash) {
some(t) { ret t; }
none {
sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
}
}
+fn metas_with(ident: ast::ident, key: str,
+ metas: [@ast::meta_item]) -> [@ast::meta_item] {
+ let name_items = attr::find_meta_items_by_name(metas, key);
+ if name_items.is_empty() {
+ metas + [attr::mk_name_value_item_str(key, ident)]
+ } else {
+ metas
+ }
+}
+
+fn metas_with_ident(ident: ast::ident,
+ metas: [@ast::meta_item]) -> [@ast::meta_item] {
+ metas_with(ident, "name", metas)
+}
+
+fn existing_match(e: env, metas: [@ast::meta_item], hash: str) ->
+ option<int> {
+ let maybe_entry = e.crate_cache.find {|c|
+ metadata_matches(*c.metas, metas) &&
+ (hash.is_empty() || c.hash == hash)
+ };
+
+ maybe_entry.map {|c| c.cnum }
+}
+
fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
- span: span) -> ast::crate_num {
- if !e.crate_cache.contains_key(ident) {
+ hash: str, span: span) -> ast::crate_num {
+ let metas = metas_with_ident(ident, metas);
+
+ alt existing_match(e, metas, hash) {
+ none {
let cinfo =
- load_library_crate(e.sess, span, ident, metas);
+ load_library_crate(e.sess, ident, span, metas, hash);
let cfilename = cinfo.ident;
let cdata = cinfo.data;
+ let attrs = decoder::get_crate_attributes(cdata);
+ let linkage_metas = attr::find_linkage_metas(attrs);
+ let hash = decoder::get_crate_hash(cdata);
+
// Claim this crate number and cache it
let cnum = e.next_crate_num;
- e.crate_cache.insert(ident, cnum);
+ e.crate_cache += [{cnum: cnum, span: span,
+ hash: hash, metas: @linkage_metas}];
e.next_crate_num += 1;
// Now resolve the crates referenced by this crate
let cnum_map = resolve_crate_deps(e, cdata);
- let cmeta = @{name: ident, data: cdata,
+ let cname = alt attr::meta_item_value_from_list(metas, "name") {
+ option::some(v) { v }
+ option::none { ident }
+ };
+ let cmeta = @{name: cname, data: cdata,
cnum_map: cnum_map, cnum: cnum};
let cstore = e.sess.cstore;
cstore::set_crate_data(cstore, cnum, cmeta);
cstore::add_used_crate_file(cstore, cfilename);
ret cnum;
- } else { ret e.crate_cache.get(ident); }
+ }
+ some(cnum) {
+ ret cnum;
+ }
+ }
}
// Go through the crate metadata and load any crates that it references
// The map from crate numbers in the crate we're resolving to local crate
// numbers
let cnum_map = int_hash::<ast::crate_num>();
- for dep: decoder::crate_dep in decoder::get_crate_deps(cdata) {
+ for decoder::get_crate_deps(cdata).each {|dep|
let extrn_cnum = dep.cnum;
- let cname = dep.ident;
- #debug("resolving dep %s", cname);
- if e.crate_cache.contains_key(cname) {
+ let cname = dep.name;
+ let cmetas = metas_with(dep.vers, "vers", []);
+ #debug("resolving dep crate %s ver: %s hash: %s",
+ dep.name, dep.vers, dep.hash);
+ alt existing_match(e, metas_with_ident(cname, cmetas), dep.hash) {
+ some(local_cnum) {
#debug("already have it");
// We've already seen this crate
- let local_cnum = e.crate_cache.get(cname);
cnum_map.insert(extrn_cnum, local_cnum);
- } else {
+ }
+ none {
#debug("need to load it");
// This is a new one so we've got to load it
// FIXME: Need better error reporting than just a bogus span
let fake_span = ast_util::dummy_sp();
- let local_cnum = resolve_crate(e, cname, [], fake_span);
+ let local_cnum =
+ resolve_crate(e, cname, cmetas, dep.hash, fake_span);
cnum_map.insert(extrn_cnum, local_cnum);
+ }
}
}
ret cnum_map;
path: [ast::ident]) -> [ast::def] {
let mut result = [];
#debug("lookup_defs: path = %? cnum = %?", path, cnum);
- for (c, data, def) in resolve_path(cstore, cnum, path) {
+ for resolve_path(cstore, cnum, path).each {|elt|
+ let (c, data, def) = elt;
result += [decoder::lookup_def(c, data, def)];
}
ret result;
#debug("resolve_path %s in crates[%d]:%s",
str::connect(path, "::"), cnum, cm.name);
let mut result = [];
- for def in decoder::resolve_path(path, cm.data) {
+ for decoder::resolve_path(path, cm.data).each {|def|
if def.crate == ast::local_crate {
result += [(cnum, cm.data, def)];
} else {
import std::map;
import std::map::hashmap;
-import syntax::ast;
+import syntax::{ast, attr};
import util::common::*;
export cstore::{};
export mk_cstore;
export get_crate_data;
export set_crate_data;
+export get_crate_hash;
+export get_crate_vers;
export have_crate_data;
export iter_crate_data;
export add_used_crate_file;
ret p(cstore).metas.get(cnum);
}
+fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> str {
+ let cdata = get_crate_data(cstore, cnum);
+ ret decoder::get_crate_hash(cdata.data);
+}
+
+fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> str {
+ let cdata = get_crate_data(cstore, cnum);
+ ret decoder::get_crate_vers(cdata.data);
+}
+
fn set_crate_data(cstore: cstore, cnum: ast::crate_num,
data: crate_metadata) {
p(cstore).metas.insert(cnum, data);
}
let sorted = std::sort::merge_sort(lteq, result);
#debug("sorted:");
- for x in sorted {
+ for sorted.each {|x|
#debug(" hash[%s]: %s", x.name, x.hash);
}
fn mapper(ch: crate_hash) -> str { ret ch.hash; }
fn get_path(cstore: cstore, d: ast::def_id) -> [str] {
// let f = bind str::split_str(_, "::");
- option::with_option(p(cstore).mod_path_map.find(d), [],
+ option::map_default(p(cstore).mod_path_map.find(d), [],
{|ds| str::split_str(ds, "::")})
}
// Local Variables:
export crate_dep;
export get_crate_deps;
export get_crate_hash;
+export get_crate_vers;
export get_impls_for_mod;
export get_iface_methods;
export get_crate_module_paths;
fn field_mutability(d: ebml::doc) -> ast::class_mutability {
// Use maybe_get_doc in case it's a method
- option::with_option(ebml::maybe_get_doc(d, tag_class_mut),
+ option::map_default(ebml::maybe_get_doc(d, tag_class_mut),
ast::class_immutable,
{|d|
alt ebml::doc_as_u8(d) as char {
let eqer = bind eq_item(_, s);
let mut result: [ast::def_id] = [];
#debug("resolve_path: looking up %s", s);
- for doc: ebml::doc in lookup_hash(paths, eqer, hash_path(s)) {
+ for lookup_hash(paths, eqer, hash_path(s)).each {|doc|
let did_doc = ebml::get_doc(doc, tag_def_id);
result += [parse_def_id(ebml::doc_data(did_doc))];
}
let mut infos: [ty::variant_info] = [];
let variant_ids = enum_variant_ids(item, cdata);
let mut disr_val = 0;
- for did: ast::def_id in variant_ids {
+ for variant_ids.each {|did|
let item = find_item(did.node, items);
let ctor_ty = item_type({crate: cdata.cnum, node: id}, item,
tcx, cdata);
let mut arg_tys: [ty::t] = [];
alt ty::get(ctor_ty).struct {
ty::ty_fn(f) {
- for a: ty::arg in f.inputs { arg_tys += [a.ty]; }
+ for f.inputs.each {|a| arg_tys += [a.ty]; }
}
_ { /* Nullary enum variant. */ }
}
}
fn list_meta_items(meta_items: ebml::doc, out: io::writer) {
- for mi: @ast::meta_item in get_meta_items(meta_items) {
+ for get_meta_items(meta_items).each {|mi|
out.write_str(#fmt["%s\n", pprust::meta_item_to_str(*mi)]);
}
}
fn list_crate_attributes(md: ebml::doc, hash: str, out: io::writer) {
out.write_str(#fmt("=Crate Attributes (%s)=\n", hash));
- for attr: ast::attribute in get_attributes(md) {
+ for get_attributes(md).each {|attr|
out.write_str(#fmt["%s\n", pprust::attribute_to_str(attr)]);
}
ret get_attributes(ebml::doc(data));
}
-type crate_dep = {cnum: ast::crate_num, ident: str};
+type crate_dep = {cnum: ast::crate_num, name: ast::ident,
+ vers: str, hash: str};
fn get_crate_deps(data: @[u8]) -> [crate_dep] {
let mut deps: [crate_dep] = [];
let cratedoc = ebml::doc(data);
let depsdoc = ebml::get_doc(cratedoc, tag_crate_deps);
let mut crate_num = 1;
+ fn docstr(doc: ebml::doc, tag_: uint) -> str {
+ str::from_bytes(ebml::doc_data(ebml::get_doc(doc, tag_)))
+ }
ebml::tagged_docs(depsdoc, tag_crate_dep) {|depdoc|
- let depname = str::from_bytes(ebml::doc_data(depdoc));
- deps += [{cnum: crate_num, ident: depname}];
+ deps += [{cnum: crate_num,
+ name: docstr(depdoc, tag_crate_dep_name),
+ vers: docstr(depdoc, tag_crate_dep_vers),
+ hash: docstr(depdoc, tag_crate_dep_hash)}];
crate_num += 1;
};
ret deps;
fn list_crate_deps(data: @[u8], out: io::writer) {
out.write_str("=External Dependencies=\n");
- for dep: crate_dep in get_crate_deps(data) {
- out.write_str(#fmt["%d %s\n", dep.cnum, dep.ident]);
+ for get_crate_deps(data).each {|dep|
+ out.write_str(#fmt["%d %s-%s-%s\n",
+ dep.cnum, dep.name, dep.hash, dep.vers]);
}
out.write_str("\n");
ret str::from_bytes(ebml::doc_data(hashdoc));
}
+fn get_crate_vers(data: @[u8]) -> str {
+ let attrs = decoder::get_crate_attributes(data);
+ ret alt attr::meta_item_value_from_list(
+ attr::find_linkage_metas(attrs), "vers") {
+ some(ver) { ver }
+ none { "0.0" }
+ };
+}
+
fn list_crate_items(bytes: @[u8], md: ebml::doc, out: io::writer) {
out.write_str("=Items=\n");
let items = ebml::get_doc(md, tag_items);
fn encode_enum_variant_paths(ebml_w: ebml::writer, variants: [variant],
path: [str], &index: [entry<str>]) {
- for variant: variant in variants {
+ for variants.each {|variant|
add_to_index(ebml_w, path, index, variant.node.name);
ebml_w.wr_tag(tag_paths_data_item) {||
encode_name(ebml_w, variant.node.name);
fn encode_native_module_item_paths(ebml_w: ebml::writer, nmod: native_mod,
path: [str], &index: [entry<str>]) {
- for nitem: @native_item in nmod.items {
+ for nmod.items.each {|nitem|
add_to_index(ebml_w, path, index, nitem.ident);
encode_named_def_id(ebml_w, nitem.ident, local_def(nitem.id));
}
fn encode_class_item_paths(ebml_w: ebml::writer,
items: [@class_member], path: [str], &index: [entry<str>]) {
- for it in items {
+ for items.each {|it|
alt ast_util::class_member_privacy(it) {
priv { cont; }
pub {
fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
module: _mod, path: [str], &index: [entry<str>]) {
// FIXME factor out add_to_index/start/encode_name/encode_def_id/end ops
- for it: @item in module.items {
+ for module.items.each {|it|
if !ecx.ccx.reachable.contains_key(it.id) ||
!ast_util::is_exported(it.ident, module) { cont; }
alt it.node {
ecx: @encode_ctxt, &index: [entry<str>]) {
let tcx = ecx.ccx.tcx;
ecx.ccx.exp_map.items {|exp_id, defs|
- for def in defs {
+ for defs.each {|def|
if !def.reexp { cont; }
let path = alt check tcx.items.get(exp_id) {
ast_map::node_export(_, path) { ast_map::path_to_str(*path) }
tcx: ecx.ccx.tcx,
reachable: ecx.ccx.reachable,
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
- for param in params {
+ for params.each {|param|
ebml_w.start_tag(tag_items_data_item_ty_param_bounds);
let bs = ecx.ccx.tcx.ty_param_bounds.get(param.id);
tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, bs);
let mut disr_val = 0;
let mut i = 0;
let vi = ty::enum_variants(ecx.ccx.tcx, {crate: local_crate, node: id});
- for variant: variant in variants {
+ for variants.each {|variant|
*index += [{val: variant.node.id, pos: ebml_w.writer.tell()}];
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(variant.node.id));
encode_name(ebml_w, name);
alt ecx.ccx.maps.impl_map.get(id) {
list::cons(impls, @list::nil) {
- for i in *impls {
+ for vec::each(*impls) {|i|
if ast_util::is_exported(i.ident, md) {
ebml_w.wr_tagged_str(tag_mod_impl, def_to_str(i.did));
}
-> [entry<int>] {
let index = @mut [];
let tcx = ecx.ccx.tcx;
- for ci in items {
+ for items.each {|ci|
/* We encode both private and public fields -- need to include
private fields to get the offsets right */
alt ci.node {
}
}
}
- }
+ };
*index
}
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
- for v: variant in variants {
+ for variants.each {|v|
encode_variant_id(ebml_w, local_def(v.node.id));
}
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
for methods, write all the stuff get_iface_method
needs to know*/
let (fs,ms) = ast_util::split_class_items(items);
- for f in fs {
+ for fs.each {|f|
ebml_w.start_tag(tag_item_field);
encode_privacy(ebml_w, f.privacy);
encode_name(ebml_w, f.ident);
encode_def_id(ebml_w, local_def(f.id));
ebml_w.end_tag();
}
- for m in ms {
+ for ms.each {|m|
alt m.privacy {
priv { /* do nothing */ }
pub {
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
- for m in methods {
+ for methods.each {|m|
ebml_w.start_tag(tag_item_method);
ebml_w.writer.write(str::bytes(def_to_str(local_def(m.id))));
ebml_w.end_tag();
ebml_w.end_tag();
let impl_path = path + [ast_map::path_name(item.ident)];
- for m in methods {
+ for methods.each {|m|
*index += [{val: m.id, pos: ebml_w.writer.tell()}];
encode_info_for_method(ecx, ebml_w, impl_path,
should_inline(m.attrs), item.id, m, tps + m.tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
let mut i = 0u;
- for mty in *ty::iface_methods(tcx, local_def(item.id)) {
+ for vec::each(*ty::iface_methods(tcx, local_def(item.id))) {|mty|
ebml_w.start_tag(tag_item_method);
encode_name(ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx, ms[i].tps);
[@[entry<T>]] {
let mut buckets: [@mut [entry<T>]] = [];
uint::range(0u, 256u) {|_i| buckets += [@mut []]; };
- for elt: entry<T> in index {
+ for index.each {|elt|
let h = hash_fn(elt.val);
*buckets[h % 256u] += [elt];
}
let mut buckets_frozen = [];
- for bucket: @mut [entry<T>] in buckets {
+ for buckets.each {|bucket|
buckets_frozen += [@*bucket];
}
ret buckets_frozen;
ebml_w.start_tag(tag_index);
let mut bucket_locs: [uint] = [];
ebml_w.start_tag(tag_index_buckets);
- for bucket: @[entry<T>] in buckets {
+ for buckets.each {|bucket|
bucket_locs += [ebml_w.writer.tell()];
ebml_w.start_tag(tag_index_buckets_bucket);
- for elt: entry<T> in *bucket {
+ for vec::each(*bucket) {|elt|
ebml_w.start_tag(tag_index_buckets_bucket_elt);
writer.write_be_uint(elt.pos, 4u);
write_fn(writer, elt.val);
}
ebml_w.end_tag();
ebml_w.start_tag(tag_index_table);
- for pos: uint in bucket_locs { writer.write_be_uint(pos, 4u); }
+ for bucket_locs.each {|pos| writer.write_be_uint(pos, 4u); }
ebml_w.end_tag();
ebml_w.end_tag();
}
ebml_w.start_tag(tag_meta_item_name);
ebml_w.writer.write(str::bytes(name));
ebml_w.end_tag();
- for inner_item: @meta_item in items {
+ for items.each {|inner_item|
encode_meta_item(ebml_w, *inner_item);
}
ebml_w.end_tag();
fn encode_attributes(ebml_w: ebml::writer, attrs: [attribute]) {
ebml_w.start_tag(tag_attributes);
- for attr: attribute in attrs {
+ for attrs.each {|attr|
ebml_w.start_tag(tag_attribute);
encode_meta_item(ebml_w, attr.node.value);
ebml_w.end_tag();
let mut attrs: [attribute] = [];
let mut found_link_attr = false;
- for attr: attribute in crate.node.attrs {
+ for crate.node.attrs.each {|attr|
attrs +=
if attr::get_attr_name(attr) != "link" {
[attr]
fn encode_crate_deps(ebml_w: ebml::writer, cstore: cstore::cstore) {
- fn get_ordered_names(cstore: cstore::cstore) -> [str] {
+ fn get_ordered_deps(cstore: cstore::cstore) -> [decoder::crate_dep] {
type hashkv = @{key: crate_num, val: cstore::crate_metadata};
- type numname = {crate: crate_num, ident: str};
+ type numdep = decoder::crate_dep;
- // Pull the cnums and names out of cstore
- let mut pairs: [mut numname] = [mut];
+ // Pull the cnums and name,vers,hash out of cstore
+ let mut deps: [mut numdep] = [mut];
cstore::iter_crate_data(cstore) {|key, val|
- pairs += [mut {crate: key, ident: val.name}];
+ let dep = {cnum: key, name: val.name,
+ vers: decoder::get_crate_vers(val.data),
+ hash: decoder::get_crate_hash(val.data)};
+ deps += [mut dep];
};
// Sort by cnum
- fn lteq(kv1: numname, kv2: numname) -> bool { kv1.crate <= kv2.crate }
- std::sort::quick_sort(lteq, pairs);
+ fn lteq(kv1: numdep, kv2: numdep) -> bool { kv1.cnum <= kv2.cnum }
+ std::sort::quick_sort(lteq, deps);
// Sanity-check the crate numbers
let mut expected_cnum = 1;
- for n: numname in pairs {
- assert (n.crate == expected_cnum);
+ for deps.each {|n|
+ assert (n.cnum == expected_cnum);
expected_cnum += 1;
}
- // Return just the names
- fn name(kv: numname) -> str { kv.ident }
// mut -> immutable hack for vec::map
- let immpairs = vec::slice(pairs, 0u, vec::len(pairs));
- ret vec::map(immpairs, name);
+ ret vec::slice(deps, 0u, vec::len(deps));
}
- // We're just going to write a list of crate names, with the assumption
- // that they are numbered 1 to n.
+ // We're just going to write a list of crate 'name-hash-version's, with
+ // the assumption that they are numbered 1 to n.
// FIXME: This is not nearly enough to support correct versioning
// but is enough to get transitive crate dependencies working.
ebml_w.start_tag(tag_crate_deps);
- for cname: str in get_ordered_names(cstore) {
- ebml_w.start_tag(tag_crate_dep);
- ebml_w.writer.write(str::bytes(cname));
- ebml_w.end_tag();
+ for get_ordered_deps(cstore).each {|dep|
+ encode_crate_dep(ebml_w, dep);
}
ebml_w.end_tag();
}
+fn encode_crate_dep(ebml_w: ebml::writer, dep: decoder::crate_dep) {
+ ebml_w.start_tag(tag_crate_dep);
+ ebml_w.start_tag(tag_crate_dep_name);
+ ebml_w.writer.write(str::bytes(dep.name));
+ ebml_w.end_tag();
+ ebml_w.start_tag(tag_crate_dep_vers);
+ ebml_w.writer.write(str::bytes(dep.vers));
+ ebml_w.end_tag();
+ ebml_w.start_tag(tag_crate_dep_hash);
+ ebml_w.writer.write(str::bytes(dep.hash));
+ ebml_w.end_tag();
+ ebml_w.end_tag();
+}
+
fn encode_hash(ebml_w: ebml::writer, hash: str) {
ebml_w.start_tag(tag_crate_hash);
ebml_w.writer.write(str::bytes(hash));
#error("didn't find ':' when parsing def id");
fail;
}
- let crate_part = vec::slice::<u8>(buf, 0u, colon_idx);
- let def_part = vec::slice::<u8>(buf, colon_idx + 1u, len);
+ let crate_part = vec::slice(buf, 0u, colon_idx);
+ let def_part = vec::slice(buf, colon_idx + 1u, len);
- let mut crate_part_vec = [];
- let mut def_part_vec = [];
- for b: u8 in crate_part { crate_part_vec += [b]; }
- for b: u8 in def_part { def_part_vec += [b]; }
-
- let crate_num = alt uint::parse_buf(crate_part_vec, 10u) {
+ let crate_num = alt uint::parse_buf(crate_part, 10u) {
some(cn) { cn as int }
none { fail (#fmt("internal error: parse_def_id: error parsing %? \
as crate",
- crate_part_vec)); }
+ crate_part)); }
};
- let def_num = alt uint::parse_buf(def_part_vec, 10u) {
+ let def_num = alt uint::parse_buf(def_part, 10u) {
some(dn) { dn as int }
none { fail (#fmt("internal error: parse_def_id: error parsing %? \
as id",
- def_part_vec)); }
+ def_part)); }
};
ret {crate: crate_num, node: def_num};
}
w.write_uint(id.to_uint());
w.write_char('|');
}
+ ty::re_static {
+ w.write_char('t');
+ }
}
}
fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_str("t[");
w.write_str(cx.ds(def));
w.write_char('|');
- for t: ty::t in tys { enc_ty(w, cx, t); }
+ for tys.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_iface(def, tys) {
w.write_str("x[");
w.write_str(cx.ds(def));
w.write_char('|');
- for t: ty::t in tys { enc_ty(w, cx, t); }
+ for tys.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_tup(ts) {
w.write_str("T[");
- for t in ts { enc_ty(w, cx, t); }
+ for ts.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_box(mt) { w.write_char('@'); enc_mt(w, cx, mt); }
ty::ty_vec(mt) { w.write_char('I'); enc_mt(w, cx, mt); }
ty::ty_rec(fields) {
w.write_str("R[");
- for field: ty::field in fields {
+ for fields.each {|field|
w.write_str(field.ident);
w.write_char('=');
enc_mt(w, cx, field.mt);
w.write_str(cx.ds(def));
w.write_char('|');
enc_ty(w, cx, ty);
- for t: ty::t in tps { enc_ty(w, cx, t); }
+ for tps.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_var(id) {
}
ty::ty_self(tps) {
w.write_str("s[");
- for t in tps { enc_ty(w, cx, t); }
+ for tps.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_type { w.write_char('Y'); }
ty::ty_constr(ty, cs) {
w.write_str("A[");
enc_ty(w, cx, ty);
- for tc: @ty::type_constr in cs { enc_ty_constr(w, cx, tc); }
+ for cs.each {|tc| enc_ty_constr(w, cx, tc); }
w.write_char(']');
}
ty::ty_opaque_box { w.write_char('B'); }
w.write_str(s);
#debug("~~~~ %s", "|");
w.write_str("|");
- for t: ty::t in tys { enc_ty(w, cx, t); }
+ for tys.each {|t| enc_ty(w, cx, t); }
#debug("~~~~ %s", "]");
w.write_char(']');
}
fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
w.write_char('[');
- for arg: ty::arg in ft.inputs {
+ for ft.inputs.each {|arg|
enc_mode(w, cx, arg.mode);
enc_ty(w, cx, arg.ty);
}
w.write_char(']');
let mut colon = true;
- for c: @ty::constr in ft.constraints {
+ for ft.constraints.each {|c|
if colon {
w.write_char(':');
colon = false;
w.write_str(cx.ds(c.node.id));
w.write_char('|');
let mut semi = false;
- for a: @constr_arg in c.node.args {
+ for c.node.args.each {|a|
if semi { w.write_char(';'); } else { semi = true; }
alt a.node {
carg_base { w.write_char('*'); }
w.write_str(cx.ds(c.node.id));
w.write_char('|');
let mut semi = false;
- for a: @ty::ty_constr_arg in c.node.args {
+ for c.node.args.each {|a|
if semi { w.write_char(';'); } else { semi = true; }
alt a.node {
carg_base { w.write_char('*'); }
}
fn enc_bounds(w: io::writer, cx: @ctxt, bs: @[ty::param_bound]) {
- for bound in *bs {
+ for vec::each(*bs) {|bound|
alt bound {
ty::bound_send { w.write_char('S'); }
ty::bound_copy { w.write_char('C'); }
visit_expr(cx, f, sc, v);
}
ast::expr_alt(input, arms, _) { check_alt(*cx, input, arms, sc, v); }
- ast::expr_for(decl, seq, blk) {
- visit_expr(cx, seq, sc, v);
- check_loop(*cx, sc) {|| check_for(*cx, decl, seq, blk, sc, v); }
- }
ast::expr_path(pt) {
check_var(*cx, ex, pt, ex.id, false, sc);
handled = false;
fn visit_block(cx: @ctx, b: ast::blk, sc: scope, v: vt<scope>) {
let sc = sc;
- for stmt in b.node.stmts {
+ for b.node.stmts.each {|stmt|
alt stmt.node {
ast::stmt_decl(@{node: ast::decl_item(it), _}, _) {
v.visit_item(it, sc, v);
}
ast::stmt_decl(@{node: ast::decl_local(locs), _}, _) {
- for loc in locs {
+ for locs.each {|loc|
alt loc.node.init {
some(init) {
if init.op == ast::init_move {
};
if f_may_close {
let mut i = 0u;
- for b in bindings {
+ for bindings.each {|b|
let mut unsfe = vec::len(b.unsafe_tys) > 0u;
alt b.root_var {
some(rid) {
- for o in sc.bs {
+ for sc.bs.each {|o|
if o.node_id == rid && vec::len(o.unsafe_tys) > 0u {
unsfe = true; break;
}
}
}
let mut j = 0u;
- for b in bindings {
- for unsafe_ty in b.unsafe_tys {
+ for bindings.each {|b|
+ for b.unsafe_tys.each {|unsafe_ty|
vec::iteri(arg_ts) {|i, arg_t|
let mut_alias =
(ast::by_mutbl_ref == ty::arg_mode(cx.tcx, arg_t));
}
// Ensure we're not passing a root by mut alias.
- for {node: node, arg: arg} in mut_roots {
- for b in bindings {
- if b.node_id != arg.id {
+ for mut_roots.each {|mroot|
+ for bindings.each {|b|
+ if b.node_id != mroot.arg.id {
alt b.root_var {
some(root) {
- if node == root && cant_copy(*cx, b) {
- err(*cx, arg.span,
+ if mroot.node == root && cant_copy(*cx, b) {
+ err(*cx, mroot.arg.span,
"passing a mut reference to a \
variable that roots another reference");
break;
// Check the bodies of block arguments against the current scope
if blocks.len() > 0u {
let inner_sc = {bs: bindings + sc.bs, invalid: sc.invalid};
- for blk in blocks {
+ for blocks.each {|blk|
alt check blk.node {
ast::expr_fn_block(_, body) {
v.visit_block(body, inner_sc, v);
}
}
}
- for binding in bindings {
+ for bindings.each {|binding|
test_scope(*cx, sc, binding, none);
}
}
let orig_invalid = *sc.invalid;
let mut all_invalid = orig_invalid;
let root = expr_root(cx, input, true);
- for a: ast::arm in arms {
+ for arms.each {|a|
let mut new_bs = sc.bs;
let root_var = path_def_id(cx, root.ex);
let pat_id_map = pat_util::pat_id_map(cx.tcx.def_map, a.pats[0]);
mut unsafe_tys: [unsafe_ty],
span: span};
let mut binding_info: [info] = [];
- for pat in a.pats {
- for proot in pattern_roots(cx.tcx, root.mutbl, pat) {
+ for a.pats.each {|pat|
+ for pattern_roots(cx.tcx, root.mutbl, pat).each {|proot|
let canon_id = pat_id_map.get(proot.name);
alt vec::find(binding_info, {|x| x.id == canon_id}) {
some(s) { s.unsafe_tys += unsafe_set(proot.mutbl); }
}
}
}
- for info in binding_info {
+ for binding_info.each {|info|
new_bs += [mk_binding(cx, info.id, info.span, root_var,
copy info.unsafe_tys)];
- }
+ };
*sc.invalid = orig_invalid;
visit::visit_arm(a, {bs: new_bs with sc}, v);
all_invalid = join_invalid(all_invalid, *sc.invalid);
- }
+ };
*sc.invalid = all_invalid;
}
}
let root_var = path_def_id(cx, root.ex);
let mut new_bs = sc.bs;
- for proot in pattern_roots(cx.tcx, cur_mutbl, local.node.pat) {
+ for pattern_roots(cx.tcx, cur_mutbl, local.node.pat).each {|proot|
new_bs += [mk_binding(cx, proot.id, proot.span, root_var,
unsafe_set(proot.mutbl))];
}
let my_defnum = ast_util::def_id_of_def(def).node;
let my_local_id = local_id_of_node(cx, my_defnum);
let var_t = ty::expr_ty(cx.tcx, ex);
- for b in sc.bs {
+ for sc.bs.each {|b|
// excludes variables introduced since the alias was made
if my_local_id < b.local_id {
- for unsafe_ty in b.unsafe_tys {
+ for b.unsafe_tys.each {|unsafe_ty|
if ty_can_unsafely_include(cx, unsafe_ty, var_t, assign) {
let inv = @{reason: val_taken, node_id: b.node_id,
sp: ex.span, path: p};
ast::expr_path(p) {
let def = cx.tcx.def_map.get(dest.id);
let dnum = ast_util::def_id_of_def(def).node;
- for b in sc.bs {
+ for sc.bs.each {|b|
if b.root_var == some(dnum) {
let inv = @{reason: overwritten, node_id: b.node_id,
sp: dest.span, path: p};
let mut prob = find_invalid(b.node_id, *sc.invalid);
alt b.root_var {
some(dn) {
- for other in sc.bs {
+ for sc.bs.each {|other|
if !is_none(prob) { break; }
if other.node_id == dn {
prob = find_invalid(other.node_id, *sc.invalid);
} { ret true; }
alt ty::get(haystack).struct {
ty::ty_enum(_, ts) {
- for t: ty::t in ts {
+ for ts.each {|t|
if helper(tcx, needle, t, mutbl) { ret true; }
}
ret false;
ret helper(tcx, needle, mt.ty, get_mutbl(mutbl, mt));
}
ty::ty_rec(fields) {
- for f: ty::field in fields {
+ for fields.each {|f|
if helper(tcx, needle, f.mt.ty, get_mutbl(mutbl, f.mt)) {
ret true;
}
ret false;
}
ty::ty_tup(ts) {
- for t in ts { if helper(tcx, needle, t, mutbl) { ret true; } }
+ for ts.each {|t| if helper(tcx, needle, t, mutbl) { ret true; } }
ret false;
}
ty::ty_fn({proto: ast::proto_bare, _}) { ret false; }
ty::ty_uniq(mt) { 1u + score_ty(tcx, mt.ty) }
ty::ty_enum(_, ts) | ty::ty_tup(ts) {
let mut sum = 0u;
- for t in ts { sum += score_ty(tcx, t); }
+ for ts.each {|t| sum += score_ty(tcx, t); }
sum
}
ty::ty_rec(fs) {
let mut sum = 0u;
- for f in fs { sum += score_ty(tcx, f.mt.ty); }
+ for fs.each {|f| sum += score_ty(tcx, f.mt.ty); }
sum
}
_ {
ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) |
ast::pat_ident(_, _) {}
ast::pat_enum(_, ps) | ast::pat_tup(ps) {
- for p in ps { walk(tcx, mutbl, p, set); }
+ for ps.each {|p| walk(tcx, mutbl, p, set); }
}
ast::pat_rec(fs, _) {
let ty = ty::node_id_to_type(tcx, pat.id);
- for f in fs {
+ for fs.each {|f|
let m = ty::get_field(ty, f.ident).mt.mutbl != ast::m_imm,
c = if m { some(contains(ty)) } else { mutbl };
walk(tcx, c, f.pat, set);
-> {ex: @ast::expr, mutbl: option<unsafe_ty>} {
let base_root = mutbl::expr_root_(cx.tcx, none, ex, autoderef);
let mut unsafe_ty = none;
- for d in *base_root.ds {
+ for vec::each(*base_root.ds) {|d|
if d.mutbl { unsafe_ty = some(contains(d.outer_t)); break; }
}
ret {ex: base_root.ex, mutbl: unsafe_ty};
fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
sp: codemap::span, id: node_id, cx: ctx, v: vt) {
- for a in decl.inputs {
+ for decl.inputs.each {|a|
cx.map.insert(a.id, node_arg(a, cx.local_id));
cx.local_id += 1u;
}
alt i.node {
item_impl(_, _, _, ms) {
let impl_did = ast_util::local_def(i.id);
- for m in ms {
+ for ms.each {|m|
map_method(impl_did, extend(cx, i.ident), m, cx);
}
}
cx.map.insert(dtor_id, node_item(i, item_path));
}
item_enum(vs, _) {
- for v in vs {
+ for vs.each {|v|
cx.map.insert(v.node.id, node_variant(
v, i, extend(cx, i.ident)));
}
either::left(msg) { cx.sess.span_fatal(i.span, msg); }
either::right(abi) { abi }
};
- for nitem in nm.items {
+ for nm.items.each {|nitem|
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
}
}
cx.map.insert(ctor.node.id, node_ctor(i, item_path));
let d_id = ast_util::local_def(i.id);
let p = extend(cx, i.ident);
- for ci in items {
+ for items.each {|ci|
// only need to handle methods
alt ci.node {
class_method(m) { map_method(d_id, p, m, cx); }
fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
alt vi.node {
view_item_export(vps) {
- for vp in vps {
+ for vps.each {|vp|
let (id, name) = alt vp.node {
view_path_simple(nm, _, id) { (id, nm) }
view_path_glob(pth, id) | view_path_list(pth, _, id) {
cx.allow_block = true;
v.visit_expr(f, cx, v);
let mut i = 0u;
- for arg_t in ty::ty_fn_args(ty::expr_ty(cx.tcx, f)) {
+ for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each {|arg_t|
cx.allow_block = (ty::arg_mode(cx.tcx, arg_t) == by_ref);
v.visit_expr(args[i], cx, v);
i += 1u;
fn check_arms(tcx: ty::ctxt, arms: [arm]) {
let mut i = 0;
/* Check for unreachable patterns */
- for arm: arm in arms {
- for arm_pat: @pat in arm.pats {
+ for arms.each {|arm|
+ for arm.pats.each {|arm_pat|
let mut reachable = true;
let mut j = 0;
while j < i {
if option::is_none(arms[j].guard) {
- for prev_pat: @pat in arms[j].pats {
+ for vec::each(arms[j].pats) {|prev_pat|
if pattern_supersedes(tcx, prev_pat, arm_pat) {
reachable = false;
}
ret;
}
// If there a non-refutable pattern in the set, we're okay.
- for pat in pats { if !is_refutable(tcx, pat) { ret; } }
+ for pats.each {|pat| if !is_refutable(tcx, pat) { ret; } }
alt ty::get(ty::node_id_to_type(tcx, pats[0].id)).struct {
ty::ty_enum(id, _) {
}
ty::ty_tup(ts) {
let cols = vec::to_mut(vec::from_elem(ts.len(), []));
- for p in pats {
+ for pats.each {|p|
alt raw_pat(p).node {
pat_tup(sub) {
vec::iteri(sub) {|i, sp| cols[i] += [sp];}
ty::ty_rec(fs) {
let cols = vec::from_elem(fs.len(), {mut wild: false,
mut pats: []});
- for p in pats {
+ for pats.each {|p|
alt raw_pat(p).node {
pat_rec(sub, _) {
vec::iteri(fs) {|i, field|
}
ty::ty_bool {
let mut saw_true = false, saw_false = false;
- for p in pats {
+ for pats.each {|p|
alt raw_pat(p).node {
pat_lit(@{node: expr_lit(@{node: lit_bool(b), _}), _}) {
if b { saw_true = true; }
cols: vec::to_mut(vec::from_elem(v.args.len(), []))}
});
- for pat in pats {
+ for pats.each {|pat|
let pat = raw_pat(pat);
alt tcx.def_map.get(pat.id) {
def_variant(_, id) {
fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
fn patterns_supersede(tcx: ty::ctxt, as: [@pat], bs: [@pat]) -> bool {
let mut i = 0;
- for a: @pat in as {
+ for as.each {|a|
if !pattern_supersedes(tcx, a, bs[i]) { ret false; }
i += 1;
}
fn field_patterns_supersede(tcx: ty::ctxt, fas: [field_pat],
fbs: [field_pat]) -> bool {
let wild = @{id: 0, node: pat_wild, span: dummy_sp()};
- for fa: field_pat in fas {
+ for fas.each {|fa|
let mut pb = wild;
- for fb: field_pat in fbs {
+ for fbs.each {|fb|
if fa.ident == fb.ident { pb = fb.pat; }
}
if !pattern_supersedes(tcx, fa.pat, pb) { ret false; }
pat_wild | pat_ident(_, none) { false }
pat_lit(_) | pat_range(_, _) { true }
pat_rec(fields, _) {
- for it: field_pat in fields {
+ for fields.each {|it|
if is_refutable(tcx, it.pat) { ret true; }
}
false
}
pat_tup(elts) {
- for elt in elts { if is_refutable(tcx, elt) { ret true; } }
+ for elts.each {|elt| if is_refutable(tcx, elt) { ret true; } }
false
}
pat_enum(_, args) {
- for p: @pat in args { if is_refutable(tcx, p) { ret true; } }
+ for args.each {|p| if is_refutable(tcx, p) { ret true; } }
false
}
}
check_item_recursion(sess, ast_map, def_map, it);
}
item_enum(vs, _) {
- for var in vs {
- option::with_option_do(var.node.disr_expr) {|ex|
+ for vs.each {|var|
+ option::iter(var.node.disr_expr) {|ex|
v.visit_expr(ex, true, v);
}
}
},
visit_expr: {|e: @expr, cx: ctx, v: visit::vt<ctx>|
alt e.node {
- expr_for(_, e, b) | expr_while(e, b) | expr_do_while(b, e) {
+ expr_while(e, b) | expr_do_while(b, e) {
v.visit_expr(e, cx, v);
v.visit_block(b, {in_loop: true with cx}, v);
}
let args_ctx = {unsafe_fn_legal: false,
generic_bare_fn_legal: false with ctx};
- for arg in args {
+ for args.each {|arg|
visit::visit_expr_opt(arg, args_ctx, v);
}
}
import result::{result, extensions, ok, err, map, map2, iter2};
import ty::type_is_bot;
import driver::session::session;
+import util::common::{indent, indenter};
export infer_ctxt;
export new_infer_ctxt;
}
fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
- #debug[">> mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
- cx.commit {||
- cx.tys(a, b)
- }
+ #debug["mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
+ indent {|| cx.commit {|| sub(cx).tys(a, b) } }.to_ures()
}
fn mk_eqty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
- #debug[">> mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
- cx.commit {||
- cx.eq_tys(a, b)
- }
+ #debug["mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
+ indent {|| cx.commit {|| cx.eq_tys(a, b) } }.to_ures()
}
fn compare_tys(tcx: ty::ctxt, a: ty::t, b: ty::t) -> ures {
let infcx = new_infer_ctxt(tcx);
- #debug[">> compare_tys(%s == %s)", a.to_str(infcx), b.to_str(infcx)];
- infcx.commit {||
- mk_subty(infcx, a, b).then {||
- mk_subty(infcx, b, a)
- }
- }
+ mk_eqty(infcx, a, b)
}
fn resolve_type_structure(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
}
}
+impl methods<T:copy> for cres<T> {
+ fn to_ures() -> ures {
+ alt self {
+ ok(_v) { ok(()) }
+ err(e) { err(e) }
+ }
+ }
+
+ fn compare(t: T, f: fn() -> ty::type_err) -> cres<T> {
+ self.chain {|s|
+ if s == t {
+ self
+ } else {
+ err(f())
+ }
+ }
+ }
+}
+
iface to_str {
fn to_str(cx: infer_ctxt) -> str;
}
}
iface st {
- fn st(infcx: infer_ctxt, b: self) -> ures;
+ fn sub(infcx: infer_ctxt, b: self) -> ures;
fn lub(infcx: infer_ctxt, b: self) -> cres<self>;
fn glb(infcx: infer_ctxt, b: self) -> cres<self>;
}
impl of st for ty::t {
- fn st(infcx: infer_ctxt, b: ty::t) -> ures {
- infcx.tys(self, b)
+ fn sub(infcx: infer_ctxt, b: ty::t) -> ures {
+ sub(infcx).tys(self, b).to_ures()
}
fn lub(infcx: infer_ctxt, b: ty::t) -> cres<ty::t> {
- lub(infcx).c_tys(self, b)
+ lub(infcx).tys(self, b)
}
fn glb(infcx: infer_ctxt, b: ty::t) -> cres<ty::t> {
- glb(infcx).c_tys(self, b)
+ glb(infcx).tys(self, b)
}
}
impl of st for ty::region {
- fn st(infcx: infer_ctxt, b: ty::region) -> ures {
- infcx.regions(self, b)
+ fn sub(infcx: infer_ctxt, b: ty::region) -> ures {
+ sub(infcx).regions(self, b).chain {|_r| ok(()) }
}
fn lub(infcx: infer_ctxt, b: ty::region) -> cres<ty::region> {
- lub(infcx).c_regions(self, b)
+ lub(infcx).regions(self, b)
}
fn glb(infcx: infer_ctxt, b: ty::region) -> cres<ty::region> {
- glb(infcx).c_regions(self, b)
+ glb(infcx).regions(self, b)
}
}
// the old range). They therefore return a result.
impl unify_methods for infer_ctxt {
fn uok() -> ures {
- #debug["Unification OK"];
ok(())
}
self.set(self.vb, vid, new_v);
}
- fn commit<T:copy,E:copy>(f: fn() -> result<T,E>) -> result<T,E> {
+ fn commit<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
assert self.vb.bindings.len() == 0u;
assert self.rb.bindings.len() == 0u;
- let r = self.try(f);
+ let r <- self.try(f);
// TODO---could use a vec::clear() that ran destructors but kept
// the vec at its currently allocated length
self.vb.bindings = [];
self.rb.bindings = [];
- #debug[">> Commit result: %?", r];
-
ret r;
}
- fn try<T:copy,E:copy>(f: fn() -> result<T,E>) -> result<T,E> {
+ fn try<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
fn rollback_to<V:copy vid, T:copy>(
vb: vals_and_bindings<V, T>, len: uint) {
let vbl = self.vb.bindings.len();
let rbl = self.rb.bindings.len();
#debug["try(vbl=%u, rbl=%u)", vbl, rbl];
- let r = f();
+ let r <- f();
alt r {
result::ok(_) { #debug["try--ok"]; }
result::err(_) {
}
}
- fn get_var(vid: ty_vid)
- -> {root: ty_vid, bounds:bounds<ty::t>} {
-
- ret self.get(self.vb, vid);
- }
-
- fn get_region(rid: region_vid)
- -> {root: region_vid, bounds:bounds<ty::region>} {
-
- ret self.get(self.rb, rid);
- }
-
// Combines the two bounds into a more general bound.
fn merge_bnd<V:copy to_str>(
a: bound<V>, b: bound<V>,
merge_op: fn(V,V) -> cres<V>) -> cres<bound<V>> {
+ #debug["merge_bnd(%s,%s)", a.to_str(self), b.to_str(self)];
+ let _r = indenter();
+
alt (a, b) {
(none, none) {
ok(none)
lub: fn(V,V) -> cres<V>,
glb: fn(V,V) -> cres<V>) -> cres<bounds<V>> {
+ let _r = indenter();
self.merge_bnd(a.ub, b.ub, glb).chain {|ub|
#debug["glb of ubs %s and %s is %s",
a.ub.to_str(self), b.ub.to_str(self),
// them explicitly gives the type inferencer more
// information and helps to produce tighter bounds
// when necessary.
+ indent {||
self.bnds(a.lb, b.ub).then {||
self.bnds(b.lb, a.ub).then {||
self.merge_bnd(a.ub, b.ub, {|x, y| x.glb(self, y)}).chain {|ub|
// the new bounds must themselves
// be relatable:
self.bnds(bnds.lb, bnds.ub).then {||
- self.set(vb, v_id, bounded(bnds));
- self.uok()
+ self.set(vb, v_id, bounded(bnds));
+ self.uok()
}
- }}}}
+ }}}}}
}
fn vars<V:copy vid, T:copy to_str st>(
// see if we can make those types subtypes.
alt (a_bounds.ub, b_bounds.lb) {
(some(a_ub), some(b_lb)) {
- let r = self.try {|| a_ub.st(self, b_lb) };
+ let r = self.try {|| a_ub.sub(self, b_lb) };
alt r {
ok(()) { ret result::ok(()); }
err(_) { /*fallthrough */ }
self.set_var_to_merged_bounds(vb, b_id, a_bounds, b_bounds)
}
- fn regions(a: ty::region, b: ty::region) -> ures {
- alt (a, b) { // XXX
- (ty::re_var(a_id), ty::re_var(b_id)) {
- self.vars(self.rb, a_id, b_id)
- }
- (ty::re_var(a_id), _) {
- self.vart(self.rb, a_id, b)
- }
- (_, ty::re_var(b_id)) {
- self.tvar(self.rb, a, b_id)
- }
-
- (ty::re_free(a_id, _), ty::re_scope(b_id)) |
- (ty::re_scope(a_id), ty::re_free(b_id, _)) |
- (ty::re_scope(a_id), ty::re_scope(b_id)) {
- let rm = self.tcx.region_map;
- alt region::nearest_common_ancestor(rm, a_id, b_id) {
- some(r_id) if r_id == a_id { self.uok() }
- _ { err(ty::terr_regions_differ(false, b, a)) }
- }
- }
-
- // For these types, we cannot define any additional relationship:
- (ty::re_free(_, _), ty::re_free(_, _)) |
- (ty::re_bound(_), ty::re_bound(_)) |
- (ty::re_bound(_), ty::re_free(_, _)) |
- (ty::re_bound(_), ty::re_scope(_)) |
- (ty::re_free(_, _), ty::re_bound(_)) |
- (ty::re_scope(_), ty::re_bound(_)) {
- if a == b {
- self.uok()
- } else {
- err(ty::terr_regions_differ(false, b, a))
- }
- }
-
- (ty::re_default, _) |
- (_, ty::re_default) {
- // actually a compiler bug, I think.
- err(ty::terr_regions_differ(false, b, a))
- }
- }
- }
-
- fn mts(a: ty::mt, b: ty::mt) -> ures {
- #debug("mts(%s <: %s)", a.to_str(self), b.to_str(self));
-
- if a.mutbl != b.mutbl && b.mutbl != ast::m_const {
- ret self.uerr(ty::terr_mutability);
- }
-
- alt b.mutbl {
- ast::m_mutbl {
- // If supertype is mut, subtype must match exactly
- // (i.e., invariant if mut):
- self.eq_tys(a.ty, b.ty)
- }
- ast::m_imm | ast::m_const {
- // Otherwise we can be covariant:
- self.tys(a.ty, b.ty)
- }
- }
- }
-
- fn flds(a: ty::field, b: ty::field) -> ures {
- if a.ident != b.ident {
- ret self.uerr(ty::terr_record_fields(a.ident, b.ident));
- }
- self.mts(a.mt, b.mt)
- }
-
- fn tps(as: [ty::t], bs: [ty::t]) -> ures {
- if check vec::same_length(as, bs) {
- iter2(as, bs) {|a, b| self.tys(a, b) }
- } else {
- self.uerr(ty::terr_ty_param_size(as.len(), bs.len()))
- }
- }
-
- fn protos(a: ast::proto, b: ast::proto) -> ures {
- alt (a, b) {
- (_, ast::proto_any) { self.uok() }
- (ast::proto_bare, _) { self.uok() }
- (_, _) if a == b { self.uok() }
- _ { self.uerr(ty::terr_proto_mismatch(a, b)) }
- }
- }
-
- fn ret_styles(
- a_ret_style: ret_style,
- b_ret_style: ret_style) -> ures {
-
- if b_ret_style != ast::noreturn && b_ret_style != a_ret_style {
- /* even though typestate checking is mostly
- responsible for checking control flow annotations,
- this check is necessary to ensure that the
- annotation in an object method matches the
- declared object type */
- self.uerr(ty::terr_ret_style_mismatch(a_ret_style, b_ret_style))
- } else {
- self.uok()
- }
- }
-
- fn modes(a: ast::mode, b: ast::mode) -> ures {
- alt ty::unify_mode(self.tcx, a, b) {
- ok(_) { self.uok() }
- err(e) { self.uerr(e) }
- }
- }
-
- fn args(a: ty::arg, b: ty::arg) -> ures {
- self.modes(a.mode, b.mode).then {||
- self.tys(b.ty, a.ty) // Note: contravariant
- }
- }
-
- fn argvecs(
- a_args: [ty::arg],
- b_args: [ty::arg]) -> ures {
-
- if check vec::same_length(a_args, b_args) {
- iter2(a_args, b_args) {|a, b| self.args(a, b) }
- } else {
- ret self.uerr(ty::terr_arg_count);
- }
- }
-
- fn fns(a_f: ty::fn_ty, b_f: ty::fn_ty) -> ures {
- self.protos(a_f.proto, b_f.proto).then {||
- self.ret_styles(a_f.ret_style, b_f.ret_style).then {||
- self.argvecs(a_f.inputs, b_f.inputs).then {||
- self.tys(a_f.output, b_f.output).then {||
- //TODO self.constrvecs(a_f.constraints,
- //TODO b_f.constraints).then {||
- self.uok()
- //TODO }
- }
- }
- }
- }
- }
-
fn constrs(
expected: @ty::type_constr,
actual_constr: @ty::type_constr) -> ures {
let actual_arg_len = vec::len(actual_constr.node.args);
if expected_arg_len != actual_arg_len { ret err_res; }
let mut i = 0u;
- for a in expected.node.args {
+ for expected.node.args.each {|a|
let actual = actual_constr.node.args[i];
alt a.node {
ast::carg_base {
a: bound<T>, b: bound<T>) -> ures {
#debug("bnds(%s <: %s)", a.to_str(self), b.to_str(self));
-
- alt (a, b) {
- (none, none) |
- (some(_), none) |
- (none, some(_)) {
- self.uok()
- }
- (some(t_a), some(t_b)) {
- t_a.st(self, t_b)
- }
+ indent {||
+ alt (a, b) {
+ (none, none) |
+ (some(_), none) |
+ (none, some(_)) {
+ self.uok()
+ }
+ (some(t_a), some(t_b)) {
+ t_a.sub(self, t_b)
+ }
+ }
}
}
self.constrs(a, b)
}
} else {
- self.uerr(ty::terr_constr_len(as.len(), bs.len()))
+ self.uerr(ty::terr_constr_len(bs.len(), as.len()))
}
}
- fn eq_tys(a: ty::t, b: ty::t) -> ures {
- self.tys(a, b).then {||
- self.tys(b, a)
- }
+ fn sub_tys(a: ty::t, b: ty::t) -> ures {
+ sub(self).tys(a, b).chain {|_t| ok(()) }
}
- fn tys(a: ty::t, b: ty::t) -> ures {
- #debug("tys(%s <: %s)",
- ty_to_str(self.tcx, a),
- ty_to_str(self.tcx, b));
-
- // Fast path.
- if a == b { ret self.uok(); }
-
- alt (ty::get(a).struct, ty::get(b).struct) {
- (ty::ty_bot, _) { self.uok() }
-
- (ty::ty_var(a_id), ty::ty_var(b_id)) {
- self.vars(self.vb, a_id, b_id)
- }
- (ty::ty_var(a_id), _) {
- self.vart(self.vb, a_id, b)
- }
- (_, ty::ty_var(b_id)) {
- self.tvar(self.vb, a, b_id)
- }
-
- (ty::ty_nil, _) |
- (ty::ty_bool, _) |
- (ty::ty_int(_), _) |
- (ty::ty_uint(_), _) |
- (ty::ty_float(_), _) |
- (ty::ty_str, _) {
- let cfg = self.tcx.sess.targ_cfg;
- if ty::mach_sty(cfg, a) == ty::mach_sty(cfg, b) {
- self.uok()
- } else {
- self.uerr(ty::terr_mismatch)
- }
- }
-
- (ty::ty_param(a_n, _), ty::ty_param(b_n, _))
- if a_n == b_n {
- self.uok()
- }
-
- (ty::ty_enum(a_id, a_tps), ty::ty_enum(b_id, b_tps)) |
- (ty::ty_iface(a_id, a_tps), ty::ty_iface(b_id, b_tps)) |
- (ty::ty_class(a_id, a_tps), ty::ty_class(b_id, b_tps))
- if a_id == b_id {
- self.tps(a_tps, b_tps)
- }
-
- (ty::ty_box(a_mt), ty::ty_box(b_mt)) |
- (ty::ty_uniq(a_mt), ty::ty_uniq(b_mt)) |
- (ty::ty_vec(a_mt), ty::ty_vec(b_mt)) |
- (ty::ty_ptr(a_mt), ty::ty_ptr(b_mt)) {
- self.mts(a_mt, b_mt)
- }
-
- (ty::ty_rptr(a_r, a_mt), ty::ty_rptr(b_r, b_mt)) {
- self.mts(a_mt, b_mt).then {||
- self.regions(a_r, b_r)
- }
- }
-
- (ty::ty_res(a_id, a_t, a_tps), ty::ty_res(b_id, b_t, b_tps))
- if a_id == b_id {
- self.tys(a_t, b_t).then {||
- self.tps(a_tps, b_tps)
- }
- }
-
- (ty::ty_rec(a_fields), ty::ty_rec(b_fields)) {
- if check vec::same_length(a_fields, b_fields) {
- iter2(a_fields, b_fields) {|a,b|
- self.flds(a, b)
- }
- } else {
- ret self.uerr(ty::terr_record_size(a_fields.len(),
- b_fields.len()));
- }
- }
-
- (ty::ty_tup(a_tys), ty::ty_tup(b_tys)) {
- if check vec::same_length(a_tys, b_tys) {
- iter2(a_tys, b_tys) {|a,b| self.tys(a,b) }
- } else {
- self.uerr(ty::terr_tuple_size(a_tys.len(), b_tys.len()))
- }
- }
-
- (ty::ty_fn(a_fty), ty::ty_fn(b_fty)) {
- self.fns(a_fty, b_fty)
- }
-
- (ty::ty_constr(a_t, a_constrs), ty::ty_constr(b_t, b_constrs)) {
- self.tys(a_t, b_t).then {||
- self.constrvecs(a_constrs, b_constrs)
- }
- }
-
- _ { self.uerr(ty::terr_mismatch) }
+ fn eq_tys(a: ty::t, b: ty::t) -> ures {
+ self.sub_tys(a, b).then {||
+ self.sub_tys(b, a)
}
}
}
//
// The `c_X()` top-level items work for *both LUB and GLB*: any
// operation which varies between LUB and GLB will be dynamically
-// dispatched using a `self.c_Y()` operation.
+// dispatched using a `self.Y()` operation.
//
// In principle, the subtyping relation computed above could be built
// on the combine framework---this would result in less code but would
iface combine {
fn infcx() -> infer_ctxt;
fn tag() -> str;
- fn bnd<V:copy>(b: bounds<V>) -> option<V>;
- fn with_bnd<V:copy>(b: bounds<V>, v: V) -> bounds<V>;
- fn c_bot(b: ty::t) -> cres<ty::t>;
- fn c_mts(a: ty::mt, b: ty::mt) -> cres<ty::mt>;
- fn c_contratys(t1: ty::t, t2: ty::t) -> cres<ty::t>;
- fn c_tys(t1: ty::t, t2: ty::t) -> cres<ty::t>;
- fn c_protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto>;
- fn c_ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
-
- // Combining regions (along with some specific cases that are
- // different for LUB/GLB):
- fn c_regions(
- a: ty::region, b: ty::region) -> cres<ty::region>;
- fn c_regions_scope_scope(
- a: ty::region, a_id: ast::node_id,
- b: ty::region, b_id: ast::node_id) -> cres<ty::region>;
- fn c_regions_free_scope(
- a: ty::region, a_id: ast::node_id, a_br: ty::bound_region,
- b: ty::region, b_id: ast::node_id) -> cres<ty::region>;
-}
-
-enum lub = infer_ctxt;
-enum glb = infer_ctxt;
-
-fn c_vars<V:copy vid, C:combine, T:copy to_str st>(
- self: C, vb: vals_and_bindings<V, T>,
- a_t: T, a_vid: V, b_vid: V,
- c_ts: fn(T, T) -> cres<T>) -> cres<T> {
-
- // The comments in this function are written for LUB and types,
- // but they apply equally well to GLB and regions if you inverse
- // upper/lower/sub/super/etc.
-
- // Need to find a type that is a supertype of both a and b:
- let {root: a_vid, bounds: a_bounds} = self.infcx().get(vb, a_vid);
- let {root: b_vid, bounds: b_bounds} = self.infcx().get(vb, b_vid);
-
- #debug["%s.c_vars(%s=%s <: %s=%s)",
- self.tag(),
- a_vid.to_str(), a_bounds.to_str(self.infcx()),
- b_vid.to_str(), b_bounds.to_str(self.infcx())];
-
- if a_vid == b_vid {
- ret ok(a_t);
- }
- // If both A and B have an UB type, then we can just compute the
- // LUB of those types:
- let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds);
- alt (a_bnd, b_bnd) {
- (some(a_ty), some(b_ty)) {
- alt self.infcx().try {|| c_ts(a_ty, b_ty) } {
- ok(t) { ret ok(t); }
- err(_) { /*fallthrough */ }
- }
- }
- _ {/*fallthrough*/}
- }
-
- // Otherwise, we need to merge A and B into one variable. We can
- // then use either variable as an upper bound:
- self.infcx().vars(vb, a_vid, b_vid).then {||
- ok(a_t)
- }
+ fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt>;
+ fn contratys(a: ty::t, b: ty::t) -> cres<ty::t>;
+ fn tys(a: ty::t, b: ty::t) -> cres<ty::t>;
+ fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]>;
+ fn fns(a: ty::fn_ty, b: ty::fn_ty) -> cres<ty::fn_ty>;
+ fn flds(a: ty::field, b: ty::field) -> cres<ty::field>;
+ fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
+ fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>;
+ fn protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto>;
+ fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
+ fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region>;
+ fn regions(a: ty::region, b: ty::region) -> cres<ty::region>;
}
-fn c_var_t<V:copy vid, C:combine, T:copy to_str st>(
- self: C, vb: vals_and_bindings<V, T>,
- a_vid: V, b: T,
- c_ts: fn(T, T) -> cres<T>) -> cres<T> {
+enum sub = infer_ctxt; // "less than" == "subtype" or "subregion"
+enum lub = infer_ctxt; // "least upper bound" (common supertype)
+enum glb = infer_ctxt; // "greatest lower bound" (common subtype)
- let {root: a_id, bounds: a_bounds} = self.infcx().get(vb, a_vid);
-
- // The comments in this function are written for LUB, but they
- // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
-
- #debug["%s.c_var_ty(%s=%s <: %s)",
- self.tag(),
- a_id.to_str(), a_bounds.to_str(self.infcx()),
- b.to_str(self.infcx())];
-
- alt self.bnd(a_bounds) {
- some(a_bnd) {
- // If a has an upper bound, return it.
- ret c_ts(a_bnd, b);
- }
- none {
- // If a does not have an upper bound, make b the upper bound of a
- // and then return b.
- let a_bounds = self.with_bnd(a_bounds, b);
- self.infcx().bnds(a_bounds.lb, a_bounds.ub).then {||
- self.infcx().set(vb, a_id, bounded(a_bounds));
- ok(b)
- }
- }
- }
-}
-
-fn c_tuptys<C:combine>(self: C, as: [ty::t], bs: [ty::t])
- -> cres<[ty::t]> {
+fn super_tps<C:combine>(
+ self: C, as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
+ // Note: type parameters are always treated as *invariant*
+ // (otherwise the type system would be unsound). In the
+ // future we could allow type parameters to declare a
+ // variance.
if check vec::same_length(as, bs) {
- map2(as, bs) {|a, b| self.c_tys(a, b) }
- } else {
- err(ty::terr_tuple_size(as.len(), bs.len()))
- }
-}
-
-fn c_tps<C:combine>(self: C, _did: ast::def_id, as: [ty::t], bs: [ty::t])
- -> cres<[ty::t]> {
- // FIXME #1973 lookup the declared variance of the type parameters
- // based on did
- if check vec::same_length(as, bs) {
- map2(as, bs) {|a,b| self.c_tys(a, b) }
+ iter2(as, bs) {|a, b| self.infcx().eq_tys(a, b) }.then {||
+ ok(as)
+ }
} else {
- err(ty::terr_ty_param_size(as.len(), bs.len()))
+ err(ty::terr_ty_param_size(bs.len(), as.len()))
}
}
-fn c_fieldvecs<C:combine>(self: C, as: [ty::field], bs: [ty::field])
- -> cres<[ty::field]> {
-
- if check vec::same_length(as, bs) {
- map2(as, bs) {|a,b| c_flds(self, a, b) }
- } else {
- err(ty::terr_record_size(as.len(), bs.len()))
- }
-}
+fn super_flds<C:combine>(
+ self: C, a: ty::field, b: ty::field) -> cres<ty::field> {
-fn c_flds<C:combine>(self: C, a: ty::field, b: ty::field) -> cres<ty::field> {
if a.ident == b.ident {
- self.c_mts(a.mt, b.mt).chain {|mt|
+ self.mts(a.mt, b.mt).chain {|mt|
ok({ident: a.ident, mt: mt})
+ }.chain_err {|e|
+ err(ty::terr_in_field(@e, a.ident))
}
} else {
- err(ty::terr_record_fields(a.ident, b.ident))
+ err(ty::terr_record_fields(b.ident, a.ident))
}
}
-fn c_modes<C:combine>(self: C, a: ast::mode, b: ast::mode)
+fn super_modes<C:combine>(
+ self: C, a: ast::mode, b: ast::mode)
-> cres<ast::mode> {
let tcx = self.infcx().tcx;
ty::unify_mode(tcx, a, b)
}
-fn c_args<C:combine>(self: C, a: ty::arg, b: ty::arg)
+fn super_args<C:combine>(
+ self: C, a: ty::arg, b: ty::arg)
-> cres<ty::arg> {
- c_modes(self, a.mode, b.mode).chain {|m|
- // Note: contravariant
- self.c_contratys(b.ty, a.ty).chain {|t|
+ self.modes(a.mode, b.mode).chain {|m|
+ self.contratys(a.ty, b.ty).chain {|t|
ok({mode: m, ty: t})
}
}
}
-fn c_argvecs<C:combine>(
- self: C, a_args: [ty::arg], b_args: [ty::arg]) -> cres<[ty::arg]> {
+fn super_fns<C:combine>(
+ self: C, a_f: ty::fn_ty, b_f: ty::fn_ty) -> cres<ty::fn_ty> {
- if check vec::same_length(a_args, b_args) {
- map2(a_args, b_args) {|a, b| c_args(self, a, b) }
- } else {
- err(ty::terr_arg_count)
- }
-}
+ fn argvecs<C:combine>(
+ self: C, a_args: [ty::arg], b_args: [ty::arg]) -> cres<[ty::arg]> {
-fn c_fns<C:combine>(
- self: C, a_f: ty::fn_ty, b_f: ty::fn_ty) -> cres<ty::fn_ty> {
+ if check vec::same_length(a_args, b_args) {
+ map2(a_args, b_args) {|a, b| self.args(a, b) }
+ } else {
+ err(ty::terr_arg_count)
+ }
+ }
- self.c_protos(a_f.proto, b_f.proto).chain {|p|
- self.c_ret_styles(a_f.ret_style, b_f.ret_style).chain {|rs|
- c_argvecs(self, a_f.inputs, b_f.inputs).chain {|inputs|
- self.c_tys(a_f.output, b_f.output).chain {|output|
+ self.protos(a_f.proto, b_f.proto).chain {|p|
+ self.ret_styles(a_f.ret_style, b_f.ret_style).chain {|rs|
+ argvecs(self, a_f.inputs, b_f.inputs).chain {|inputs|
+ self.tys(a_f.output, b_f.output).chain {|output|
//FIXME self.infcx().constrvecs(a_f.constraints,
//FIXME b_f.constraints).then {||
ok({proto: p,
}
}
-fn c_tys<C:combine>(
+fn super_tys<C:combine>(
self: C, a: ty::t, b: ty::t) -> cres<ty::t> {
let tcx = self.infcx().tcx;
-
- #debug("%s.c_tys(%s, %s)",
- self.tag(),
- ty_to_str(tcx, a),
- ty_to_str(tcx, b));
-
- // Fast path.
- if a == b { ret ok(a); }
-
alt (ty::get(a).struct, ty::get(b).struct) {
- (ty::ty_bot, _) { self.c_bot(b) }
- (_, ty::ty_bot) { self.c_bot(b) }
-
- (ty::ty_var(a_id), ty::ty_var(b_id)) {
- c_vars(self, self.infcx().vb,
- a, a_id, b_id,
- {|x, y| self.c_tys(x, y) })
- }
-
- // Note that the LUB/GLB operations are commutative:
- (ty::ty_var(v_id), _) {
- c_var_t(self, self.infcx().vb,
- v_id, b,
- {|x, y| self.c_tys(x, y) })
- }
- (_, ty::ty_var(v_id)) {
- c_var_t(self, self.infcx().vb,
- v_id, a,
- {|x, y| self.c_tys(x, y) })
+ // The "subtype" ought to be handling cases involving bot or var:
+ (ty::ty_bot, _) |
+ (_, ty::ty_bot) |
+ (ty::ty_var(_), _) |
+ (_, ty::ty_var(_)) {
+ tcx.sess.bug(
+ #fmt["%s: bot and var types should have been handled (%s,%s)",
+ self.tag(),
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx())]);
}
(ty::ty_nil, _) |
if ty::mach_sty(cfg, a) == ty::mach_sty(cfg, b) {
ok(a)
} else {
- err(ty::terr_mismatch)
+ err(ty::terr_sorts(b, a))
}
}
(ty::ty_enum(a_id, a_tps), ty::ty_enum(b_id, b_tps))
if a_id == b_id {
- c_tps(self, a_id, a_tps, b_tps).chain {|tps|
+ self.tps(a_tps, b_tps).chain {|tps|
ok(ty::mk_enum(tcx, a_id, tps))
}
}
(ty::ty_iface(a_id, a_tps), ty::ty_iface(b_id, b_tps))
if a_id == b_id {
- c_tps(self, a_id, a_tps, b_tps).chain {|tps|
+ self.tps(a_tps, b_tps).chain {|tps|
ok(ty::mk_iface(tcx, a_id, tps))
}
}
(ty::ty_class(a_id, a_tps), ty::ty_class(b_id, b_tps))
if a_id == b_id {
- // FIXME variance
- c_tps(self, a_id, a_tps, b_tps).chain {|tps|
+ self.tps(a_tps, b_tps).chain {|tps|
ok(ty::mk_class(tcx, a_id, tps))
}
}
(ty::ty_box(a_mt), ty::ty_box(b_mt)) {
- self.c_mts(a_mt, b_mt).chain {|mt|
+ self.mts(a_mt, b_mt).chain {|mt|
ok(ty::mk_box(tcx, mt))
}
}
(ty::ty_uniq(a_mt), ty::ty_uniq(b_mt)) {
- self.c_mts(a_mt, b_mt).chain {|mt|
+ self.mts(a_mt, b_mt).chain {|mt|
ok(ty::mk_uniq(tcx, mt))
}
}
(ty::ty_vec(a_mt), ty::ty_vec(b_mt)) {
- self.c_mts(a_mt, b_mt).chain {|mt|
+ self.mts(a_mt, b_mt).chain {|mt|
ok(ty::mk_vec(tcx, mt))
}
}
(ty::ty_ptr(a_mt), ty::ty_ptr(b_mt)) {
- self.c_mts(a_mt, b_mt).chain {|mt|
+ self.mts(a_mt, b_mt).chain {|mt|
ok(ty::mk_ptr(tcx, mt))
}
}
(ty::ty_rptr(a_r, a_mt), ty::ty_rptr(b_r, b_mt)) {
- self.c_regions(a_r, b_r).chain {|r|
- self.c_mts(a_mt, b_mt).chain {|mt|
+ self.contraregions(a_r, b_r).chain {|r|
+ self.mts(a_mt, b_mt).chain {|mt|
ok(ty::mk_rptr(tcx, r, mt))
}
}
(ty::ty_res(a_id, a_t, a_tps), ty::ty_res(b_id, b_t, b_tps))
if a_id == b_id {
- self.c_tys(a_t, b_t).chain {|t|
- c_tps(self, a_id, a_tps, b_tps).chain {|tps|
+ self.tys(a_t, b_t).chain {|t|
+ self.tps(a_tps, b_tps).chain {|tps|
ok(ty::mk_res(tcx, a_id, t, tps))
}
}
}
- (ty::ty_rec(a_fields), ty::ty_rec(b_fields)) {
- c_fieldvecs(self, a_fields, b_fields).chain {|fs|
- ok(ty::mk_rec(tcx, fs))
+ (ty::ty_rec(as), ty::ty_rec(bs)) {
+ if check vec::same_length(as, bs) {
+ map2(as, bs) {|a,b| self.flds(a, b) }.chain {|flds|
+ ok(ty::mk_rec(tcx, flds))
+ }
+ } else {
+ err(ty::terr_record_size(bs.len(), as.len()))
}
}
- (ty::ty_tup(a_tys), ty::ty_tup(b_tys)) {
- c_tuptys(self, a_tys, b_tys).chain {|ts|
- ok(ty::mk_tup(tcx, ts))
+ (ty::ty_tup(as), ty::ty_tup(bs)) {
+ if check vec::same_length(as, bs) {
+ map2(as, bs) {|a, b| self.tys(a, b) }.chain {|ts|
+ ok(ty::mk_tup(tcx, ts))
+ }
+ } else {
+ err(ty::terr_tuple_size(bs.len(), as.len()))
}
}
(ty::ty_fn(a_fty), ty::ty_fn(b_fty)) {
- c_fns(self, a_fty, b_fty).chain {|fty|
+ self.fns(a_fty, b_fty).chain {|fty|
ok(ty::mk_fn(tcx, fty))
}
}
(ty::ty_constr(a_t, a_constrs), ty::ty_constr(b_t, b_constrs)) {
- self.c_tys(a_t, b_t).chain {|t|
+ self.tys(a_t, b_t).chain {|t|
self.infcx().constrvecs(a_constrs, b_constrs).then {||
ok(ty::mk_constr(tcx, t, a_constrs))
}
}
}
- _ { err(ty::terr_mismatch) }
+ _ { err(ty::terr_sorts(b, a)) }
}
}
-fn c_regions<C:combine>(
- self: C, a: ty::region, b: ty::region) -> cres<ty::region> {
+impl of combine for sub {
+ fn infcx() -> infer_ctxt { *self }
+ fn tag() -> str { "sub" }
- #debug["%s.c_regions(%?, %?)",
- self.tag(),
- a.to_str(self.infcx()),
- b.to_str(self.infcx())];
+ fn lub() -> lub { lub(*self) }
- alt (a, b) {
- (ty::re_var(a_id), ty::re_var(b_id)) {
- c_vars(self, self.infcx().rb,
- a, a_id, b_id,
- {|x, y| self.c_regions(x, y) })
- }
+ fn contratys(a: ty::t, b: ty::t) -> cres<ty::t> {
+ self.tys(b, a)
+ }
- (ty::re_var(v_id), r) |
- (r, ty::re_var(v_id)) {
- c_var_t(self, self.infcx().rb,
- v_id, r,
- {|x, y| self.c_regions(x, y) })
- }
+ fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region> {
+ self.regions(b, a)
+ }
- (f @ ty::re_free(f_id, f_br), s @ ty::re_scope(s_id)) |
- (s @ ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
- self.c_regions_free_scope(f, f_id, f_br, s, s_id)
- }
+ fn regions(a: ty::region, b: ty::region) -> cres<ty::region> {
+ #debug["regions(%s <= %s)", a.to_str(*self), b.to_str(*self)];
+ indent {||
+ alt (a, b) {
+ (ty::re_var(a_id), ty::re_var(b_id)) {
+ self.infcx().vars(self.rb, a_id, b_id).then {||
+ ok(a)
+ }
+ }
+ (ty::re_var(a_id), _) {
+ self.infcx().vart(self.rb, a_id, b).then {||
+ ok(a)
+ }
+ }
+ (_, ty::re_var(b_id)) {
+ self.infcx().tvar(self.rb, a, b_id).then {||
+ ok(a)
+ }
+ }
+ _ {
+ self.lub().regions(a, b).compare(b) {||
+ ty::terr_regions_differ(b, a)
+ }
+ }
+ }
+ }
+ }
- (ty::re_scope(a_id), ty::re_scope(b_id)) {
- self.c_regions_scope_scope(a, a_id, b, b_id)
- }
+ fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
+ #debug("mts(%s <: %s)", a.to_str(*self), b.to_str(*self));
- // For these types, we cannot define any additional relationship:
- (ty::re_free(_, _), ty::re_free(_, _)) |
- (ty::re_bound(_), ty::re_bound(_)) |
- (ty::re_bound(_), ty::re_free(_, _)) |
- (ty::re_bound(_), ty::re_scope(_)) |
- (ty::re_free(_, _), ty::re_bound(_)) |
- (ty::re_scope(_), ty::re_bound(_)) {
- if a == b {
- #debug["... yes, %s == %s.",
- a.to_str(self.infcx()),
- b.to_str(self.infcx())];
- ok(a)
- } else {
- #debug["... no, %s != %s.",
- a.to_str(self.infcx()),
- b.to_str(self.infcx())];
- err(ty::terr_regions_differ(false, b, a))
+ if a.mutbl != b.mutbl && b.mutbl != ast::m_const {
+ ret err(ty::terr_mutability);
}
- }
- (ty::re_default, _) |
- (_, ty::re_default) {
- // actually a compiler bug, I think.
- err(ty::terr_regions_differ(false, b, a))
- }
+ alt b.mutbl {
+ ast::m_mutbl {
+ // If supertype is mut, subtype must match exactly
+ // (i.e., invariant if mut):
+ self.infcx().eq_tys(a.ty, b.ty).then {|| ok(a) }
+ }
+ ast::m_imm | ast::m_const {
+ // Otherwise we can be covariant:
+ self.tys(a.ty, b.ty).chain {|_t| ok(a) }
+ }
+ }
}
-}
-impl of combine for lub {
- fn infcx() -> infer_ctxt { *self }
+ fn protos(a: ast::proto, b: ast::proto) -> cres<ast::proto> {
+ self.lub().protos(a, b).compare(b) {||
+ ty::terr_proto_mismatch(b, a)
+ }
+ }
- fn tag() -> str { "lub" }
+ fn ret_styles(a: ret_style, b: ret_style) -> cres<ret_style> {
+ self.lub().ret_styles(a, b).compare(b) {||
+ ty::terr_ret_style_mismatch(b, a)
+ }
+ }
- fn bnd<V:copy>(b: bounds<V>) -> option<V> {
- b.ub
+ fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
+ #debug("%s.tys(%s, %s)", self.tag(),
+ a.to_str(*self), b.to_str(*self));
+ if a == b { ret ok(a); }
+ indent {||
+ alt (ty::get(a).struct, ty::get(b).struct) {
+ (ty::ty_bot, _) {
+ ok(a)
+ }
+ (ty::ty_var(a_id), ty::ty_var(b_id)) {
+ self.infcx().vars(self.vb, a_id, b_id).then {|| ok(a) }
+ }
+ (ty::ty_var(a_id), _) {
+ self.infcx().vart(self.vb, a_id, b).then {|| ok(a) }
+ }
+ (_, ty::ty_var(b_id)) {
+ self.infcx().tvar(self.vb, a, b_id).then {|| ok(a) }
+ }
+ (_, ty::ty_bot) {
+ err(ty::terr_sorts(b, a))
+ }
+ _ {
+ super_tys(self, a, b)
+ }
+ }
+ }
+ }
+
+ // Traits please:
+
+ fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
+ super_flds(self, a, b)
}
- fn with_bnd<V:copy>(b: bounds<V>, v: V) -> bounds<V> {
- assert b.ub == none;
- {ub: some(v) with b}
+ fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode> {
+ super_modes(self, a, b)
}
- fn c_bot(b: ty::t) -> cres<ty::t> {
- ok(b)
+ fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg> {
+ super_args(self, a, b)
}
- fn c_mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
+ fn fns(a: ty::fn_ty, b: ty::fn_ty) -> cres<ty::fn_ty> {
+ super_fns(self, a, b)
+ }
+
+ fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
+ super_tps(self, as, bs)
+ }
+}
+
+impl of combine for lub {
+ fn infcx() -> infer_ctxt { *self }
+ fn tag() -> str { "lub" }
+
+ fn bot_ty(b: ty::t) -> cres<ty::t> { ok(b) }
+ fn ty_bot(b: ty::t) -> cres<ty::t> { self.bot_ty(b) } // commutative
+
+ fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
let tcx = self.infcx().tcx;
- #debug("%s.c_mts(%s, %s)",
+ #debug("%s.mts(%s, %s)",
self.tag(),
mt_to_str(tcx, a),
mt_to_str(tcx, b));
alt m {
ast::m_imm | ast::m_const {
- self.c_tys(a.ty, b.ty).chain {|t|
+ self.tys(a.ty, b.ty).chain {|t|
ok({ty: t, mutbl: m})
}
}
ok({ty: a.ty, mutbl: m})
}
}.chain_err {|_e|
- self.c_tys(a.ty, b.ty).chain {|t|
+ self.tys(a.ty, b.ty).chain {|t|
ok({ty: t, mutbl: ast::m_const})
}
}
}
}
- fn c_contratys(a: ty::t, b: ty::t) -> cres<ty::t> {
- glb(self.infcx()).c_tys(a, b)
- }
-
- fn c_tys(a: ty::t, b: ty::t) -> cres<ty::t> {
- c_tys(self, a, b)
+ fn contratys(a: ty::t, b: ty::t) -> cres<ty::t> {
+ glb(self.infcx()).tys(a, b)
}
- fn c_protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto> {
+ fn protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto> {
if p1 == ast::proto_bare {
ok(p2)
} else if p2 == ast::proto_bare {
}
}
- fn c_ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
+ fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
alt (r1, r2) {
(ast::return_val, _) |
(_, ast::return_val) {
}
}
- fn c_regions(a: ty::region, b: ty::region) -> cres<ty::region> {
- ret c_regions(self, a, b);
+ fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region> {
+ ret glb(self.infcx()).regions(a, b);
}
- fn c_regions_free_scope(
- a: ty::region, _a_id: ast::node_id, _a_br: ty::bound_region,
- _b: ty::region, _b_id: ast::node_id) -> cres<ty::region> {
+ fn regions(a: ty::region, b: ty::region) -> cres<ty::region> {
+ #debug["%s.regions(%?, %?)",
+ self.tag(),
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx())];
- // for LUB, the scope is within the function and the free
- // region is always a parameter to the method.
- ret ok(a); // NDM--not so for nested functions
- }
+ indent {||
+ alt (a, b) {
+ (ty::re_static, _) | (_, ty::re_static) {
+ ok(ty::re_static) // nothing lives longer than static
+ }
+
+ (ty::re_var(a_id), ty::re_var(b_id)) {
+ lattice_vars(self, self.infcx().rb,
+ a, a_id, b_id,
+ {|x, y| self.regions(x, y) })
+ }
+
+ (ty::re_var(v_id), r) |
+ (r, ty::re_var(v_id)) {
+ lattice_var_t(self, self.infcx().rb,
+ v_id, r,
+ {|x, y| self.regions(x, y) })
+ }
- fn c_regions_scope_scope(a: ty::region, a_id: ast::node_id,
- b: ty::region, b_id: ast::node_id)
- -> cres<ty::region> {
+ (f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
+ (ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
+ // for LUB, the scope is within the function and the free
+ // region is always a parameter to the method.
+ ok(f) // NDM--not so for nested functions
+ }
+
+ (ty::re_scope(a_id), ty::re_scope(b_id)) {
+ // The region corresponding to an outer block is a
+ // subtype of the region corresponding to an inner
+ // block.
+ let rm = self.infcx().tcx.region_map;
+ alt region::nearest_common_ancestor(rm, a_id, b_id) {
+ some(r_id) { ok(ty::re_scope(r_id)) }
+ _ { err(ty::terr_regions_differ(b, a)) }
+ }
+ }
+
+ // For these types, we cannot define any additional
+ // relationship:
+ (ty::re_free(_, _), ty::re_free(_, _)) |
+ (ty::re_bound(_), ty::re_bound(_)) |
+ (ty::re_bound(_), ty::re_free(_, _)) |
+ (ty::re_bound(_), ty::re_scope(_)) |
+ (ty::re_free(_, _), ty::re_bound(_)) |
+ (ty::re_scope(_), ty::re_bound(_)) {
+ if a == b {
+ ok(a)
+ } else {
+ err(ty::terr_regions_differ(b, a))
+ }
+ }
- // The region corresponding to an outer block is a subtype of the
- // region corresponding to an inner block.
- let rm = self.infcx().tcx.region_map;
- alt region::nearest_common_ancestor(rm, a_id, b_id) {
- some(r_id) { ok(ty::re_scope(r_id)) }
- _ { err(ty::terr_regions_differ(false, b, a)) }
+ (ty::re_default, _) |
+ (_, ty::re_default) {
+ // actually a compiler bug, I think.
+ err(ty::terr_regions_differ(b, a))
+ }
+ }
}
}
-}
-impl of combine for glb {
- fn infcx() -> infer_ctxt { *self }
+ // Traits please:
- fn tag() -> str { "glb" }
+ fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
+ lattice_tys(self, a, b)
+ }
- fn bnd<V:copy>(b: bounds<V>) -> option<V> {
- b.lb
+ fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
+ super_flds(self, a, b)
}
- fn with_bnd<V:copy>(b: bounds<V>, v: V) -> bounds<V> {
- assert b.lb == none;
- {lb: some(v) with b}
+ fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode> {
+ super_modes(self, a, b)
}
- fn c_bot(_b: ty::t) -> cres<ty::t> {
- ok(ty::mk_bot(self.infcx().tcx))
+ fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg> {
+ super_args(self, a, b)
}
- fn c_mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
+ fn fns(a: ty::fn_ty, b: ty::fn_ty) -> cres<ty::fn_ty> {
+ super_fns(self, a, b)
+ }
+
+ fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
+ super_tps(self, as, bs)
+ }
+}
+
+impl of combine for glb {
+ fn infcx() -> infer_ctxt { *self }
+ fn tag() -> str { "glb" }
+
+ fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
let tcx = self.infcx().tcx;
- #debug("%s.c_mts(%s, %s)",
+ #debug("%s.mts(%s, %s)",
self.tag(),
mt_to_str(tcx, a),
mt_to_str(tcx, b));
// If one side or both is mut, then the GLB must use
// the precise type from the mut side.
(ast::m_mutbl, ast::m_const) {
- self.infcx().tys(a.ty, b.ty).then {||
+ sub(*self).tys(a.ty, b.ty).chain {|_t|
ok({ty: a.ty, mutbl: ast::m_mutbl})
}
}
(ast::m_const, ast::m_mutbl) {
- self.infcx().tys(b.ty, a.ty).then {||
+ sub(*self).tys(b.ty, a.ty).chain {|_t|
ok({ty: b.ty, mutbl: ast::m_mutbl})
}
}
(ast::m_imm, ast::m_const) |
(ast::m_const, ast::m_imm) |
(ast::m_imm, ast::m_imm) {
- self.c_tys(a.ty, b.ty).chain {|t|
+ self.tys(a.ty, b.ty).chain {|t|
ok({ty: t, mutbl: ast::m_imm})
}
}
// If both sides are const, then we can use GLB of both
// sides and mutbl of only `m_const`.
(ast::m_const, ast::m_const) {
- self.c_tys(a.ty, b.ty).chain {|t|
+ self.tys(a.ty, b.ty).chain {|t|
ok({ty: t, mutbl: ast::m_const})
}
}
}
}
- fn c_contratys(a: ty::t, b: ty::t) -> cres<ty::t> {
- lub(self.infcx()).c_tys(a, b)
- }
-
- fn c_tys(a: ty::t, b: ty::t) -> cres<ty::t> {
- c_tys(self, a, b)
+ fn contratys(a: ty::t, b: ty::t) -> cres<ty::t> {
+ lub(self.infcx()).tys(a, b)
}
- fn c_protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto> {
+ fn protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto> {
if p1 == ast::proto_any {
ok(p2)
} else if p2 == ast::proto_any {
}
}
- fn c_ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
+ fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
alt (r1, r2) {
(ast::return_val, ast::return_val) {
ok(ast::return_val)
}
}
- fn c_regions(a: ty::region, b: ty::region) -> cres<ty::region> {
- ret c_regions(self, a, b);
+ fn regions(a: ty::region, b: ty::region) -> cres<ty::region> {
+ #debug["%s.regions(%?, %?)",
+ self.tag(),
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx())];
+
+ indent {||
+ alt (a, b) {
+ (ty::re_static, r) | (r, ty::re_static) {
+ // static lives longer than everything else
+ ok(r)
+ }
+
+ (ty::re_var(a_id), ty::re_var(b_id)) {
+ lattice_vars(self, self.infcx().rb,
+ a, a_id, b_id,
+ {|x, y| self.regions(x, y) })
+ }
+
+ (ty::re_var(v_id), _) | (_, ty::re_var(v_id)) {
+ lattice_var_t(self, self.infcx().rb,
+ v_id, b,
+ {|x, y| self.regions(x, y) })
+ }
+
+ (f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
+ (ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
+ // for GLB, the scope is within the function and the free
+ // region is always a parameter to the method. So the GLB
+ // must be the scope.
+ ok(b) // NDM--not so for nested functions
+ }
+
+ (ty::re_scope(a_id), ty::re_scope(b_id)) {
+ // We want to generate a region that is contained by both of
+ // these: so, if one of these scopes is a subscope of the
+ // other, return it. Otherwise fail.
+ let rm = self.infcx().tcx.region_map;
+ alt region::nearest_common_ancestor(rm, a_id, b_id) {
+ some(r_id) if a_id == r_id { ok(b) }
+ some(r_id) if b_id == r_id { ok(a) }
+ _ { err(ty::terr_regions_differ(b, a)) }
+ }
+ }
+
+ // For these types, we cannot define any additional
+ // relationship:
+ (ty::re_free(_, _), ty::re_free(_, _)) |
+ (ty::re_bound(_), ty::re_bound(_)) |
+ (ty::re_bound(_), ty::re_free(_, _)) |
+ (ty::re_bound(_), ty::re_scope(_)) |
+ (ty::re_free(_, _), ty::re_bound(_)) |
+ (ty::re_scope(_), ty::re_bound(_)) {
+ if a == b {
+ ok(a)
+ } else {
+ err(ty::terr_regions_differ(b, a))
+ }
+ }
+
+ (ty::re_default, _) |
+ (_, ty::re_default) {
+ // actually a compiler bug, I think.
+ err(ty::terr_regions_differ(b, a))
+ }
+ }
+ }
+ }
+
+ fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region> {
+ lub(self.infcx()).regions(a, b)
+ }
+
+ fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
+ lattice_tys(self, a, b)
+ }
+
+ // Traits please:
+
+ fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
+ super_flds(self, a, b)
+ }
+
+ fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode> {
+ super_modes(self, a, b)
+ }
+
+ fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg> {
+ super_args(self, a, b)
+ }
+
+ fn fns(a: ty::fn_ty, b: ty::fn_ty) -> cres<ty::fn_ty> {
+ super_fns(self, a, b)
+ }
+
+ fn tps(as: [ty::t], bs: [ty::t]) -> cres<[ty::t]> {
+ super_tps(self, as, bs)
+ }
+}
+
+// ______________________________________________________________________
+// Lattice operations on variables
+//
+// this is common code used by both LUB and GLB
+
+iface lattice_ops {
+ fn bnd<T:copy>(b: bounds<T>) -> option<T>;
+ fn with_bnd<T:copy>(b: bounds<T>, t: T) -> bounds<T>;
+ fn ty_bot(t: ty::t) -> cres<ty::t>;
+}
+
+impl of lattice_ops for lub {
+ fn bnd<T:copy>(b: bounds<T>) -> option<T> { b.ub }
+ fn with_bnd<T:copy>(b: bounds<T>, t: T) -> bounds<T> {
+ {ub: some(t) with b}
+ }
+ fn ty_bot(t: ty::t) -> cres<ty::t> {
+ ok(t)
+ }
+}
+
+impl of lattice_ops for glb {
+ fn bnd<T:copy>(b: bounds<T>) -> option<T> { b.lb }
+ fn with_bnd<T:copy>(b: bounds<T>, t: T) -> bounds<T> {
+ {lb: some(t) with b}
+ }
+ fn ty_bot(_t: ty::t) -> cres<ty::t> {
+ ok(ty::mk_bot(self.infcx().tcx))
+ }
+}
+
+fn lattice_tys<L:lattice_ops combine>(
+ self: L, a: ty::t, b: ty::t) -> cres<ty::t> {
+
+ #debug("%s.tys(%s, %s)", self.tag(),
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx()));
+ if a == b { ret ok(a); }
+ indent {||
+ alt (ty::get(a).struct, ty::get(b).struct) {
+ (ty::ty_bot, _) { self.ty_bot(b) }
+ (_, ty::ty_bot) { self.ty_bot(a) }
+
+ (ty::ty_var(a_id), ty::ty_var(b_id)) {
+ lattice_vars(self, self.infcx().vb,
+ a, a_id, b_id,
+ {|x, y| self.tys(x, y) })
+ }
+
+ (ty::ty_var(a_id), _) {
+ lattice_var_t(self, self.infcx().vb, a_id, b,
+ {|x, y| self.tys(x, y) })
+ }
+
+ (_, ty::ty_var(b_id)) {
+ lattice_var_t(self, self.infcx().vb, b_id, a,
+ {|x, y| self.tys(x, y) })
+ }
+
+ _ {
+ super_tys(self, a, b)
+ }
+ }
+ }
+}
+
+fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
+ self: L, vb: vals_and_bindings<V, T>,
+ a_t: T, a_vid: V, b_vid: V,
+ c_ts: fn(T, T) -> cres<T>) -> cres<T> {
+
+ // The comments in this function are written for LUB and types,
+ // but they apply equally well to GLB and regions if you inverse
+ // upper/lower/sub/super/etc.
+
+ // Need to find a type that is a supertype of both a and b:
+ let {root: a_vid, bounds: a_bounds} = self.infcx().get(vb, a_vid);
+ let {root: b_vid, bounds: b_bounds} = self.infcx().get(vb, b_vid);
+
+ #debug["%s.vars(%s=%s <: %s=%s)",
+ self.tag(),
+ a_vid.to_str(), a_bounds.to_str(self.infcx()),
+ b_vid.to_str(), b_bounds.to_str(self.infcx())];
+
+ if a_vid == b_vid {
+ ret ok(a_t);
}
- fn c_regions_free_scope(
- _a: ty::region, _a_id: ast::node_id, _a_br: ty::bound_region,
- b: ty::region, _b_id: ast::node_id) -> cres<ty::region> {
+ // If both A and B have an UB type, then we can just compute the
+ // LUB of those types:
+ let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds);
+ alt (a_bnd, b_bnd) {
+ (some(a_ty), some(b_ty)) {
+ alt self.infcx().try {|| c_ts(a_ty, b_ty) } {
+ ok(t) { ret ok(t); }
+ err(_) { /*fallthrough */ }
+ }
+ }
+ _ {/*fallthrough*/}
+ }
- // for GLB, the scope is within the function and the free
- // region is always a parameter to the method. So the GLB
- // must be the scope.
- ret ok(b); // NDM--not so for nested functions
+ // Otherwise, we need to merge A and B into one variable. We can
+ // then use either variable as an upper bound:
+ self.infcx().vars(vb, a_vid, b_vid).then {||
+ ok(a_t)
}
+}
- fn c_regions_scope_scope(a: ty::region, a_id: ast::node_id,
- b: ty::region, b_id: ast::node_id)
- -> cres<ty::region> {
+fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
+ self: L, vb: vals_and_bindings<V, T>,
+ a_vid: V, b: T,
+ c_ts: fn(T, T) -> cres<T>) -> cres<T> {
- // We want to generate a region that is contained by both of
- // these: so, if one of these scopes is a subscope of the
- // other, return it. Otherwise fail.
- let rm = self.infcx().tcx.region_map;
- alt region::nearest_common_ancestor(rm, a_id, b_id) {
- some(r_id) if a_id == r_id { ok(b) }
- some(r_id) if b_id == r_id { ok(a) }
- _ { err(ty::terr_regions_differ(false, b, a)) }
+ let {root: a_id, bounds: a_bounds} = self.infcx().get(vb, a_vid);
+
+ // The comments in this function are written for LUB, but they
+ // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
+
+ #debug["%s.var_ty(%s=%s <: %s)",
+ self.tag(),
+ a_id.to_str(), a_bounds.to_str(self.infcx()),
+ b.to_str(self.infcx())];
+
+ alt self.bnd(a_bounds) {
+ some(a_bnd) {
+ // If a has an upper bound, return it.
+ #debug["bnd=some(%s)", a_bnd.to_str(self.infcx())];
+ ret c_ts(a_bnd, b);
+ }
+ none {
+ // If a does not have an upper bound, make b the upper bound of a
+ // and then return b.
+ #debug["bnd=none"];
+ let a_bounds = self.with_bnd(a_bounds, b);
+ self.infcx().bnds(a_bounds.lb, a_bounds.ub).then {||
+ self.infcx().set(vb, a_id, bounded(a_bounds));
+ ok(b)
}
+ }
}
}
// the common flow point for all functions that appear in the AST.
with_appropriate_checker(cx, fn_id) { |checker|
- for @{def, span} in *freevars::get_freevars(cx.tcx, fn_id) {
- let id = ast_util::def_id_of_def(def).node;
+ for vec::each(*freevars::get_freevars(cx.tcx, fn_id)) {|fv|
+ let id = ast_util::def_id_of_def(fv.def).node;
if checker == check_copy {
let last_uses = alt check cx.last_uses.find(fn_id) {
some(last_use::closes_over(vars)) { vars }
vec::position_elem(last_uses, id)) { cont; }
}
let ty = ty::node_id_to_type(cx.tcx, id);
- checker(cx, ty, span);
+ checker(cx, ty, fv.span);
}
}
// Vector add copies.
expr_binary(add, ls, rs) { maybe_copy(cx, ls); maybe_copy(cx, rs); }
expr_rec(fields, def) {
- for field in fields { maybe_copy(cx, field.node.expr); }
+ for fields.each {|field| maybe_copy(cx, field.node.expr); }
alt def {
some(ex) {
// All noncopyable fields must be overridden
ty::ty_rec(f) { f }
_ { cx.tcx.sess.span_bug(ex.span, "bad expr type in record"); }
};
- for tf in ty_fields {
+ for ty_fields.each {|tf|
if !vec::any(fields, {|f| f.node.ident == tf.ident}) &&
!ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) {
cx.tcx.sess.span_err(ex.span,
}
}
expr_tup(exprs) | expr_vec(exprs, _) {
- for expr in exprs { maybe_copy(cx, expr); }
+ for exprs.each {|expr| maybe_copy(cx, expr); }
}
expr_bind(_, args) {
- for a in args { alt a { some(ex) { maybe_copy(cx, ex); } _ {} } }
+ for args.each {|a| alt a { some(ex) { maybe_copy(cx, ex); } _ {} } }
}
expr_call(f, args, _) {
let mut i = 0u;
- for arg_t in ty::ty_fn_args(ty::expr_ty(cx.tcx, f)) {
+ for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each {|arg_t|
alt ty::arg_mode(cx.tcx, arg_t) {
by_copy { maybe_copy(cx, args[i]); }
by_ref | by_val | by_mutbl_ref | by_move { }
}
}
expr_path(_) | expr_field(_, _, _) {
- option::with_option_do(cx.tcx.node_type_substs.find(e.id)) {|ts|
+ option::iter(cx.tcx.node_type_substs.find(e.id)) {|ts|
let bounds = alt check e.node {
expr_path(_) {
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
alt stmt.node {
stmt_decl(@{node: decl_local(locals), _}, _) {
- for local in locals {
+ for locals.each {|local|
alt local.node.init {
some({op: init_assign, expr}) { maybe_copy(cx, expr); }
_ {}
fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
alt aty.node {
ty_path(_, id) {
- option::with_option_do(cx.tcx.node_type_substs.find(id)) {|ts|
+ option::iter(cx.tcx.node_type_substs.find(id)) {|ts|
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(id));
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
vec::iter2(ts, *bounds) {|ty, bound|
expr_while(_, _) | expr_do_while(_, _) | expr_loop(_) {
visit_block(lp, cx) {|| visit::visit_expr(ex, cx, v);}
}
- expr_for(_, coll, blk) {
- v.visit_expr(coll, cx, v);
- visit_block(lp, cx) {|| visit::visit_block(blk, cx, v);}
- }
expr_alt(input, arms, _) {
v.visit_expr(input, cx, v);
let before = cx.current;
let mut sets = [];
- for arm in arms {
+ for arms.each {|arm|
cx.current = before;
v.visit_arm(arm, cx, v);
sets += [cx.current];
clear_in_current(cx, root_id, false);
}
_ {
- option::with_option_do(def_is_owned_local(cx, my_def)) {|nid|
+ option::iter(def_is_owned_local(cx, my_def)) {|nid|
clear_in_current(cx, nid, false);
cx.current += [{def: nid,
uses: cons(var_use(ex.id), @nil)}];
}
}
}
- for f in fns { v.visit_expr(f, cx, v); }
+ for fns.each {|f| v.visit_expr(f, cx, v); }
vec::iter2(args, arg_ts) {|arg, arg_t|
alt arg.node {
expr_path(_) {
alt ty::arg_mode(cx.tcx, arg_t) {
by_ref | by_val | by_mutbl_ref {
let def = cx.def_map.get(arg.id);
- option::with_option_do(def_is_owned_local(cx, def)) {|id|
+ option::iter(def_is_owned_local(cx, def)) {|id|
clear_in_current(cx, id, false);
cx.spill_map.insert(id, ());
}
stmt_decl(@{node: decl_local(ls), _}, _) {
shadow_in_current(cx, {|id|
let mut rslt = false;
- for local in ls {
+ for ls.each {|local|
let mut found = false;
pat_util::pat_bindings(cx.tcx.def_map, local.node.pat,
{|pid, _a, _b|
proto_box | proto_uniq | proto_bare {
alt cx.tcx.freevars.find(id) {
some(vars) {
- for v in *vars {
- option::with_option_do(def_is_owned_local(cx, v.def)) {|nid|
+ for vec::each(*vars) {|v|
+ option::iter(def_is_owned_local(cx, v.def)) {|nid|
clear_in_current(cx, nid, false);
cx.current += [{def: nid,
uses: cons(close_over(id), @nil)}];
fn join_branches(branches: [set]) -> set {
let mut found: set = [], i = 0u;
let l = vec::len(branches);
- for set in branches {
+ for branches.each {|set|
i += 1u;
- for {def, uses} in set {
- if !vec::any(found, {|v| v.def == def}) {
- let mut j = i, nne = uses;
+ for set.each {|elt|
+ if !vec::any(found, {|v| v.def == elt.def}) {
+ let mut j = i, nne = elt.uses;
while j < l {
- for {def: d2, uses} in branches[j] {
- if d2 == def {
- list::iter(uses) {|e|
+ for vec::each(branches[j]) {|elt2|
+ if elt2.def == elt.def {
+ list::iter(elt2.uses) {|e|
if !list::has(nne, e) { nne = cons(e, @nne); }
}
}
}
j += 1u;
}
- found += [{def: def, uses: nne}];
+ found += [{def: elt.def, uses: nne}];
}
}
}
}
fn leave_fn(cx: ctx) {
- for {def, uses} in cx.current {
- list::iter(uses) {|use|
+ for cx.current.each {|elt|
+ list::iter(elt.uses) {|use|
let key = alt use {
var_use(pth_id) { path(pth_id) }
- close_over(fn_id) { close(fn_id, def) }
+ close_over(fn_id) { close(fn_id, elt.def) }
};
if !cx.last_uses.contains_key(key) {
cx.last_uses.insert(key, true);
fn shadow_in_current(cx: ctx, p: fn(node_id) -> bool) {
let mut out = [];
cx.current <-> out;
- for e in out { if !p(e.def) { cx.current += [e]; } }
+ for out.each {|e| if !p(e.def) { cx.current += [e]; } }
}
fn clear_in_current(cx: ctx, my_def: node_id, to: bool) {
- for {def, uses} in cx.current {
- if def == my_def {
- list::iter(uses) {|use|
+ for cx.current.each {|elt|
+ if elt.def == my_def {
+ list::iter(elt.uses) {|use|
let key = alt use {
var_use(pth_id) { path(pth_id) }
- close_over(fn_id) { close(fn_id, def) }
+ close_over(fn_id) { close(fn_id, elt.def) }
};
if !to || !cx.last_uses.contains_key(key) {
cx.last_uses.insert(key, to);
}
fn contains(xs: [(option, bool)], x: option) -> bool {
- for (o, _) in xs {
+ for xs.each {|c|
+ let (o, _) = c;
if o == x { ret true; }
}
ret false;
}
};
- for (o, v) in default() {
+ for default().each {|c|
+ let (o, v) = c;
if !contains(result, o) {
result += [(o, v)];
}
fn check_ctypes(tcx: ty::ctxt, crate: @ast::crate) {
fn check_native_fn(tcx: ty::ctxt, decl: ast::fn_decl) {
let tys = vec::map(decl.inputs) {|a| a.ty };
- for ty in (tys + [decl.output]) {
+ for vec::each(tys + [decl.output]) {|ty|
alt ty.node {
ast::ty_path(_, id) {
alt tcx.def_map.get(id) {
alt it.node {
ast::item_native_mod(nmod) if attr::native_abi(it.attrs) !=
either::right(ast::native_abi_rust_intrinsic) {
- for ni in nmod.items {
+ for nmod.items.each {|ni|
alt ni.node {
ast::native_item_fn(decl, tps) {
check_native_fn(tcx, decl);
fn check_crate(tcx: ty::ctxt, crate: @ast::crate,
opts: [(option, bool)], time: bool) {
let lint_opts = lint::merge_opts(crate.node.attrs, opts);
- for (lopt, switch) in lint_opts {
+ for lint_opts.each {|opt|
+ let (lopt, switch) = opt;
if switch == true {
lopt.run(tcx, crate, time);
}
let mut is_mutbl = false;
alt ty::get(auto_unbox.t).struct {
ty::ty_rec(fields) {
- for fld: ty::field in fields {
+ for fields.each {|fld|
if str::eq(ident, fld.ident) {
is_mutbl = fld.mt.mutbl == m_mutbl;
break;
}
none { false }
};
- for fld: ty::field_ty in ty::lookup_class_fields(tcx, did) {
+ for ty::lookup_class_fields(tcx, did).each {|fld|
if str::eq(ident, fld.ident) {
is_mutbl = fld.mutability == class_mutable
|| in_self; // all fields can be mutated
visit::visit_decl(d, cx, v);
alt d.node {
decl_local(locs) {
- for loc in locs {
+ for locs.each {|loc|
alt loc.node.init {
some(init) {
if init.op == init_move { check_move_rhs(cx, init.expr); }
check_lval(cx, dest, msg_assign);
}
expr_fn(_, _, _, cap) {
- for moved in cap.moves {
+ for cap.moves.each {|moved|
let def = cx.tcx.def_map.get(moved.id);
alt is_illegal_to_modify_def(cx, def, msg_move_out) {
some(name) { mk_err(cx, moved.span, msg_move_out, moved.name); }
fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
let arg_ts = ty::ty_fn_args(ty::expr_ty(cx.tcx, f));
let mut i = 0u;
- for arg_t: ty::arg in arg_ts {
+ for arg_ts.each {|arg_t|
alt ty::resolved_mode(cx.tcx, arg_t.mode) {
by_mutbl_ref { check_lval(cx, args[i], msg_mutbl_ref); }
by_move { check_lval(cx, args[i], msg_move_out); }
fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
let arg_ts = ty::ty_fn_args(ty::expr_ty(cx.tcx, f));
let mut i = 0u;
- for arg in args {
+ for args.each {|arg|
alt arg {
some(expr) {
let o_msg = alt ty::resolved_mode(cx.tcx, arg_ts[i].mode) {
--- /dev/null
+iface lattice<T> {
+ fn lub(T, T) -> cres<T>;
+ fn glb(T, T) -> cres<T>;
+}
+
+iface lattice_op<T> {
+ fn bnd<V:copy>(b: bounds<V>) -> option<V>;
+ fn with_bnd<V:copy>(b: bounds<V>, v: V) -> bounds<V>;
+}
+
+iface pairwise {
+ fn infcx() -> infer_ctxt;
+ fn tag() -> str;
+
+ fn c_tys(t1: ty::t, t2: ty::t) -> cres<ty::t>;
+ fn c_flds(a: ty::field, b: ty::field) -> cres<ty::field>;
+ fn c_bot(b: ty::t) -> cres<ty::t>;
+ fn c_mts(a: ty::mt, b: ty::mt) -> cres<ty::mt>;
+ fn c_contratys(t1: ty::t, t2: ty::t) -> cres<ty::t>;
+ fn c_protos(p1: ast::proto, p2: ast::proto) -> cres<ast::proto>;
+ fn c_ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
+
+ // Combining regions (along with some specific cases that are
+ // different for LUB/GLB):
+ fn c_regions(
+ a: ty::region, b: ty::region) -> cres<ty::region>;
+ fn c_regions_scope_scope(
+ a: ty::region, a_id: ast::node_id,
+ b: ty::region, b_id: ast::node_id) -> cres<ty::region>;
+ fn c_regions_free_scope(
+ a: ty::region, a_id: ast::node_id, a_br: ty::bound_region,
+ b: ty::region, b_id: ast::node_id) -> cres<ty::region>;
+}
+
+fn c_vars<V:copy vid, PW:pairwise, T:copy to_str st>(
+ self: PW, vb: vals_and_bindings<V, T>,
+ a_t: T, a_vid: V, b_vid: V,
+ c_ts: fn(T, T) -> cres<T>) -> cres<T> {
+
+ // The comments in this function are written for LUB and types,
+ // but they apply equally well to GLB and regions if you inverse
+ // upper/lower/sub/super/etc.
+
+ // Need to find a type that is a supertype of both a and b:
+ let {root: a_vid, bounds: a_bounds} = self.infcx().get(vb, a_vid);
+ let {root: b_vid, bounds: b_bounds} = self.infcx().get(vb, b_vid);
+
+ #debug["%s.c_vars(%s=%s <: %s=%s)",
+ self.tag(),
+ a_vid.to_str(), a_bounds.to_str(self.infcx()),
+ b_vid.to_str(), b_bounds.to_str(self.infcx())];
+
+ if a_vid == b_vid {
+ ret ok(a_t);
+ }
+
+ // If both A and B have an UB type, then we can just compute the
+ // LUB of those types:
+ let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds);
+ alt (a_bnd, b_bnd) {
+ (some(a_ty), some(b_ty)) {
+ alt self.infcx().try {|| c_ts(a_ty, b_ty) } {
+ ok(t) { ret ok(t); }
+ err(_) { /*fallthrough */ }
+ }
+ }
+ _ {/*fallthrough*/}
+ }
+
+ // Otherwise, we need to merge A and B into one variable. We can
+ // then use either variable as an upper bound:
+ self.infcx().vars(vb, a_vid, b_vid).then {||
+ ok(a_t)
+ }
+}
+
+fn c_var_t<V:copy vid, PW:pairwise, T:copy to_str st>(
+ self: PW, vb: vals_and_bindings<V, T>,
+ a_vid: V, b: T,
+ c_ts: fn(T, T) -> cres<T>) -> cres<T> {
+
+ let {root: a_id, bounds: a_bounds} = self.infcx().get(vb, a_vid);
+
+ // The comments in this function are written for LUB, but they
+ // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
+
+ #debug["%s.c_var_ty(%s=%s <: %s)",
+ self.tag(),
+ a_id.to_str(), a_bounds.to_str(self.infcx()),
+ b.to_str(self.infcx())];
+
+ alt self.bnd(a_bounds) {
+ some(a_bnd) {
+ // If a has an upper bound, return it.
+ ret c_ts(a_bnd, b);
+ }
+ none {
+ // If a does not have an upper bound, make b the upper bound of a
+ // and then return b.
+ let a_bounds = self.with_bnd(a_bounds, b);
+ self.infcx().bnds(a_bounds.lb, a_bounds.ub).then {||
+ self.infcx().set(vb, a_id, bounded(a_bounds));
+ ok(b)
+ }
+ }
+ }
+}
+
+fn c_tuptys<PW:pairwise>(self: PW, as: [ty::t], bs: [ty::t])
+ -> cres<[ty::t]> {
+
+ if check vec::same_length(as, bs) {
+ map2(as, bs) {|a, b| self.c_tys(a, b) }
+ } else {
+ err(ty::terr_tuple_size(as.len(), bs.len()))
+ }
+}
+
+fn c_tps<PW:pairwise>(self: PW, _did: ast::def_id, as: [ty::t], bs: [ty::t])
+ -> cres<[ty::t]> {
+ // FIXME #1973 lookup the declared variance of the type parameters
+ // based on did
+ if check vec::same_length(as, bs) {
+ map2(as, bs) {|a,b| self.c_tys(a, b) }
+ } else {
+ err(ty::terr_ty_param_size(as.len(), bs.len()))
+ }
+}
+
+fn c_fieldvecs<PW:pairwise>(
+ self: PW, as: [ty::field], bs: [ty::field])
+ -> cres<[ty::field]> {
+
+ if check vec::same_length(as, bs) {
+ map2(as, bs) {|a,b| self.c_flds(a, b) }
+ } else {
+ err(ty::terr_record_size(as.len(), bs.len()))
+ }
+}
+
+fn c_flds<PW:pairwise>(
+ self: PW, a: ty::field, b: ty::field) -> cres<ty::field> {
+
+ if a.ident == b.ident {
+ self.c_mts(a.mt, b.mt).chain {|mt|
+ ok({ident: a.ident, mt: mt})
+ }
+ } else {
+ err(ty::terr_record_fields(a.ident, b.ident))
+ }
+}
+
+fn c_modes<PW:pairwise>(
+ self: PW, a: ast::mode, b: ast::mode)
+ -> cres<ast::mode> {
+
+ let tcx = self.infcx().tcx;
+ ty::unify_mode(tcx, a, b)
+}
+
+fn c_args<PW:pairwise>(
+ self: PW, a: ty::arg, b: ty::arg)
+ -> cres<ty::arg> {
+
+ self.c_modes(a.mode, b.mode).chain {|m|
+ // Note: contravariant
+ self.c_contratys(b.ty, a.ty).chain {|t|
+ ok({mode: m, ty: t})
+ }
+ }
+}
+
+fn c_argvecs<PW:pairwise>(
+ self: PW, a_args: [ty::arg], b_args: [ty::arg]) -> cres<[ty::arg]> {
+
+ if check vec::same_length(a_args, b_args) {
+ map2(a_args, b_args) {|a, b| self.c_args(a, b) }
+ } else {
+ err(ty::terr_arg_count)
+ }
+}
+
+fn c_fns<PW:pairwise>(
+ self: PW, a_f: ty::fn_ty, b_f: ty::fn_ty) -> cres<ty::fn_ty> {
+
+ self.c_protos(a_f.proto, b_f.proto).chain {|p|
+ self.c_ret_styles(a_f.ret_style, b_f.ret_style).chain {|rs|
+ self.c_argvecs(a_f.inputs, b_f.inputs).chain {|inputs|
+ self.c_tys(a_f.output, b_f.output).chain {|output|
+ //FIXME self.infcx().constrvecs(a_f.constraints,
+ //FIXME b_f.constraints).then {||
+ ok({proto: p,
+ inputs: inputs,
+ output: output,
+ ret_style: rs,
+ constraints: a_f.constraints})
+ //FIXME }
+ }
+ }
+ }
+ }
+}
+
+fn c_tys<PW:pairwise>(
+ self: PW, a: ty::t, b: ty::t) -> cres<ty::t> {
+
+ let tcx = self.infcx().tcx;
+
+ #debug("%s.c_tys(%s, %s)",
+ self.tag(),
+ ty_to_str(tcx, a),
+ ty_to_str(tcx, b));
+
+ // Fast path.
+ if a == b { ret ok(a); }
+
+ alt (ty::get(a).struct, ty::get(b).struct) {
+ (ty::ty_bot, _) { self.c_bot(b) }
+ (_, ty::ty_bot) { self.c_bot(b) }
+
+ (ty::ty_var(a_id), ty::ty_var(b_id)) {
+ self.c_vars(self.infcx().vb,
+ a, a_id, b_id,
+ {|x, y| self.c_tys(x, y) })
+ }
+
+ // Note that the LUB/GLB operations are commutative:
+ (ty::ty_var(v_id), _) {
+ self.c_var_t(self.infcx().vb,
+ v_id, b,
+ {|x, y| self.c_tys(x, y) })
+ }
+ (_, ty::ty_var(v_id)) {
+ self.c_var_t(self.infcx().vb,
+ v_id, a,
+ {|x, y| self.c_tys(x, y) })
+ }
+
+ (ty::ty_nil, _) |
+ (ty::ty_bool, _) |
+ (ty::ty_int(_), _) |
+ (ty::ty_uint(_), _) |
+ (ty::ty_float(_), _) |
+ (ty::ty_str, _) {
+ let cfg = tcx.sess.targ_cfg;
+ if ty::mach_sty(cfg, a) == ty::mach_sty(cfg, b) {
+ ok(a)
+ } else {
+ err(ty::terr_mismatch)
+ }
+ }
+
+ (ty::ty_param(a_n, _), ty::ty_param(b_n, _)) if a_n == b_n {
+ ok(a)
+ }
+
+ (ty::ty_enum(a_id, a_tps), ty::ty_enum(b_id, b_tps))
+ if a_id == b_id {
+ self.c_tps(a_id, a_tps, b_tps).chain {|tps|
+ ok(ty::mk_enum(tcx, a_id, tps))
+ }
+ }
+
+ (ty::ty_iface(a_id, a_tps), ty::ty_iface(b_id, b_tps))
+ if a_id == b_id {
+ self.c_tps(a_id, a_tps, b_tps).chain {|tps|
+ ok(ty::mk_iface(tcx, a_id, tps))
+ }
+ }
+
+ (ty::ty_class(a_id, a_tps), ty::ty_class(b_id, b_tps))
+ if a_id == b_id {
+ // FIXME variance
+ self.c_tps(a_id, a_tps, b_tps).chain {|tps|
+ ok(ty::mk_class(tcx, a_id, tps))
+ }
+ }
+
+ (ty::ty_box(a_mt), ty::ty_box(b_mt)) {
+ self.c_mts(a_mt, b_mt).chain {|mt|
+ ok(ty::mk_box(tcx, mt))
+ }
+ }
+
+ (ty::ty_uniq(a_mt), ty::ty_uniq(b_mt)) {
+ self.c_mts(a_mt, b_mt).chain {|mt|
+ ok(ty::mk_uniq(tcx, mt))
+ }
+ }
+
+ (ty::ty_vec(a_mt), ty::ty_vec(b_mt)) {
+ self.c_mts(a_mt, b_mt).chain {|mt|
+ ok(ty::mk_vec(tcx, mt))
+ }
+ }
+
+ (ty::ty_ptr(a_mt), ty::ty_ptr(b_mt)) {
+ self.c_mts(a_mt, b_mt).chain {|mt|
+ ok(ty::mk_ptr(tcx, mt))
+ }
+ }
+
+ (ty::ty_rptr(a_r, a_mt), ty::ty_rptr(b_r, b_mt)) {
+ self.c_regions(a_r, b_r).chain {|r|
+ self.c_mts(a_mt, b_mt).chain {|mt|
+ ok(ty::mk_rptr(tcx, r, mt))
+ }
+ }
+ }
+
+ (ty::ty_res(a_id, a_t, a_tps), ty::ty_res(b_id, b_t, b_tps))
+ if a_id == b_id {
+ self.c_tys(a_t, b_t).chain {|t|
+ self.c_tps(a_id, a_tps, b_tps).chain {|tps|
+ ok(ty::mk_res(tcx, a_id, t, tps))
+ }
+ }
+ }
+
+ (ty::ty_rec(a_fields), ty::ty_rec(b_fields)) {
+ self.c_fieldvecs(a_fields, b_fields).chain {|fs|
+ ok(ty::mk_rec(tcx, fs))
+ }
+ }
+
+ (ty::ty_tup(a_tys), ty::ty_tup(b_tys)) {
+ self.c_tuptys(a_tys, b_tys).chain {|ts|
+ ok(ty::mk_tup(tcx, ts))
+ }
+ }
+
+ (ty::ty_fn(a_fty), ty::ty_fn(b_fty)) {
+ self.c_fns(a_fty, b_fty).chain {|fty|
+ ok(ty::mk_fn(tcx, fty))
+ }
+ }
+
+ (ty::ty_constr(a_t, a_constrs), ty::ty_constr(b_t, b_constrs)) {
+ self.c_tys(a_t, b_t).chain {|t|
+ self.infcx().constrvecs(a_constrs, b_constrs).then {||
+ ok(ty::mk_constr(tcx, t, a_constrs))
+ }
+ }
+ }
+
+ _ { err(ty::terr_mismatch) }
+ }
+}
+
+fn c_regions<PW:pairwise>(
+ self: PW, a: ty::region, b: ty::region) -> cres<ty::region> {
+
+ #debug["%s.c_regions(%?, %?)",
+ self.tag(),
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx())];
+
+ alt (a, b) {
+ (ty::re_var(a_id), ty::re_var(b_id)) {
+ self.c_vars(self.infcx().rb,
+ a, a_id, b_id,
+ {|x, y| self.c_regions(x, y) })
+ }
+
+ (ty::re_var(v_id), r) |
+ (r, ty::re_var(v_id)) {
+ self.c_var_t(self.infcx().rb,
+ v_id, r,
+ {|x, y| self.c_regions(x, y) })
+ }
+
+ (f @ ty::re_free(f_id, f_br), s @ ty::re_scope(s_id)) |
+ (s @ ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
+ self.c_regions_free_scope(f, f_id, f_br, s, s_id)
+ }
+
+ (ty::re_scope(a_id), ty::re_scope(b_id)) {
+ self.c_regions_scope_scope(a, a_id, b, b_id)
+ }
+
+ // For these types, we cannot define any additional relationship:
+ (ty::re_free(_, _), ty::re_free(_, _)) |
+ (ty::re_bound(_), ty::re_bound(_)) |
+ (ty::re_bound(_), ty::re_free(_, _)) |
+ (ty::re_bound(_), ty::re_scope(_)) |
+ (ty::re_free(_, _), ty::re_bound(_)) |
+ (ty::re_scope(_), ty::re_bound(_)) {
+ if a == b {
+ #debug["... yes, %s == %s.",
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx())];
+ ok(a)
+ } else {
+ #debug["... no, %s != %s.",
+ a.to_str(self.infcx()),
+ b.to_str(self.infcx())];
+ err(ty::terr_regions_differ(false, b, a))
+ }
+ }
+
+ (ty::re_default, _) |
+ (_, ty::re_default) {
+ // actually a compiler bug, I think.
+ err(ty::terr_regions_differ(false, b, a))
+ }
+ }
+}
it(pat);
alt pat.node {
pat_ident(pth, some(p)) { walk_pat(p, it); }
- pat_rec(fields, _) { for f in fields { walk_pat(f.pat, it); } }
- pat_enum(_, s) | pat_tup(s) { for p in s { walk_pat(p, it); } }
+ pat_rec(fields, _) { for fields.each {|f| walk_pat(f.pat, it); } }
+ pat_enum(_, s) | pat_tup(s) { for s.each {|p| walk_pat(p, it); } }
pat_box(s) | pat_uniq(s) { walk_pat(s, it); }
pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, none) {}
}
// }
}
+ ast::re_static { /* fallthrough */ }
+
ast::re_named(ident) {
alt cx.scope.resolve_ident(ident) {
some(r) {
record_parent(cx, blk.node.id);
// Resolve queued locals to this block.
- for local_id in cx.queued_locals {
+ for cx.queued_locals.each {|local_id|
cx.region_map.local_blocks.insert(local_id, blk.node.id);
}
alt ty::get(t).struct {
ty::ty_rptr(region, _) {
alt region {
- ty::re_bound(_) | ty::re_free(_, _) {
+ ty::re_bound(_) | ty::re_free(_, _) | ty::re_static {
/* ok */
}
ty::re_scope(rbi) {
fn iter_export_paths(vi: ast::view_item, f: fn(vp: @ast::view_path)) {
alt vi.node {
ast::view_item_export(vps) {
- for vp in vps {
+ for vps.each {|vp|
f(vp);
}
}
fn iter_import_paths(vi: ast::view_item, f: fn(vp: @ast::view_path)) {
alt vi.node {
ast::view_item_import(vps) {
- for vp in vps {
- f(vp);
- }
+ for vps.each {|vp| f(vp);}
}
_ {}
}
e.imports.insert(id, is_glob(path, sc, vp.span));
}
ast::view_path_list(mod_path, idents, _) {
- for ident in idents {
+ for idents.each {|ident|
let t = todo(ident.node.name,
@(*mod_path + [ident.node.name]),
ident.span, sc);
e.sess.abort_if_errors();
fn walk_expr(e: @env, exp: @ast::expr, sc: scopes, v: vt<scopes>) {
- visit_expr_with_scope(exp, sc, v);
+ visit::visit_expr(exp, sc, v);
alt exp.node {
ast::expr_path(p) {
maybe_insert(e, exp.id,
fn walk_tps(e: @env, tps: [ast::ty_param], sc: scopes, v: vt<scopes>) {
let outer_current_tp = e.current_tp;
let mut current = 0u;
- for tp in tps {
+ for tps.each {|tp|
e.current_tp = some(current);
- for bound in *tp.bounds {
+ for vec::each(*tp.bounds) {|bound|
alt bound {
bound_iface(t) { v.visit_ty(t, sc, v); }
_ {}
visit::visit_ty_params(tps, sc, v);
alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} }
v.visit_ty(sty, sc, v);
- for m in methods {
+ for methods.each {|m|
v.visit_ty_params(m.tps, sc, v);
let msc = cons(scope_method(m.self_id, tps + m.tps), @sc);
v.visit_fn(visit::fk_method(m.ident, [], m),
}
ast::item_iface(tps, methods) {
visit::visit_ty_params(tps, sc, v);
- for m in methods {
+ for methods.each {|m|
let msc = cons(scope_method(i.id, tps + m.tps), @sc);
- for a in m.decl.inputs { v.visit_ty(a.ty, msc, v); }
+ for m.decl.inputs.each {|a| v.visit_ty(a.ty, msc, v); }
v.visit_ty(m.decl.output, msc, v);
}
}
ctor.node.body, ctor.span, ctor.node.id,
ctor_scope, v);
/* visit the items */
- for cm in members {
+ for members.each {|cm|
alt cm.node {
class_method(m) {
let msc = cons(scope_method(m.self_id, tps + m.tps),
// here's where we need to set up the mapping
// for f's constrs in the table.
- for c: @ast::constr in decl.constraints { resolve_constr(e, c, sc, v); }
+ for decl.constraints.each {|c| resolve_constr(e, c, sc, v); }
let scope = alt fk {
visit::fk_item_fn(_, tps) | visit::fk_res(_, tps) |
visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps)
fn visit_block_with_scope(b: ast::blk, sc: scopes, v: vt<scopes>) {
let pos = @mut 0u, loc = @mut 0u;
let block_sc = cons(scope_block(b, pos, loc), @sc);
- for vi in b.node.view_items { v.visit_view_item(vi, block_sc, v); }
- for stmt in b.node.stmts {
+ for b.node.view_items.each {|vi| v.visit_view_item(vi, block_sc, v); }
+ for b.node.stmts.each {|stmt|
v.visit_stmt(stmt, block_sc, v);;
*pos += 1u;;
*loc = 0u;
};
alt d.node {
decl_local(locs) {
- for loc in locs { v.visit_local(loc, sc, v);; *loc_pos += 1u; }
+ for locs.each {|loc| v.visit_local(loc, sc, v);; *loc_pos += 1u; }
}
decl_item(it) { v.visit_item(it, sc, v); }
}
}
fn visit_arm_with_scope(a: ast::arm, sc: scopes, v: vt<scopes>) {
- for p: @pat in a.pats { v.visit_pat(p, sc, v); }
+ for a.pats.each {|p| v.visit_pat(p, sc, v); }
let sc_inner = cons(scope_arm(a), @sc);
visit::visit_expr_opt(a.guard, sc_inner, v);
v.visit_block(a.body, sc_inner, v);
}
-fn visit_expr_with_scope(x: @ast::expr, sc: scopes, v: vt<scopes>) {
- alt x.node {
- ast::expr_for(decl, coll, blk) {
- let new_sc = cons(scope_loop(decl), @sc);
- v.visit_expr(coll, sc, v);
- v.visit_local(decl, new_sc, v);
- v.visit_block(blk, new_sc, v);
- }
- _ { visit::visit_expr(x, sc, v); }
- }
-}
-
// This is only for irrefutable patterns (e.g. ones that appear in a let)
// So if x occurs, and x is already known to be a enum, that's always an error
fn visit_local_with_scope(e: @env, loc: @local, sc:scopes, v:vt<scopes>) {
fn find_imports_after(e: env, id: node_id, sc: scopes) -> [node_id] {
fn lst(my_id: node_id, vis: [@view_item]) -> [node_id] {
let mut imports = [], found = false;
- for vi in vis {
+ for vis.each {|vi|
iter_effective_import_paths(*vi) {|vp|
alt vp.node {
view_path_simple(_, _, id)
if found { imports += [id]; }
}
view_path_list(_, ids, _) {
- for id in ids {
+ for ids.each {|id|
if id.node.id == my_id { found = true; }
if found { imports += [id.node.id]; }
}
in_scope(sc) {
alt find_fn_or_mod_scope(sc) {
some(err_scope) {
- for rs: {ident: str, sc: scope} in e.reported {
+ for e.reported.each {|rs|
if str::eq(rs.ident, name) && err_scope == rs.sc { ret; }
}
e.reported += [{ident: name, sc: err_scope}];
fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
-> option<def> {
let mut n = 0u;
- for tp: ast::ty_param in ty_params {
+ for ty_params.each {|tp|
if str::eq(tp.ident, name) && alt e.current_tp {
some(cur) { n < cur } none { true }
} { ret some(ast::def_ty_param(local_def(tp.id), n)); }
ns: namespace) -> option<def> {
alt ns {
ns_val {
- for a: ast::arg in decl.inputs {
+ for decl.inputs.each {|a|
if str::eq(a.ident, name) {
ret some(ast::def_arg(a.id, a.mode));
}
} else {
alt ns {
ns_val {
- for v: ast::variant in variants {
+ for variants.each {|v|
if str::eq(v.node.name, name) {
let i = v.node.id;
ret some(ast::def_variant
_ { }
}
}
- for vi in b.view_items {
-
+ for b.view_items.each {|vi|
let mut is_import = false;
alt vi.node {
ast::view_item_import(_) { is_import = true; }
alt vi.node {
ast::view_item_import(vps) | ast::view_item_export(vps) {
- for vp in vps {
+ for vps.each {|vp|
alt vp.node {
ast::view_path_simple(ident, _, id) {
if is_import && name == ident {
}
ast::view_path_list(path, idents, _) {
- for ident in idents {
+ for idents.each {|ident|
if name == ident.node.name {
ret lookup_import(e, ident.node.id, ns);
}
else if vec::len(matches) == 1u {
ret some(matches[0].def);
} else {
- for match: glob_imp_def in matches {
+ for matches.each {|match|
let sp = match.path.span;
e.sess.span_note(sp, #fmt["'%s' is imported here", id]);
}
fn index_view_items(view_items: [@ast::view_item],
index: hashmap<ident, list<mod_index_entry>>) {
- for vi in view_items {
+ for view_items.each {|vi|
alt vi.node {
ast::view_item_use(ident, _, id) {
add_to_index(index, ident, mie_view_item(ident, id, vi.span));
add_to_index(index, ident, mie_import_ident(id, vp.span));
}
ast::view_path_list(_, idents, _) {
- for ident in idents {
+ for idents.each {|ident|
add_to_index(index, ident.node.name,
mie_import_ident(ident.node.id,
ident.span));
index_view_items(md.view_items, index);
- for it: @ast::item in md.items {
+ for md.items.each {|it|
alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_native_mod(_) | ast::item_ty(_, _) |
ast::item_enum(variants, _) {
add_to_index(index, it.ident, mie_item(it));
let mut variant_idx: uint = 0u;
- for v: ast::variant in variants {
+ for variants.each {|v|
add_to_index(index, v.node.name,
mie_enum_variant(variant_idx, variants,
it.id, it.span));
index_view_items(md.view_items, index);
- for it: @ast::native_item in md.items {
+ for md.items.each {|it|
add_to_index(index, it.ident, mie_native_item(it));
}
ret index;
fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->
option<def> {
- for d: def in csearch::lookup_defs(e.sess.cstore, cnum, ids) {
+ let mut result = none;
+ for csearch::lookup_defs(e.sess.cstore, cnum, ids).each {|d|
e.ext_map.insert(def_id_of_def(d), ids);
- if ns_ok(ns, ns_for_def(d)) { ret some(d); }
+ if ns_ok(ns, ns_for_def(d)) { result = some(d); }
}
- ret none;
+ ret result;
}
fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
fn typaram_names(tps: [ast::ty_param]) -> [ident] {
let mut x: [ast::ident] = [];
- for tp: ast::ty_param in tps { x += [tp.ident]; }
+ for tps.each {|tp| x += [tp.ident]; }
ret x;
}
visit::visit_item(i, x, v);
e.sess.span_err(a.pats[i].span,
"inconsistent number of bindings");
} else {
- for name: ident in ch.seen {
+ for ch.seen.each {|name|
if is_none(vec::find(seen0, bind str::eq(name, _))) {
// Fight the alias checker
let name_ = name;
let values = checker(*e, "value");
let types = checker(*e, "type");
let mods = checker(*e, "module");
- for st: @ast::stmt in b.node.stmts {
+ for b.node.stmts.each {|st|
alt st.node {
ast::stmt_decl(d, _) {
alt d.node {
ast::decl_local(locs) {
let local_values = checker(*e, "value");
- for loc in locs {
+ for locs.each {|loc|
pat_util::pat_bindings(e.def_map, loc.node.pat)
{|_i, p_sp, n|
let ident = path_to_ident(n);
alt it.node {
ast::item_enum(variants, _) {
add_name(types, it.span, it.ident);
- for v: ast::variant in variants {
+ for variants.each {|v|
add_name(values, v.span, v.node.name);
}
}
}
fn check_name(ch: checker, sp: span, name: ident) {
- for s: ident in ch.seen {
+ for ch.seen.each {|s|
if str::eq(s, name) {
ch.sess.span_fatal(sp, "duplicate " + ch.kind + " name: " + name);
}
fn ensure_unique<T>(e: env, sp: span, elts: [T], id: fn(T) -> ident,
kind: str) {
let ch = checker(e, kind);
- for elt: T in elts { add_name(ch, sp, id(elt)); }
+ for elts.each {|elt| add_name(ch, sp, id(elt)); }
}
fn check_exports(e: @env) {
[ found_def_item(item, ns_val),
found_def_item(item, ns_type),
found_def_item(item, ns_module) ];
- for d in defs {
+ for defs.each {|d|
alt d {
some(def) {
f(ident, def);
fn maybe_add_reexport(e: @env, export_id: node_id, def: option<def>) {
- option::with_option_do(def) {|def|
+ option::iter(def) {|def|
add_export(e, export_id, def_id_of_def(def), true);
}
}
ids: [ast::path_list_ident]) {
let parent_id = check_enum_ok(e, span, id, _mod);
add_export(e, export_id, local_def(parent_id), false);
- for variant_id in ids {
+ for ids.each {|variant_id|
let mut found = false;
alt _mod.index.find(variant_id.node.name) {
some(ms) {
some(m) {
let glob_is_re_exported = int_hash();
- for vi in m.view_items {
+ for m.view_items.each {|vi|
iter_export_paths(*vi) { |vp|
alt vp.node {
ast::view_path_simple(ident, _, id) {
}
// Now follow the export-glob links and fill in the
// globbed_exports and exp_map lists.
- for glob in _mod.glob_imports {
+ for _mod.glob_imports.each {|glob|
let id = alt check glob.path.node {
ast::view_path_glob(_, node_id) { node_id }
};
ast::view_path_simple(name, pt, id) {
let mut found = [];
if vec::len(*pt) == 1u {
- option::with_option_do(sc) {|sc|
+ option::iter(sc) {|sc|
list::iter(sc) {|level|
if vec::len(found) == 0u {
- for imp in *level {
+ for vec::each(*level) {|imp|
if imp.ident == pt[0] {
found += [@{ident: name with *imp}];
}
}
} else {
lookup_imported_impls(e, id) {|is|
- for i in *is { impls += [@{ident: name with *i}]; }
+ for vec::each(*is) {|i|
+ impls += [@{ident: name with *i}];
+ }
}
}
}
ast::view_path_list(base, names, _) {
- for nm in names {
+ for names.each {|nm|
lookup_imported_impls(e, nm.node.id) {|is| impls += *is; }
}
}
let mut tmp = [];
let mi = e.mod_map.get(defid.node);
let md = option::get(mi.m);
- for vi in md.view_items {
+ for md.view_items.each {|vi|
find_impls_in_view_item(e, vi, tmp, none);
}
- for i in md.items {
+ for md.items.each {|i|
find_impls_in_item(e, i, tmp, none, none);
}
@vec::filter(tmp) {|i| is_exported(e, i.ident, mi)}
}
alt name {
some(n) {
- for im in *cached {
+ for vec::each(*cached) {|im|
if n == im.ident { impls += [im]; }
}
}
fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
v: vt<iscopes>) {
let mut impls = [];
- for vi in b.node.view_items {
+ for b.node.view_items.each {|vi|
find_impls_in_view_item(*e, vi, impls, some(sc));
}
- for st in b.node.stmts {
+ for b.node.stmts.each {|st|
alt st.node {
ast::stmt_decl(@{node: ast::decl_item(i), _}, _) {
find_impls_in_item(*e, i, impls, none, none);
fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, id: node_id,
sc: iscopes, v: vt<iscopes>) {
let mut impls = [];
- for vi in m.view_items {
+ for m.view_items.each {|vi|
find_impls_in_view_item(*e, vi, impls, some(sc));
}
- for i in m.items { find_impls_in_item(*e, i, impls, none, none); }
+ for m.items.each {|i| find_impls_in_item(*e, i, impls, none, none); }
let impls = @impls;
visit::visit_mod(m, s, id, if vec::len(*impls) > 0u {
cons(impls, @sc)
let then_cx = scope_block(bcx, "then");
then_cx.block_span = some(thn.span);
let else_cx = scope_block(bcx, "else");
- option::with_option_do(els) {|e| else_cx.block_span = some(e.span); }
+ option::iter(els) {|e| else_cx.block_span = some(e.span); }
CondBr(bcx, cond_val, then_cx.llbb, else_cx.llbb);
let then_bcx = trans_block(then_cx, thn, then_dest);
let then_bcx = trans_block_cleanups(then_bcx, then_cx);
ret join_returns(cx, [then_bcx, else_bcx], [then_dest, else_dest], dest);
}
-fn trans_for(cx: block, local: @ast::local, seq: @ast::expr,
- body: ast::blk) -> block {
- let _icx = cx.insn_ctxt("trans_for");
- fn inner(bcx: block, local: @ast::local, curr: ValueRef, t: ty::t,
- body: ast::blk, outer_next_cx: block) -> block {
- let next_cx = sub_block(bcx, "next");
- let scope_cx = loop_scope_block(bcx, cont_other(next_cx),
- outer_next_cx, "for loop scope",
- body.span);
- Br(bcx, scope_cx.llbb);
- let curr = PointerCast(bcx, curr,
- T_ptr(type_of(bcx.ccx(), t)));
- let bcx = alt::bind_irrefutable_pat(scope_cx, local.node.pat,
- curr, false);
- let bcx = trans_block(bcx, body, ignore);
- cleanup_and_Br(bcx, scope_cx, next_cx.llbb);
- ret next_cx;
- }
- let ccx = cx.ccx();
- let next_cx = sub_block(cx, "next");
- let seq_ty = expr_ty(cx, seq);
- let {bcx: bcx, val: seq} = trans_temp_expr(cx, seq);
- let seq = PointerCast(bcx, seq, T_ptr(ccx.opaque_vec_type));
- let mut fill = tvec::get_fill(bcx, seq);
- if ty::type_is_str(seq_ty) {
- fill = Sub(bcx, fill, C_int(ccx, 1));
- }
- let bcx = tvec::iter_vec_raw(bcx, seq, seq_ty, fill,
- bind inner(_, local, _, _, body, next_cx));
- Br(bcx, next_cx.llbb);
- ret next_cx;
-}
-
fn trans_while(cx: block, cond: @ast::expr, body: ast::blk)
-> block {
let _icx = cx.insn_ctxt("trans_while");
Unreachable(bcx);
} else if ret_in_loop {
bcx = with_cond(bcx, Load(bcx, option::get(ret_flag))) {|bcx|
- option::with_option_do(bcx.fcx.loop_ret) {|lret|
+ option::iter(bcx.fcx.loop_ret) {|lret|
Store(bcx, C_bool(true), lret.flagptr);
Store(bcx, C_bool(false), bcx.fcx.llretptr);
}
loop {
alt cur.kind {
block_scope(info) {
- for cleanup in info.cleanups {
+ for info.cleanups.each {|cleanup|
alt cleanup {
clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) {
if cleanup_type == normal_exit_and_unwind {
let ty_fields = alt check ty::get(t).struct { ty::ty_rec(f) { f } };
let mut temp_cleanups = [];
- for fld in fields {
+ for fields.each {|fld|
let ix = option::get(vec::position(ty_fields, {|ft|
str::eq(fld.node.ident, ft.ident)
}));
let mut i = 0;
bcx = cx;
// Copy over inherited fields
- for tf in ty_fields {
+ for ty_fields.each {|tf|
if !vec::any(fields, {|f| str::eq(f.node.ident, tf.ident)}) {
let dst = GEPi(bcx, addr, [0, i]);
let base = GEPi(bcx, base_val, [0, i]);
// Now revoke the cleanups as we pass responsibility for the data
// structure on to the caller
- for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
+ for temp_cleanups.each {|cleanup| revoke_clean(bcx, cleanup); }
ret bcx;
}
trans_check_expr(bcx, a, "Claim")
};
}
- ast::expr_for(decl, seq, body) {
- assert dest == ignore;
- ret trans_for(bcx, decl, seq, body);
- }
ast::expr_while(cond, body) {
assert dest == ignore;
ret trans_while(bcx, cond, body);
let _icx = bcx.insn_ctxt("cleanup_and_leave");
let mut cur = bcx, bcx = bcx;
let is_lpad = leave == none;
+ let mut done = false;
loop {
alt cur.kind {
block_scope(info) if info.cleanups.len() > 0u {
- for cp in info.cleanup_paths {
- if cp.target == leave {
- Br(bcx, cp.dest);
- ret;
- }
+ option::iter(vec::find(info.cleanup_paths,
+ {|cp| cp.target == leave})) {|cp|
+ Br(bcx, cp.dest);
+ done = true;
}
+ if done { ret; }
let sub_cx = sub_block(bcx, "cleanup");
Br(bcx, sub_cx.llbb);
info.cleanup_paths += [{target: leave, dest: sub_cx.llbb}];
}
let val = alloc_ty(cx, t);
if cx.sess().opts.debuginfo {
- option::with_option_do(simple_name) {|name|
+ option::iter(simple_name) {|name|
str::as_c_str(name, {|buf|
llvm::LLVMSetValueName(val, buf)
});
let mut bcx = bcx_top;
// Initialize fields to zero so init assignments can validly
// drop their LHS
- for field in fields {
+ for fields.each {|field|
let ix = field_idx_strict(bcx.tcx(), sp, field.ident, fields);
bcx = zero_alloca(bcx, GEPi(bcx, selfptr, [0, ix]),
field.mt.ty);
}
-fn decl_crate_map(sess: session::session, mapname: str,
+fn decl_crate_map(sess: session::session, mapmeta: link::link_meta,
llmod: ModuleRef) -> ValueRef {
let targ_cfg = sess.targ_cfg;
let int_type = T_int(targ_cfg);
let mut n_subcrates = 1;
let cstore = sess.cstore;
while cstore::have_crate_data(cstore, n_subcrates) { n_subcrates += 1; }
- let mapname = if sess.building_library { mapname } else { "toplevel" };
+ let mapname = if sess.building_library {
+ mapmeta.name + "_" + mapmeta.vers + "_" + mapmeta.extras_hash
+ } else { "toplevel" };
let sym_name = "_rust_crate_map_" + mapname;
let arrtype = T_array(int_type, n_subcrates as uint);
let maptype = T_struct([int_type, arrtype]);
ret map;
}
-// FIXME use hashed metadata instead of crate names once we have that
fn fill_crate_map(ccx: @crate_ctxt, map: ValueRef) {
let mut subcrates: [ValueRef] = [];
let mut i = 1;
let cstore = ccx.sess.cstore;
while cstore::have_crate_data(cstore, i) {
- let nm = "_rust_crate_map_" + cstore::get_crate_data(cstore, i).name;
+ let cdata = cstore::get_crate_data(cstore, i);
+ let nm = "_rust_crate_map_" + cdata.name +
+ "_" + cstore::get_crate_vers(cstore, i) +
+ "_" + cstore::get_crate_hash(cstore, i);
let cr = str::as_c_str(nm, {|buf|
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
});
lib::llvm::associate_type(tn, "taskptr", taskptr_type);
let tydesc_type = T_tydesc(targ_cfg);
lib::llvm::associate_type(tn, "tydesc", tydesc_type);
- let crate_map = decl_crate_map(sess, link_meta.name, llmod);
+ let crate_map = decl_crate_map(sess, link_meta, llmod);
let dbg_cx = if sess.opts.debuginfo {
option::some(debuginfo::mk_ctxt(llmod_id))
} else {
}
}
}
- option::with_option_do(include_ret_handle) {|flagptr|
+ option::iter(include_ret_handle) {|flagptr|
let our_ret = alt bcx.fcx.loop_ret {
some({retptr, _}) { retptr }
none { bcx.fcx.llretptr }
// drop glue checks whether it is zero.
fn revoke_clean(cx: block, val: ValueRef) {
in_scope_cx(cx) {|info|
- let mut i = 0u;
- for cu in info.cleanups {
- alt cu {
- clean_temp(v, _, _) if v == val {
- info.cleanups =
- vec::slice(info.cleanups, 0u, i) +
- vec::slice(info.cleanups, i + 1u, info.cleanups.len());
- scope_clean_changed(info);
- break;
- }
- _ {}
- }
- i += 1u;
+ option::iter(vec::position(info.cleanups, {|cu|
+ alt cu { clean_temp(v, _, _) if v == val { true } _ { false } }
+ })) {|i|
+ info.cleanups =
+ vec::slice(info.cleanups, 0u, i) +
+ vec::slice(info.cleanups, i + 1u, info.cleanups.len());
+ scope_clean_changed(info);
}
}
}
h = h * alt param {
mono_precise(ty, vts) {
let mut h = ty::type_id(ty);
- option::with_option_do(vts) {|vts|
+ option::iter(vts) {|vts|
for vec::each(vts) {|vt| h += hash_mono_id(vt); }
}
h
eq: fn(md: T) -> bool) -> option<T> unsafe {
if cache.contains_key(mdtag) {
let items = cache.get(mdtag);
- for item in items {
+ for items.each {|item|
let md: T = md_from_metadata::<T>(item);
if eq(md) {
ret option::some(md);
option::get(cx.dbg_cx).names("rec"),
line_from_span(cx.sess.codemap,
span) as int);
- for field in fields {
+ for fields.each {|field|
let field_t = ty::get_field(t, field.node.ident).mt.ty;
let ty_md = create_ty(cx, field_t, field.node.mt.ty);
let (size, align) = size_and_align_of(cx, field_t);
}
fn traverse_export(cx: ctx, exp_id: node_id) {
- option::with_option_do(cx.exp_map.find(exp_id)) {|defs|
+ option::iter(cx.exp_map.find(exp_id)) {|defs|
for vec::each(defs) {|def| traverse_def_id(cx, def.id); }
}
}
ty::ty_class(did, ts) {
// same as records
let mut s = [shape_struct], sub = [];
- for f:field in ty::class_items_as_fields(ccx.tcx, did, ts) {
+ for ty::class_items_as_fields(ccx.tcx, did, ts).each {|f|
sub += shape_of(ccx, f.mt.ty, ty_param_map);
}
add_substr(s, sub);
let data_sz = vec::len(data) as u16;
let mut info_sz = 0u16;
- for did_ in ccx.shape_cx.tag_order {
+ for ccx.shape_cx.tag_order.each {|did_|
let did = did_; // Satisfy alias checker.
let num_variants = vec::len(*ty::enum_variants(ccx.tcx, did)) as u16;
add_u16(header, header_sz + info_sz);
let mut lv_table = [];
i = 0u;
- for did_ in ccx.shape_cx.tag_order {
+ for ccx.shape_cx.tag_order.each {|did_|
let did = did_; // Satisfy alias checker.
let variants = ty::enum_variants(ccx.tcx, did);
add_u16(info, vec::len(*variants) as u16);
}
}
expr_path(_) {
- option::with_option_do(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
+ option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id));
vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst|
type_needs(cx, uses, subst)
}
}
}
- expr_for(_, _, _) | expr_do_while(_, _) | expr_alt(_, _, _) |
+ expr_do_while(_, _) | expr_alt(_, _, _) |
expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
expr_lit(_) | expr_assert(_) | expr_check(_, _) |
},
visit_block: {|b, cx, v|
visit::visit_block(b, cx, v);
- option::with_option_do(b.node.expr) {|e|
+ option::iter(b.node.expr) {|e|
node_type_needs(cx, use_repr, e.id);
}
},
}
fn init_vecs(ccx: crate_ctxt, node_ids: [node_id], len: uint) {
- for i: node_id in node_ids {
+ for node_ids.each {|i|
log(debug, int::str(i) + " |-> " + uint::str(len));
add_node(ccx, i, empty_ann(len));
}
fn comma_str(args: [@constr_arg_use]) -> str {
let mut rslt = "";
let mut comma = false;
- for a: @constr_arg_use in args {
+ for args.each {|a|
if comma { rslt += ", "; } else { comma = true; }
alt a.node {
carg_base { rslt += "*"; }
fn tritv_to_str(fcx: fn_ctxt, v: tritv::t) -> str {
let mut s = "";
let mut comma = false;
- for p: norm_constraint in constraints(fcx) {
+ for constraints(fcx).each {|p|
alt tritv_get(v, p.bit_num) {
dont_care { }
tt {
fn first_difference_string(fcx: fn_ctxt, expected: tritv::t, actual: tritv::t)
-> str {
- let s: str = "";
- for c: norm_constraint in constraints(fcx) {
+ let mut s = "";
+ for constraints(fcx).each {|c|
if tritv_get(expected, c.bit_num) == ttrue &&
tritv_get(actual, c.bit_num) != ttrue {
- ret constraint_to_str(fcx.ccx.tcx, c.c);
+ s = constraint_to_str(fcx.ccx.tcx, c.c);
+ break;
}
}
ret s;
fn tos(v: [uint]) -> str {
let mut rslt = "";
- for i: uint in v {
+ for v.each {|i|
if i == 0u {
rslt += "0";
} else if i == 1u { rslt += "1"; } else { rslt += "?"; }
}
cpred(p, descs) {
let mut rslt: [norm_constraint] = [];
- for pd: pred_args in *descs {
+ for vec::each(*descs) {|pd|
rslt +=
[{bit_num: pd.node.bit_num,
c: respan(pd.span, npred(p, id, pd.node.args))}];
occ: [@constr_arg_use]) -> uint {
#debug("match_args: looking at %s",
constr_args_to_str(fn@(i: inst) -> str { ret i.ident; }, occ));
- for pd: pred_args in *occs {
+ for vec::each(*occs) {|pd|
log(debug,
"match_args: candidate " + pred_args_to_str(pd));
fn eq(p: inst, q: inst) -> bool { ret p.node == q.node; }
fn exprs_to_constr_args(tcx: ty::ctxt, args: [@expr]) -> [@constr_arg_use] {
let f = bind expr_to_constr_arg(tcx, _);
let mut rslt: [@constr_arg_use] = [];
- for e: @expr in args { rslt += [f(e)]; }
+ for args.each {|e| rslt += [f(e)]; }
rslt
}
fn substitute_constr_args(cx: ty::ctxt, actuals: [@expr], c: @ty::constr) ->
tsconstr {
let mut rslt: [@constr_arg_use] = [];
- for a: @constr_arg in c.node.args {
+ for c.node.args.each {|a|
rslt += [substitute_arg(cx, actuals, a)];
}
ret npred(c.node.path, c.node.id, rslt);
fn pred_args_matches(pattern: [constr_arg_general_<inst>], desc: pred_args) ->
bool {
let mut i = 0u;
- for c: @constr_arg_use in desc.node.args {
+ for desc.node.args.each {|c|
let n = pattern[i];
alt c.node {
carg_ident(p) {
fn find_instance_(pattern: [constr_arg_general_<inst>], descs: [pred_args]) ->
option<uint> {
- for d: pred_args in descs {
+ for descs.each {|d|
if pred_args_matches(pattern, d) { ret some(d.node.bit_num); }
}
ret none;
alt c {
cinit(_, _, _) {/* this is dealt with separately */ }
cpred(p, descs) {
- for d: pred_args in *descs {
+ for vec::each(copy *descs) {|d|
if args_mention(d.node.args, find_in_subst_bool, subst) {
let old_bit_num = d.node.bit_num;
let newv = replace(subst, d);
}
fn find_in_subst(id: node_id, s: subst) -> option<inst> {
- for p: {from: inst, to: inst} in s {
+ for s.each {|p|
if id == p.from.node { ret some(p.to); }
}
ret none;
fn insts_to_str(stuff: [constr_arg_general_<inst>]) -> str {
let mut rslt = "<";
- for i: constr_arg_general_<inst> in stuff {
+ for stuff.each {|i|
rslt +=
" " +
alt i {
fn replace(subst: subst, d: pred_args) -> [constr_arg_general_<inst>] {
let mut rslt: [constr_arg_general_<inst>] = [];
- for c: @constr_arg_use in d.node.args {
+ for d.node.args.each {|c|
alt c.node {
carg_ident(p) {
alt find_in_subst(p.node, subst) {
// replace any occurrences of the src def_id with the
// dest def_id
let insts = find_instances(fcx, subst, val);
- for p: {from: uint, to: uint} in insts {
+ for insts.each {|p|
if promises_(p.from, src_post) {
set_in_poststate_(p.to, target_post);
}
let d = local_node_id_to_local_def_id(fcx, dead_v);
alt d {
some(d_id) {
- for c: norm_constraint in constraints(fcx) {
+ for constraints(fcx).each {|c|
if constraint_mentions(fcx, c, d_id) {
#debug("clearing constraint %u %s",
c.bit_num,
let d = local_node_id_to_local_def_id(fcx, dead_v);
alt d {
some(d_id) {
- for c: norm_constraint in constraints(fcx) {
+ for constraints(fcx).each {|c|
if non_init_constraint_mentions(fcx, c, d_id) {
clear_in_postcond(c.bit_num,
node_id_to_ts_ann(fcx.ccx,
let mut changed = false;
alt d {
some(d_id) {
- for c: norm_constraint in constraints(fcx) {
+ for constraints(fcx).each {|c|
if constraint_mentions(fcx, c, d_id) {
changed |= clear_in_poststate_(c.bit_num, p);
}
let mut changed = false;
alt d {
some(d_id) {
- for c: norm_constraint in constraints(fcx) {
+ for constraints(fcx).each {|c|
if non_init_constraint_mentions(fcx, c, d_id) {
changed |= clear_in_poststate_(c.bit_num, p);
}
}
fn any_eq(v: [node_id], d: node_id) -> bool {
- for i: node_id in v { if i == d { ret true; } }
+ for v.each {|i| if i == d { ret true; } }
false
}
ret vec::any(bind mentions(s,q,_), args);
*/
- for a: @constr_arg_use in args {
+ for args.each {|a|
alt a.node { carg_ident(p1) { if q(s, p1.node) { ret true; } } _ { } }
}
ret false;
// FIXME: This should be a function in vec::.
fn vec_contains(v: @mut [node_id], i: node_id) -> bool {
- for d: node_id in *v { if d == i { ret true; } }
+ for vec::each(*v) {|d| if d == i { ret true; } }
ret false;
}
indices: [@sp_constr_arg<uint>]) -> [@constr_arg_use] {
let mut actuals: [@constr_arg_use] = [];
let num_args = vec::len(args);
- for a: @sp_constr_arg<uint> in indices {
+ for indices.each {|a|
actuals +=
[@respan(a.span,
alt a.node {
fn locals_to_bindings(tcx: ty::ctxt, locals: [@local]) -> [binding] {
let mut rslt = [];
- for loc in locals { rslt += [local_to_bindings(tcx, loc)]; }
+ for locals.each {|loc| rslt += [local_to_bindings(tcx, loc)]; }
ret rslt;
}
alt ty::get(ty).struct {
ty::ty_fn({inputs: args, _}) {
let mut modes = [];
- for arg: ty::arg in args { modes += [arg.mode]; }
+ for args.each {|arg| modes += [arg.mode]; }
ret modes;
}
_ {
fn anon_bindings(ops: [init_op], es: [@expr]) -> [binding] {
let mut bindings: [binding] = [];
let mut i = 0;
- for op: init_op in ops {
+ for ops.each {|op|
bindings += [{lhs: [], rhs: some({op: op, expr: es[i]})}];
i += 1;
}
let sz = vec::len(ps);
if sz >= 1u {
let prev = tritv_clone(ps[0]);
- for p: postcond in vec::slice(ps, 1u, sz) { seq_tritv(prev, p); }
+ vec::iter_between(ps, 1u, sz) {|p| seq_tritv(prev, p); }
ret prev;
} else { ret ann::empty_poststate(num_constraints(fcx.enclosing)); }
}
fn check_unused_vars(fcx: fn_ctxt) {
// FIXME: could be more efficient
- for c: norm_constraint in constraints(fcx) {
+ for constraints(fcx).each {|c|
alt c.c.node {
ninit(id, v) {
if !vec_contains(fcx.enclosing.used_vars, id) && v[0] != '_' as u8
// If it's a call, generate appropriate instances of the
// call's constraints.
expr_call(operator, operands, _) {
- for c: @ty::constr in constraints_expr(cx.tcx, operator) {
+ for constraints_expr(cx.tcx, operator).each {|c|
let ct: sp_constr =
respan(c.span,
aux::substitute_constr_args(cx.tcx, operands, c));
/* now we have to add bit nums for both the constraints
and the variables... */
- for c: sp_constr in { *cx.cs } {
- next = add_constraint(cx.tcx, c, next, res_map);
+ let mut i = 0u, l = vec::len(*cx.cs);
+ while i < l {
+ next = add_constraint(cx.tcx, cx.cs[i], next, res_map);
+ i += 1u;
}
/* if this function has any constraints, instantiate them to the
argument names and add them */
- let mut sc;
- for c: @constr in f_decl.constraints {
- sc = ast_constr_to_sp_constr(cx.tcx, f_decl.inputs, c);
+ for f_decl.constraints.each {|c|
+ let sc = ast_constr_to_sp_constr(cx.tcx, f_decl.inputs, c);
next = add_constraint(cx.tcx, sc, next, res_map);
}
/* Need to add constraints for args too, b/c they
can be deinitialized */
- for a: arg in f_decl.inputs {
+ for f_decl.inputs.each {|a|
next = add_constraint(
cx.tcx,
respan(f_sp, ninit(a.id, a.ident)),
item_class(_,_,_) {
fail "find_pre_post_item: implement item_class";
}
- item_impl(_, _, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
+ item_impl(_, _, _, ms) {
+ for ms.each {|m| find_pre_post_method(ccx, m); }
+ }
}
}
log_expr(*args[0]);
}
fn do_one(fcx: fn_ctxt, e: @expr) { find_pre_post_expr(fcx, e); }
- for e: @expr in args { do_one(fcx, e); }
+ for args.each {|e| do_one(fcx, e); }
fn get_pp(ccx: crate_ctxt, &&e: @expr) -> pre_and_post {
ret expr_pp(ccx, e);
fn find_pre_post_expr_fn_upvars(fcx: fn_ctxt, e: @expr) {
let rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
- for def in *freevars::get_freevars(fcx.ccx.tcx, e.id) {
+ for vec::each(*freevars::get_freevars(fcx.ccx.tcx, e.id)) {|def|
log(debug, ("handle_var_def: def=", def));
handle_var_def(fcx, rslt, def.def, "upvar");
}
find_pre_post_exprs(fcx, args, e.id);
/* see if the call has any constraints on its type */
- for c: @ty::constr in constraints_expr(fcx.ccx.tcx, operator) {
+ for constraints_expr(fcx.ccx.tcx, operator).each {|c|
let i =
bit_num(fcx, substitute_constr_args(fcx.ccx.tcx, args, c));
require(i, expr_pp(fcx.ccx, e));
let use_cap_item = fn@(&&cap_item: @capture_item) {
let d = local_node_id_to_local_def_id(fcx, cap_item.id);
- option::with_option_do(d, { |id| use_var(fcx, id) });
+ option::iter(d, { |id| use_var(fcx, id) });
};
vec::iter(cap_clause.copies, use_cap_item);
vec::iter(cap_clause.moves, use_cap_item);
set_pre_and_post(fcx.ccx, e.id, block_precond(fcx.ccx, body),
loop_postcond);
}
- expr_for(d, index, body) {
- find_pre_post_loop(fcx, d, index, body, e.id);
- }
expr_index(val, sub) { find_pre_post_exprs(fcx, [val, sub], e.id); }
expr_alt(ex, alts, _) {
find_pre_post_expr(fcx, ex);
ret block_pp(fcx.ccx, an_alt.body);
}
let mut alt_pps = [];
- for a: arm in alts { alt_pps += [do_an_alt(fcx, a)]; }
+ for alts.each {|a| alt_pps += [do_an_alt(fcx, a)]; }
fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, &&pp: pre_and_post,
&&next: pre_and_post) -> pre_and_post {
union(pp.precondition, seq_preconds(fcx, [antec, next]));
let mut cmodes = callee_modes(fcx, operator.id);
let mut modes = [];
let mut i = 0;
- for expr_opt: option<@expr> in maybe_args {
+ for maybe_args.each {|expr_opt|
alt expr_opt {
none {/* no-op */ }
some(expr) { modes += [cmodes[i]]; args += [expr]; }
stmt_decl(adecl, id) {
alt adecl.node {
decl_local(alocals) {
- let mut e_pp;
let prev_pp = empty_pre_post(num_constraints(fcx.enclosing));
- for alocal in alocals {
+ for alocals.each {|alocal|
alt alocal.node.init {
some(an_init) {
/* LHS always becomes initialized,
/* Clear out anything that the previous initializer
guaranteed */
- e_pp = expr_pp(fcx.ccx, an_init.expr);
+ let e_pp = expr_pp(fcx.ccx, an_init.expr);
tritv_copy(prev_pp.precondition,
seq_preconds(fcx, [prev_pp, e_pp]));
/* Include the LHSs too, since those aren't in the
log_pp_err(stmt_pp(fcx.ccx, *s));
*/
}
- for s: @stmt in b.node.stmts { do_one_(fcx, s); }
+ for b.node.stmts.each {|s| do_one_(fcx, s); }
fn do_inner_(fcx: fn_ctxt, &&e: @expr) { find_pre_post_expr(fcx, e); }
let do_inner = bind do_inner_(fcx, _);
option::map::<@expr, ()>(b.node.expr, do_inner);
let mut pps: [pre_and_post] = [];
- for s: @stmt in b.node.stmts { pps += [stmt_pp(fcx.ccx, *s)]; }
+ for b.node.stmts.each {|s| pps += [stmt_pp(fcx.ccx, *s)]; }
alt b.node.expr {
none {/* no-op */ }
some(e) { pps += [expr_pp(fcx.ccx, e)]; }
let block_precond = seq_preconds(fcx, pps);
let mut postconds = [];
- for pp: pre_and_post in pps { postconds += [get_post(pp)]; }
+ for pps.each {|pp| postconds += [get_post(pp)]; }
/* A block may be empty, so this next line ensures that the postconds
vector is non-empty. */
{changed: bool, post: poststate} {
let mut changed = false;
let mut post = tritv_clone(pres);
- for b: binding in bindings {
+ for bindings.each {|b|
alt b.rhs {
some(an_init) {
// an expression, with or without a destination
changed |=
find_pre_post_state_expr(fcx, post, an_init.expr) || changed;
post = tritv_clone(expr_poststate(fcx.ccx, an_init.expr));
- for i: inst in b.lhs {
+ for b.lhs.each {|i|
alt an_init.expr.node {
expr_path(p) {
handle_move_or_copy(fcx, post, p, an_init.expr.id, i,
}
}
none {
- for i: inst in b.lhs {
+ for b.lhs.each {|i|
// variables w/o an initializer
clear_in_poststate_ident_(fcx, i.node, i.ident, post);
}
let callee_ops = callee_arg_init_ops(fcx, operator.id);
let mut ops = [];
let mut i = 0;
- for a_opt: option<@expr> in maybe_args {
+ for maybe_args.each {|a_opt|
alt a_opt {
none {/* no-op */ }
some(a) { ops += [callee_ops[i]]; args += [a]; }
let base_pres = alt vec::last_opt(exs) { none { pres }
some(f) { expr_poststate(fcx.ccx, f) }};
- option::with_option_do(maybe_base, {|base|
+ option::iter(maybe_base, {|base|
changed |= find_pre_post_state_expr(fcx, base_pres, base) |
set_poststate_ann(fcx.ccx, e.id,
expr_poststate(fcx.ccx, base))});
false_postcond(num_constrs));
}
}
- expr_for(d, index, body) {
- ret find_pre_post_state_loop(fcx, pres, d, index, body, e.id);
- }
expr_index(val, sub) {
ret find_pre_post_state_two(fcx, pres, val, sub, e.id, oper_pure);
}
let mut a_post;
if vec::len(alts) > 0u {
a_post = false_postcond(num_constrs);
- for an_alt: arm in alts {
+ for alts.each {|an_alt|
alt an_alt.guard {
some(e) {
changed |= find_pre_post_state_expr(fcx, e_post, e);
handle_fail(fcx, pres, post);
ret set_prestate_ann(fcx.ccx, e.id, pres) |
set_poststate_ann(fcx.ccx, e.id, post) |
- option::with_option(maybe_fail_val, false, {|fail_val|
+ option::map_default(maybe_fail_val, false, {|fail_val|
find_pre_post_state_expr(fcx, pres, fail_val)});
}
expr_check(_, p) {
initializes. Then <pres> becomes the new poststate. */
let mut changed = false;
- for s: @stmt in b.node.stmts {
+ for b.node.stmts.each {|s|
changed |= find_pre_post_state_stmt(fcx, pres, s);
pres = stmt_poststate(fcx.ccx, *s);
}
// Arguments start out initialized
let block_pre = block_prestate(fcx.ccx, f_body);
- for a: arg in f_decl.inputs {
+ for f_decl.inputs.each {|a|
set_in_prestate_constr(fcx, ninit(a.id, a.ident), block_pre);
}
// Instantiate any constraints on the arguments so we can use them
- for c: @constr in f_decl.constraints {
+ for f_decl.constraints.each {|c|
let tsc = ast_constr_to_ts_constr(fcx.ccx.tcx, f_decl.inputs, c);
set_in_prestate_constr(fcx, tsc, block_pre);
}
re_free(node_id, bound_region),
re_scope(node_id),
re_var(region_vid),
+ re_static, // effectively `top` in the region lattice
re_default
}
terr_mode_mismatch(mode, mode),
terr_constr_len(uint, uint),
terr_constr_mismatch(@type_constr, @type_constr),
- terr_regions_differ(bool /* variance */, region, region),
+ terr_regions_differ(region, region),
+ terr_in_field(@type_err, str),
+ terr_sorts(t, t)
}
enum param_bound {
fn param_bounds_to_kind(bounds: param_bounds) -> kind {
let mut kind = kind_noncopyable;
- for bound in *bounds {
+ for vec::each(*bounds) {|bound|
alt bound {
bound_copy {
if kind != kind_sendable { kind = kind_copyable; }
region_map: @middle::region::region_map) -> ctxt {
let interner = map::hashmap({|&&k: intern_key|
hash_type_structure(k.struct) +
- option::with_option(k.o_def_id, 0u, ast_util::hash_def_id)
+ option::map_default(k.o_def_id, 0u, ast_util::hash_def_id)
}, {|&&a, &&b| a == b});
@{interner: interner,
mut next_id: 0u,
ty_param(_, _) { has_params = true; }
ty_var(_) | ty_self(_) { has_vars = true; }
ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) {
- for tt in tys { derive_flags(has_params, has_vars, has_rptrs, tt); }
+ for tys.each {|tt|
+ derive_flags(has_params, has_vars, has_rptrs, tt);
+ }
}
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) {
derive_flags(has_params, has_vars, has_rptrs, m.ty);
derive_flags(has_params, has_vars, has_rptrs, m.ty);
}
ty_rec(flds) {
- for f in flds {
+ for flds.each {|f|
derive_flags(has_params, has_vars, has_rptrs, f.mt.ty);
}
}
ty_tup(ts) {
- for tt in ts { derive_flags(has_params, has_vars, has_rptrs, tt); }
+ for ts.each {|tt| derive_flags(has_params, has_vars, has_rptrs, tt); }
}
ty_fn(f) {
- for a in f.inputs {
+ for f.inputs.each {|a|
derive_flags(has_params, has_vars, has_rptrs, a.ty);
}
derive_flags(has_params, has_vars, has_rptrs, f.output);
}
ty_res(_, tt, tps) {
derive_flags(has_params, has_vars, has_rptrs, tt);
- for tt in tps { derive_flags(has_params, has_vars, has_rptrs, tt); }
+ for tps.each {|tt|
+ derive_flags(has_params, has_vars, has_rptrs, tt);
+ }
}
ty_constr(tt, _) {
derive_flags(has_params, has_vars, has_rptrs, tt);
}
ty_enum(_, subtys) | ty_iface(_, subtys) | ty_class(_, subtys)
| ty_self(subtys) {
- for subty: t in subtys { maybe_walk_ty(subty, f); }
+ for subtys.each {|subty| maybe_walk_ty(subty, f); }
}
ty_rec(fields) {
- for fl: field in fields { maybe_walk_ty(fl.mt.ty, f); }
+ for fields.each {|fl| maybe_walk_ty(fl.mt.ty, f); }
}
- ty_tup(ts) { for tt in ts { maybe_walk_ty(tt, f); } }
+ ty_tup(ts) { for ts.each {|tt| maybe_walk_ty(tt, f); } }
ty_fn(ft) {
- for a: arg in ft.inputs { maybe_walk_ty(a.ty, f); }
+ for ft.inputs.each {|a| maybe_walk_ty(a.ty, f); }
maybe_walk_ty(ft.output, f);
}
ty_res(_, sub, tps) {
maybe_walk_ty(sub, f);
- for tp: t in tps { maybe_walk_ty(tp, f); }
+ for tps.each {|tp| maybe_walk_ty(tp, f); }
}
ty_constr(sub, _) { maybe_walk_ty(sub, f); }
ty_uniq(tm) { maybe_walk_ty(tm.ty, f); }
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_type | ty_ptr(_) | ty_rptr(_, _) { false }
ty_rec(flds) {
- for f in flds { if type_needs_drop(cx, f.mt.ty) { accum = true; } }
+ for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } }
accum
}
ty_class(did, ts) {
- for f in ty::class_items_as_fields(cx, did, ts)
- { if type_needs_drop(cx, f.mt.ty) { accum = true; } }
+ for vec::each(ty::class_items_as_fields(cx, did, ts)) {|f|
+ if type_needs_drop(cx, f.mt.ty) { accum = true; }
+ }
accum
}
ty_tup(elts) {
- for m in elts { if type_needs_drop(cx, m) { accum = true; } }
+ for elts.each {|m| if type_needs_drop(cx, m) { accum = true; } }
accum
}
ty_enum(did, tps) {
let variants = enum_variants(cx, did);
- for variant in *variants {
- for aty in variant.args {
+ for vec::each(*variants) {|variant|
+ for variant.args.each {|aty|
// Perform any type parameter substitutions.
let arg_ty = substitute_type_params(cx, tps, aty);
if type_needs_drop(cx, arg_ty) { accum = true; }
true
}
ty_enum(did, tps) {
- for v in *enum_variants(cx, did) {
- for aty in v.args {
+ for vec::each(*enum_variants(cx, did)) {|v|
+ for v.args.each {|aty|
let t = substitute_type_params(cx, tps, aty);
needs_unwind_cleanup |=
type_needs_unwind_cleanup_(cx, t, tycache,
// Records lower to the lowest of their members.
ty_rec(flds) {
let mut lowest = kind_sendable;
- for f in flds { lowest = lower_kind(lowest, type_kind(cx, f.mt.ty)); }
+ for flds.each {|f|
+ lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
+ }
lowest
}
// Tuples lower to the lowest of their members.
ty_tup(tys) {
let mut lowest = kind_sendable;
- for ty in tys { lowest = lower_kind(lowest, type_kind(cx, ty)); }
+ for tys.each {|ty| lowest = lower_kind(lowest, type_kind(cx, ty)); }
lowest
}
// Enums lower to the lowest of their variants.
if vec::len(*variants) == 0u {
lowest = kind_noncopyable;
} else {
- for variant in *variants {
- for aty in variant.args {
+ for vec::each(*variants) {|variant|
+ for variant.args.each {|aty|
// Perform any type parameter substitutions.
let arg_ty = substitute_type_params(cx, tps, aty);
lowest = lower_kind(lowest, type_kind(cx, arg_ty));
if test(sty) { ret true; }
alt sty {
ty_enum(did, tps) {
- for variant in *enum_variants(cx, did) {
- for aty in variant.args {
+ for vec::each(*enum_variants(cx, did)) {|variant|
+ for variant.args.each {|aty|
let sty = substitute_type_params(cx, tps, aty);
if type_structurally_contains(cx, sty, test) { ret true; }
}
ret false;
}
ty_rec(fields) {
- for field in fields {
+ for fields.each {|field|
if type_structurally_contains(cx, field.mt.ty, test) { ret true; }
}
ret false;
}
ty_tup(ts) {
- for tt in ts {
+ for ts.each {|tt|
if type_structurally_contains(cx, tt, test) { ret true; }
}
ret false;
// Structural types
ty_enum(did, tps) {
let variants = enum_variants(cx, did);
- for variant: variant_info in *variants {
+ for vec::each(*variants) {|variant|
let tup_ty = mk_tup(cx, variant.args);
// Perform any type parameter substitutions.
}
}
ty_rec(flds) {
- for f: field in flds {
+ for flds.each {|f|
if !type_is_pod(cx, f.mt.ty) { result = false; }
}
}
ty_tup(elts) {
- for elt in elts { if !type_is_pod(cx, elt) { result = false; } }
+ for elts.each {|elt| if !type_is_pod(cx, elt) { result = false; } }
}
ty_res(_, inner, tps) {
result = type_is_pod(cx, substitute_type_params(cx, tps, inner));
fn hash_subty(id: uint, subty: t) -> uint { (id << 2u) + type_id(subty) }
fn hash_subtys(id: uint, subtys: [t]) -> uint {
let mut h = id;
- for s in subtys { h = (h << 2u) + type_id(s) }
+ for subtys.each {|s| h = (h << 2u) + type_id(s) }
h
}
fn hash_type_constr(id: uint, c: @type_constr) -> uint {
let mut h = id;
h = (h << 2u) + hash_def(h, c.node.id);
// FIXME this makes little sense
- for a in c.node.args {
+ for c.node.args.each {|a|
alt a.node {
carg_base { h += h << 2u; }
carg_lit(_) { fail "lit args not implemented yet"; }
re_scope(id) { ((id as uint) << 2u) | 2u }
re_var(id) { (id.to_uint() << 2u) | 3u }
re_default { 4u }
+ re_bot { 5u }
}
}
alt st {
ty_str { 17u }
ty_enum(did, tys) {
let mut h = hash_def(18u, did);
- for typ: t in tys { h = hash_subty(h, typ); }
+ for tys.each {|typ| h = hash_subty(h, typ); }
h
}
ty_box(mt) { hash_subty(19u, mt.ty) }
ty_vec(mt) { hash_subty(21u, mt.ty) }
ty_rec(fields) {
let mut h = 26u;
- for f in fields { h = hash_subty(h, f.mt.ty); }
+ for fields.each {|f| h = hash_subty(h, f.mt.ty); }
h
}
ty_tup(ts) { hash_subtys(25u, ts) }
ty_fn(f) {
let mut h = 27u;
- for a in f.inputs { h = hash_subty(h, a.ty); }
+ for f.inputs.each {|a| h = hash_subty(h, a.ty); }
hash_subty(h, f.output)
}
ty_var(v) { hash_uint(30u, v.to_uint()) }
ty_param(pid, did) { hash_def(hash_uint(31u, pid), did) }
ty_self(ts) {
let mut h = 28u;
- for t in ts { h = hash_subty(h, t); }
+ for ts.each {|t| h = hash_subty(h, t); }
h
}
ty_type { 32u }
}
ty_constr(t, cs) {
let mut h = hash_subty(36u, t);
- for c in cs { h = (h << 2u) + hash_type_constr(h, c); }
+ for cs.each {|c| h = (h << 2u) + hash_type_constr(h, c); }
h
}
ty_uniq(mt) { hash_subty(37u, mt.ty) }
ty_iface(did, tys) {
let mut h = hash_def(40u, did);
- for typ: t in tys { h = hash_subty(h, typ); }
+ for tys.each {|typ| h = hash_subty(h, typ); }
h
}
ty_opaque_closure_ptr(ck_block) { 41u }
ty_opaque_box { 44u }
ty_class(did, tys) {
let mut h = hash_def(45u, did);
- for typ: t in tys { h = hash_subty(h, typ); }
+ for tys.each {|typ| h = hash_subty(h, typ); }
h
}
}
a: [@sp_constr_arg<T>],
b: [@sp_constr_arg<T>]) -> bool {
let mut i: uint = 0u;
- for arg: @sp_constr_arg<T> in a {
+ for a.each {|arg|
if !arg_eq(eq, arg, b[i]) { ret false; }
i += 1u;
}
fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool {
if vec::len(cs) != vec::len(ds) { ret false; }
let mut i = 0u;
- for c: @constr in cs { if !constr_eq(c, ds[i]) { ret false; } i += 1u; }
+ for cs.each {|c| if !constr_eq(c, ds[i]) { ret false; } i += 1u; }
ret true;
}
fn field_idx(id: ast::ident, fields: [field]) -> option<uint> {
let mut i = 0u;
- for f in fields { if f.ident == id { ret some(i); } i += 1u; }
+ for fields.each {|f| if f.ident == id { ret some(i); } i += 1u; }
ret none;
}
fn method_idx(id: ast::ident, meths: [method]) -> option<uint> {
let mut i = 0u;
- for m in meths { if m.ident == id { ret some(i); } i += 1u; }
+ for meths.each {|m| if m.ident == id { ret some(i); } i += 1u; }
ret none;
}
}
}
+fn ty_sort_str(cx: ctxt, t: t) -> str {
+ alt get(t).struct {
+ ty_nil | ty_bot | ty_bool | ty_int(_) |
+ ty_uint(_) | ty_float(_) | ty_str | ty_type | ty_opaque_box |
+ ty_opaque_closure_ptr(_) {
+ ty_to_str(cx, t)
+ }
+
+ ty_enum(_, _) { "enum" }
+ ty_box(_) { "@-ptr" }
+ ty_uniq(_) { "~-ptr" }
+ ty_vec(_) { "vector" }
+ ty_ptr(_) { "*-ptr" }
+ ty_rptr(_, _) { "&-ptr" }
+ ty_rec(_) { "record" }
+ ty_fn(_) { "fn" }
+ ty_iface(_, _) { "iface" }
+ ty_class(_, _) { "class" }
+ ty_res(_, _, _) { "resource" }
+ ty_tup(_) { "tuple" }
+ ty_var(_) { "variable" }
+ ty_param(_, _) { "type parameter" }
+ ty_self(_) { "self" }
+ ty_constr(t, _) { ty_sort_str(cx, t) }
+ }
+}
+
fn type_err_to_str(cx: ctxt, err: type_err) -> str {
alt err {
terr_mismatch { ret "types differ"; }
}
terr_record_mutability { ret "record elements differ in mutability"; }
terr_record_fields(e_fld, a_fld) {
- ret "expected a record with field '" + e_fld +
- "' but found one with field '" + a_fld + "'";
+ ret "expected a record with field `" + e_fld +
+ "` but found one with field `" + a_fld + "`";
}
terr_arg_count { ret "incorrect number of function parameters"; }
terr_mode_mismatch(e_mode, a_mode) {
" but found one with constraint " +
ty_constr_to_str(a_constr);
}
- terr_regions_differ(true, region_a, region_b) {
- ret #fmt("reference lifetime %s does not match reference lifetime %s",
- region_to_str(cx, region_a), region_to_str(cx, region_b));
- }
- terr_regions_differ(false, subregion, superregion) {
+ terr_regions_differ(subregion, superregion) {
ret #fmt("references with lifetime %s do not outlive references with \
lifetime %s",
region_to_str(cx, subregion),
region_to_str(cx, superregion));
}
+ terr_in_field(err, fname) {
+ ret #fmt("in field `%s`, %s", fname, type_err_to_str(cx, *err));
+ }
+ terr_sorts(exp, act) {
+ ret #fmt("%s vs %s", ty_sort_str(cx, exp), ty_sort_str(cx, act));
+ }
}
}
sp: span) -> def_id {
if check is_local(did) {
let ms = lookup_class_method_ids(cx, did);
- for m in ms {
+ for ms.each {|m|
if m.name == name {
ret ast_util::local_def(m.id);
}
fn class_field_tys(items: [@class_member]) -> [field_ty] {
let mut rslt = [];
- for it in items {
+ for items.each {|it|
alt it.node {
instance_var(nm, _, cm, id, privacy) {
rslt += [{ident: nm, id: ast_util::local_def(id),
fn class_items_as_fields(cx:ctxt, did: ast::def_id, substs: [ty::t])
-> [field] {
let mut rslt = [];
- for f in lookup_class_fields(cx, did) {
+ for lookup_class_fields(cx, did).each {|f|
// consider all instance vars mut, because the
// constructor may mutate all vars
rslt += [{ident: f.ident, mt:
import std::serialization::{serialize_uint, deserialize_uint};
import std::ufind;
import syntax::print::pprust::*;
+import util::common::indent;
export check_crate;
export method_map;
// Type tests
fn structurally_resolved_type(fcx: @fn_ctxt, sp: span, tp: ty::t) -> ty::t {
alt infer::resolve_type_structure(fcx.infcx, tp) {
- result::ok(typ_s) { ret typ_s; }
- result::err(_) {
+ // 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; }
+ _ {
fcx.ccx.tcx.sess.span_fatal
(sp, "the type of this value must be known in this context");
}
tcx.sess.span_fatal(sp, "wrong number of type arguments for a \
polymorphic type");
}
- for ast_ty: @ast::ty in args {
+ for args.each {|ast_ty|
param_bindings += [do_ast_ty_to_ty(tcx, mode, ast_ty)];
}
#debug("substituting(%s into %s)",
ast::re_self | ast::re_named(_) {
tcx.region_map.ast_type_to_region.get(region.id)
}
+ ast::re_static {
+ ty::re_static
+ }
};
ty::mk_rptr(tcx, r, ast_mt_to_mt(tcx, mode, mt))
}
}
ast::ty_rec(fields) {
let mut flds: [field] = [];
- for f: ast::ty_field in fields {
+ for fields.each {|f|
let tm = ast_mt_to_mt(tcx, mode, f.node.mt);
flds += [{ident: f.node.ident, mt: tm}];
}
}
ast::ty_constr(t, cs) {
let mut out_cs = [];
- for constr: @ast::ty_constr in cs {
+ for cs.each {|constr|
out_cs += [ty::ast_constr_to_constr(tcx, constr)];
}
ty::mk_constr(tcx, do_ast_ty_to_ty(tcx, mode, t), out_cs)
fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
-> @[ty::param_bounds] {
let mut result = [];
- for param in params {
+ for params.each {|param|
result += [alt tcx.ty_param_bounds.find(param.id) {
some(bs) { bs }
none {
let mut bounds = [];
- for b in *param.bounds {
+ for vec::each(*param.bounds) {|b|
bounds += [alt b {
ast::bound_send { ty::bound_send }
ast::bound_copy { ty::bound_copy }
variants: [ast::variant],
ty_params: [ast::ty_param]) {
// Create a set of parameter types shared among all the variants.
- for variant in variants {
+ for variants.each {|variant|
// Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions.
let result_ty = if vec::len(variant.node.args) == 0u {
// As above, tell ast_ty_to_ty() that trans_ty_item_to_ty()
// should be called to resolve named types.
let mut args: [arg] = [];
- for va: ast::variant_arg in variant.node.args {
+ for variant.node.args.each {|va|
let arg_ty = {
// NDM We need BOUNDS here. It should be that this
// yields a type like "foo &anon". Basically every
i_bounds: @[ty::param_bounds], maybe_self: option<ty::t>)
-> [{mty: ty::method, id: ast::node_id, span: span}] {
let mut my_methods = [];
- for m in ms {
+ for ms.each {|m|
alt maybe_self {
some(selfty) {
write_ty_to_tcx(tcx, m.self_id, selfty);
ast::item_native_mod(m) {
if syntax::attr::native_abi(it.attrs) ==
either::right(ast::native_abi_rust_intrinsic) {
- for item in m.items { check_intrinsic_type(tcx, item); }
+ for m.items.each {|item| check_intrinsic_type(tcx, item); }
}
}
ast::item_enum(variants, ty_params) {
if did.crate == ast::local_crate {
ensure_iface_methods(tcx, did.node);
}
- for if_m in *ty::iface_methods(tcx, did) {
+ for vec::each(*ty::iface_methods(tcx, did)) {|if_m|
alt vec::find(my_methods,
{|m| if_m.ident == m.mty.ident}) {
some({mty: m, id, span}) {
/* FIXME: check for proper public/privateness */
// Write the type of each of the members
let (fields, methods) = split_class_items(members);
- for f in fields {
+ for fields.each {|f|
convert_class_item(tcx, f);
}
// The selfty is just the class type
let mut ty_param_substs: [mut ty::t] = [mut];
let mut ty_param_subst_var_ids: [ty_vid] = [];
- for ty_param_subst: ty::t in ty_param_substs_0 {
+ for ty_param_substs_0.each {|ty_param_subst|
// Generate a type variable and unify it with the type parameter
// substitution. We will then pull out these type variables.
let t_0 = next_ty_var(fcx);
ty_param_subst_var_ids: [ty_vid]) ->
ty_param_substs_and_ty {
let mut result_ty_param_substs: [ty::t] = [];
- for var_id in ty_param_subst_var_ids {
+ for ty_param_subst_var_ids.each {|var_id|
let tp_subst = ty::mk_var(fcx.ccx.tcx, var_id);
result_ty_param_substs += [tp_subst];
}
alt ty::get(tpt.ty).struct {
ty::ty_fn(f) {
// N-ary variant.
- for arg: ty::arg in f.inputs {
+ for f.inputs.each {|arg|
let arg_ty =
ty::substitute_type_params(ccx.tcx, enum_ty_params, arg.ty);
result += [arg_ty];
alt fcx.opt_node_ty_substs(id) {
some(substs) {
let mut new_substs = [];
- for subst: ty::t in substs {
+ for substs.each {|subst|
alt resolve_type_vars_in_type(fcx, sp, subst) {
some(t) { new_substs += [t]; }
none { wbcx.success = false; ret none; }
visit_local: visit_local
with *visit::default_visitor()});
visit.visit_block(blk, wbcx, visit);
- for arg in decl.inputs {
+ for decl.inputs.each {|arg|
resolve_type_vars_for_node(wbcx, arg.ty.span, arg.id);
}
ret wbcx.success;
fn matches(name: str, f: ty::field) -> bool {
ret str::eq(name, f.ident);
}
- for f: ast::field_pat in fields {
+ for fields.each {|f|
alt vec::find(ex_fields, bind matches(f.ident, _)) {
some(field) {
check_pat(pcx, f.pat, field.mt.ty);
fields", vec::len(ex_elts), e_count]);
}
let mut i = 0u;
- for elt in elts {
+ for elts.each {|elt|
check_pat(pcx, elt, ex_elts[i]);
i += 1u;
}
origin: method_origin, self_sub: option<self_subst>}> {
#debug("lookup_method_inner_: %? %? %s", ms, parent, name);
let mut i = 0u;
- for m in ms {
+ for ms.each {|m|
if m.ident == name {
let fty = ty::mk_fn(tcx, {proto: ast::proto_box with m.fty});
if ty::type_has_vars(fty) {
alt ty::get(ty).struct {
ty::ty_param(n, did) {
let mut bound_n = 0u;
- for bound in *tcx.ty_param_bounds.get(did.node) {
+ for vec::each(*tcx.ty_param_bounds.get(did.node)) {|bound|
alt bound {
ty::bound_iface(t) {
let (iid, tps) = alt check ty::get(t).struct {
let mut result = none, complained = false;
std::list::iter(fcx.ccx.impl_map.get(expr.id)) {|impls|
if option::is_none(result) {
- for @{did, methods, _} in *impls {
- alt vec::find(methods, {|m| m.ident == name}) {
+ for vec::each(*impls) {|im|
+ alt vec::find(im.methods, {|m| m.ident == name}) {
some(m) {
- let mut {n_tps, ty: self_ty} = impl_self_ty(tcx, did);
+ let mut {n_tps, ty: self_ty} = impl_self_ty(tcx, im.did);
let mut {vars, ty: self_ty} = if n_tps > 0u {
bind_params(fcx, self_ty, n_tps)
} else {
fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
expected: ty::t) -> bool {
- #debug("typechecking expr %d (%s)",
+ #debug(">> typechecking expr %d (%s)",
expr.id, syntax::print::pprust::expr_to_str(expr));
// A generic function to factor out common logic from call and bind
let check_args = fn@(check_blocks: bool) -> bool {
let mut i = 0u;
let mut bot = false;
- for a_opt in args {
+ for args.each {|a_opt|
alt a_opt {
some(a) {
let is_block = alt a.node {
fn check_call(fcx: @fn_ctxt, sp: span, f: @ast::expr, args: [@ast::expr])
-> {fty: ty::t, bot: bool} {
let mut args_opt_0: [option<@ast::expr>] = [];
- for arg: @ast::expr in args {
+ for args.each {|arg|
args_opt_0 += [some::<@ast::expr>(arg)];
}
let lhs_t = structurally_resolved_type(fcx, lhs.span, lhs_t);
ret alt (op, ty::get(lhs_t).struct) {
(ast::add, ty::ty_vec(lhs_mt)) {
- // For adding vectors with type L=[M TL] and R=[M TR], the result
- // is somewhat subtle. Let L_c=[const TL] and R_c=[const TR] be
- // const versions of the vectors in L and R. Next, let T be a
- // fresh type variable where TL <: T and TR <: T. Then the result
- // type is a fresh type variable T1 where T1 <: [const T]. This
- // allows the result to be either a mut or immutable vector,
- // depending on external demands.
- let const_vec_t =
- ty::mk_vec(tcx, {ty: next_ty_var(fcx),
- mutbl: ast::m_const});
+ // For adding vectors with type L=[ML TL] and R=[MR TR], the the
+ // result [ML T] where TL <: T and TR <: T. In other words, the
+ // result type is (generally) the LUB of (TL, TR) and takes the
+ // mutability from the LHS.
+ let t_var = next_ty_var(fcx);
+ let const_vec_t = ty::mk_vec(tcx, {ty: t_var,
+ mutbl: ast::m_const});
demand::simple(fcx, lhs.span, const_vec_t, lhs_t);
let rhs_bot = check_expr_with(fcx, rhs, const_vec_t);
- let result_var = next_ty_var(fcx);
- demand::simple(fcx, lhs.span, const_vec_t, result_var);
- fcx.write_ty(expr.id, result_var);
+ let result_vec_t = ty::mk_vec(tcx, {ty: t_var,
+ mutbl: lhs_mt.mutbl});
+ fcx.write_ty(expr.id, result_vec_t);
lhs_bot | rhs_bot
}
check_expr_with(fcx, cond, ty::mk_bool(tcx)) |
check_then_else(fcx, thn, elsopt, id, expr.span);
}
- ast::expr_for(decl, seq, body) {
- bot = check_expr(fcx, seq);
- let mut elt_ty;
- let ety = fcx.expr_ty(seq);
- alt structure_of(fcx, expr.span, ety) {
- ty::ty_vec(vec_elt_ty) { elt_ty = vec_elt_ty.ty; }
- ty::ty_str { elt_ty = ty::mk_mach_uint(tcx, ast::ty_u8); }
- _ {
- tcx.sess.span_fatal(expr.span,
- "mismatched types: expected vector or string "
- + "but found `" + ty_to_str(tcx, ety) + "`");
- }
- }
- bot |= check_for(fcx, decl, elt_ty, body, id);
- }
ast::expr_while(cond, body) {
bot = check_expr_with(fcx, cond, ty::mk_bool(tcx));
check_block_no_value(fcx, body);
// Typecheck the patterns first, so that we get types for all the
// bindings.
//let pattern_ty = fcx.expr_ty(discrim);
- for arm: ast::arm in arms {
+ for arms.each {|arm|
let pcx = {
fcx: fcx,
map: pat_util::pat_id_map(tcx.def_map, arm.pats[0]),
pat_region: ty::re_scope(parent_block)
};
- for p: @ast::pat in arm.pats {
- check_pat(pcx, p, pattern_ty);
- }
+ for arm.pats.each {|p| check_pat(pcx, p, pattern_ty);}
}
// Now typecheck the blocks.
let mut result_ty = next_ty_var(fcx);
let mut arm_non_bot = false;
- for arm: ast::arm in arms {
+ for arms.each {|arm|
alt arm.guard {
some(e) { check_expr_with(fcx, e, ty::mk_bool(tcx)); }
none { }
}
ast::expr_vec(args, mutbl) {
let t: ty::t = next_ty_var(fcx);
- for e: @ast::expr in args { bot |= check_expr_with(fcx, e, t); }
+ for args.each {|e| bot |= check_expr_with(fcx, e, t); }
let typ = ty::mk_vec(tcx, {ty: t, mutbl: mutbl});
fcx.write_ty(id, typ);
}
ast::expr_tup(elts) {
let mut elt_ts = [];
vec::reserve(elt_ts, vec::len(elts));
- for e in elts {
+ for elts.each {|e|
check_expr(fcx, e);
let ety = fcx.expr_ty(e);
elt_ts += [ety];
fcx.write_ty(id, typ);
}
ast::expr_rec(fields, base) {
- option::with_option_do(base) {|b| check_expr(fcx, b); }
+ option::iter(base) {|b| check_expr(fcx, b); }
let fields_t = vec::map(fields, {|f|
bot |= check_expr(fcx, f.node.expr);
let expr_t = fcx.expr_ty(f.node.expr);
}
}
fcx.write_ty(id, bexpr_t);
- for f: spanned<ty::field> in fields_t {
+ for fields_t.each {|f|
let mut found = false;
- for bf: ty::field in base_fields {
+ for base_fields.each {|bf|
if str::eq(f.node.ident, bf.ident) {
demand::simple(fcx, f.span, bf.mt.ty, f.node.mt.ty);
found = true;
ty_to_str(tcx, expected));
unify(fcx, expr.span, expected, fcx.expr_ty(expr));
+
+ #debug("<< bot=%b", bot);
ret bot;
}
node_id = id;
alt decl.node {
ast::decl_local(ls) {
- for l in ls { bot |= check_decl_local(fcx, l); }
+ for ls.each {|l| bot |= check_decl_local(fcx, l); }
}
ast::decl_item(_) {/* ignore for now */ }
}
};
let mut bot = false;
let mut warned = false;
- for s: @ast::stmt in blk.node.stmts {
+ for blk.node.stmts.each {|s|
if bot && !warned &&
alt s.node {
ast::stmt_decl(@{node: ast::decl_local(_), _}, _) |
ccx: ccx};
let mut disr_vals: [int] = [];
let mut disr_val = 0;
- for v in vs {
+ for vs.each {|v|
alt v.node.disr_expr {
some(e) {
check_expr(fcx, e);
in constraint");
}
}
- for operand: @ast::expr in operands {
+ for operands.each {|operand|
if !ast_util::is_constraint_arg(operand) {
let s =
"constraint args must be slot variables or literals";
}
fn check_constraints(fcx: @fn_ctxt, cs: [@ast::constr], args: [ast::arg]) {
- let mut c_args;
let num_args = vec::len(args);
- for c: @ast::constr in cs {
- c_args = [];
- for a: @spanned<ast::fn_constr_arg> in c.node.args {
+ for cs.each {|c|
+ let mut c_args = [];
+ for c.node.args.each {|a|
c_args += [
// "base" should not occur in a fn type thing, as of
// yet, b/c we don't allow constraints on the return type
fn class_types(ccx: @crate_ctxt, members: [@ast::class_member]) -> class_map {
let rslt = int_hash::<ty::t>();
- for m in members {
+ for members.each {|m|
alt m.node {
ast::instance_var(_,t,_,id,_) {
rslt.insert(id, ast_ty_to_ty(ccx.tcx, m_collect, t));
let self_ty = ast_ty_to_ty(ccx.tcx, m_check, ty);
let self_region = ty::re_free(it.id, ty::br_self);
let self_ty = replace_self_region(ccx.tcx, self_region, self_ty);
- for m in ms {
- check_method(ccx, m, self_ty);
- }
+ for ms.each {|m| check_method(ccx, m, self_ty);}
}
ast::item_class(tps, members, ctor) {
let cid = some(it.id);
some(class_t));
// typecheck the members
- for m in members { check_class_member(class_ccx, class_t, m); }
+ for members.each {|m| check_class_member(class_ccx, class_t, m); }
}
_ {/* nothing to do */ }
}
allow_unsafe: bool) -> vtable_res {
let tcx = fcx.ccx.tcx;
let mut result = [], i = 0u;
- for ty in tys {
- for bound in *bounds[i] {
+ for tys.each {|ty|
+ for vec::each(*bounds[i]) {|bound|
alt bound {
ty::bound_iface(i_ty) {
let i_ty = ty::substitute_type_params(tcx, tys, i_ty);
alt ty::get(ty).struct {
ty::ty_param(n, did) {
let mut n_bound = 0u;
- for bound in *tcx.ty_param_bounds.get(did.node) {
+ for vec::each(*tcx.ty_param_bounds.get(did.node)) {|bound|
alt bound {
ty::bound_iface(ity) {
alt check ty::get(ity).struct {
}
ty::ty_iface(did, tps) if iface_id == did {
if !allow_unsafe {
- for m in *ty::iface_methods(tcx, did) {
+ for vec::each(*ty::iface_methods(tcx, did)) {|m|
if ty::type_has_vars(ty::mk_fn(tcx, m.fty)) {
tcx.sess.span_err(
sp, "a boxed iface with self types may not be \
let mut found = none;
std::list::iter(isc) {|impls|
if option::is_none(found) {
- for im in *impls {
+ for vec::each(*impls) {|im|
let match = alt ty::impl_iface(tcx, im.did) {
some(ity) {
alt check ty::get(ity).struct {
#[license = "MIT"];
#[crate_type = "lib"];
-use std (name = "std",
- vers = "0.2",
- url = "https://github.com/mozilla/rust/tree/master/src/libstd");
+#[no_core];
-use rustsyntax;
+use core(vers = "0.2");
+use std(vers = "0.2");
+use rustsyntax(vers = "0.2");
+
+import core::*;
mod middle {
mod trans {
import syntax::visit;
import syntax::print;
+fn indent<R>(op: fn() -> R) -> R {
+ // Use in conjunction with the log post-processor like `src/etc/indenter`
+ // to make debug output more readable.
+ #debug[">>"];
+ let r <- op();
+ #debug["<< (Result = %?)", r];
+ ret r;
+}
+
+resource _indenter(_i: ()) {
+ #debug["<<"];
+}
+
+fn indenter() -> _indenter {
+ #debug[">>"];
+ _indenter(())
+}
+
type flag = hashmap<str, ()>;
fn def_eq(a: ast::def_id, b: ast::def_id) -> bool {
fn field_exprs(fields: [ast::field]) -> [@ast::expr] {
let mut es = [];
- for f: ast::field in fields { es += [f.node.expr]; }
+ for fields.each {|f| es += [f.node.expr]; }
ret es;
}
target_triple: target_triple} as filesearch
}
-// FIXME #1001: This can't be an obj method
fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
- for lib_search_path in filesearch.lib_search_paths() {
+ let mut rslt = none;
+ for filesearch.lib_search_paths().each {|lib_search_path|
#debug("searching %s", lib_search_path);
- for path in os::list_dir_path(lib_search_path) {
+ for os::list_dir_path(lib_search_path).each {|path|
#debug("testing %s", path);
let maybe_picked = pick(path);
if option::is_some(maybe_picked) {
#debug("picked %s", path);
- ret maybe_picked;
+ rslt = maybe_picked;
+ break;
} else {
#debug("rejected %s", path);
}
}
+ if option::is_some(rslt) { break; }
}
- ret option::none;
+ ret rslt;
}
fn relative_target_lib_path(target_triple: str) -> [path] {
// These two should not be seen by end-users (very often, anyhow):
re_var(id) { #fmt("&%s.", id.to_str()) }
re_default { "&(default)." }
+ re_static { "&static." }
}
}
alt ident { some(i) { s += " "; s += i; } _ { } }
s += "(";
let mut strs = [];
- for a: arg in inputs { strs += [fn_input_to_str(cx, a)]; }
+ for inputs.each {|a| strs += [fn_input_to_str(cx, a)]; }
s += str::connect(strs, ", ");
s += ")";
if ty::get(output).struct != ty_nil {
ty_type { "type" }
ty_rec(elems) {
let mut strs: [str] = [];
- for fld: field in elems { strs += [field_to_str(cx, fld)]; }
+ for elems.each {|fld| strs += [field_to_str(cx, fld)]; }
"{" + str::connect(strs, ",") + "}"
}
ty_tup(elems) {
let mut strs = [];
- for elem in elems { strs += [ty_to_str(cx, elem)]; }
+ for elems.each {|elem| strs += [ty_to_str(cx, elem)]; }
"(" + str::connect(strs, ",") + ")"
}
ty_fn(f) {
fn constrs_str(constrs: [@constr]) -> str {
let mut s = "";
let mut colon = true;
- for c: @constr in constrs {
+ for constrs.each {|c|
if colon { s += " : "; colon = false; } else { s += ", "; }
s += constr_to_str(c);
}
println("Usage: rustdoc [options] <cratefile>\n");
println("Options:\n");
- for opt in opts() {
+ for opts().each {|opt|
println(#fmt(" %s", tuple::second(opt)));
}
println("");
let result = result::chain(result) {|config|
let output_format = getopts::opt_maybe_str(
match, opt_output_format());
- option::with_option(output_format, result::ok(config))
+ option::map_default(output_format, result::ok(config))
{|output_format|
result::chain(parse_output_format(output_format)) {|output_format|
result::ok({
};
let result = result::chain(result) {|config|
let output_style = getopts::opt_maybe_str(match, opt_output_style());
- option::with_option(output_style, result::ok(config))
+ option::map_default(output_style, result::ok(config))
{|output_style|
result::chain(parse_output_style(output_style)) {|output_style|
result::ok({
write_index(ctxt, option::get(doc.index));
}
- for itemtag in doc.items {
+ for doc.items.each {|itemtag|
write_item(ctxt, itemtag);
}
}
ret;
}
- for entry in index.entries {
+ for index.entries.each {|entry|
let header = header_text_(entry.kind, entry.name);
let id = entry.link;
if option::is_some(entry.brief) {
write_index(ctxt, option::get(doc.index));
}
- for fndoc in doc.fns {
+ for doc.fns.each {|fndoc|
write_item_header(ctxt, doc::fntag(fndoc));
write_fn(ctxt, fndoc);
}
export anymap, seqmap, parmap;
fn anymap<T:send, U:send>(v: [T], f: fn~(T) -> U) -> [U] {
- seqmap(v, f)
+ parmap(v, f)
}
fn seqmap<T, U>(v: [T], f: fn(T) -> U) -> [U] {
let assoc_list = astsrv::exec(srv) {|ctxt|
let def_set = common::new_def_hash();
ctxt.exp_map.items {|_id, defs|
- for def in defs {
+ for defs.each {|def|
if def.reexp {
def_set.insert(def.id, ());
}
}
}
- for def in find_reexport_impls(ctxt) {
+ for find_reexport_impls(ctxt).each {|def|
def_set.insert(def, ());
}
to_assoc_list(def_set)
fn fold_mod(fold: fold::fold<ctxt>, doc: doc::moddoc) -> doc::moddoc {
let doc = fold::default_seq_fold_mod(fold, doc);
- for item in doc.items {
+ for doc.items.each {|item|
let def_id = ast_util::local_def(item.id());
if fold.ctxt.def_set.contains_key(def_id) {
fold.ctxt.def_map.insert(def_id, item);
fn fold_nmod(fold: fold::fold<ctxt>, doc: doc::nmoddoc) -> doc::nmoddoc {
let doc = fold::default_seq_fold_nmod(fold, doc);
- for fndoc in doc.fns {
+ for doc.fns.each {|fndoc|
let def_id = ast_util::local_def(fndoc.id());
if fold.ctxt.def_set.contains_key(def_id) {
fold.ctxt.def_map.insert(def_id, doc::fntag(fndoc));
let modpath = ast_map::path_to_str(vec::init(*path));
let mut reexportdocs = [];
- for def in defs {
+ for defs.each {|def|
if !def.reexp { cont; }
alt def_map.find(def.id) {
some(itemtag) {
}
if reexportdocs.len() > 0u {
- option::with_option_do(path_map.find(modpath)) {|docs|
+ option::iter(path_map.find(modpath)) {|docs|
reexportdocs = docs + vec::filter(reexportdocs, {|x|
!vec::contains(docs, x)
});
}
}
- for (path, doc) in find_reexport_impl_docs(ctxt, def_map) {
+ for find_reexport_impl_docs(ctxt, def_map).each {|elt|
+ let (path, doc) = elt;
let docs = alt path_map.find(path) {
some(docs) { docs + [(doc)] }
none { [doc] }
let all_impls = all_impls(m);
alt check ctxt.impl_map.get(mod_id) {
list::cons(impls, @list::nil) {
- for i in *impls {
+ for vec::each(*impls) {|i|
// This impl is not an item in the current mod
if !all_impls.contains_key(i.did) {
// Ignore external impls because I don't
fn all_impls(m: ast::_mod) -> map::set<ast::def_id> {
let all_impls = common::new_def_hash();
- for item in m.items {
+ for m.items.each {|item|
alt item.node {
ast::item_impl(_, _, _, _) {
all_impls.insert(ast_util::local_def(item.id), ());
#[license = "MIT"];
#[crate_type = "bin"];
-use std;
-use rustc;
+#[no_core];
+
+use core(vers = "0.2");
+use std(vers = "0.2");
+use rustc(vers = "0.2");
+
+import core::*;
mod config;
mod parse;
let mut current_section = none;
let mut sections = [];
- for line in lines {
+ for lines.each {|line|
alt parse_header(line) {
some(header) {
if option::is_some(current_section) {
fn alist_get<A: copy, B: copy>(lst: alist<A,B>, k: A) -> B {
let eq_fn = lst.eq_fn;
- for pair in lst.data {
+ for lst.data.each {|pair|
let (ki, vi) = pair; // copy req'd for alias analysis
if eq_fn(k, ki) { ret vi; }
}
--- /dev/null
+#[link(name = "crateresolve1",
+ vers = "0.1")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 10 }
--- /dev/null
+#[link(name = "crateresolve1",
+ vers = "0.2")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 20 }
--- /dev/null
+#[link(name = "crateresolve1",
+ vers = "0.3")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 30 }
--- /dev/null
+#[link(name = "crateresolve2",
+ vers = "0.1")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 10 }
--- /dev/null
+#[link(name = "crateresolve2",
+ vers = "0.2")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 20 }
--- /dev/null
+#[link(name = "crateresolve2",
+ vers = "0.3")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 30 }
--- /dev/null
+#[link(name = "crateresolve3",
+ vers = "0.1")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 10 }
--- /dev/null
+#[link(name = "crateresolve3",
+ vers = "0.2")];
+
+#[crate_type = "lib"];
+
+fn g() -> int { 20 }
--- /dev/null
+#[link(name = "crateresolve4a", vers = "0.1")];
+#[crate_type = "lib"];
+
+fn f() -> int { 10 }
--- /dev/null
+#[link(name = "crateresolve4a", vers= "0.2")];
+#[crate_type = "lib"];
+
+fn g() -> int { 20 }
--- /dev/null
+// aux-build:crateresolve4a-1.rs
+// aux-build:crateresolve4a-2.rs
+#[link(name = "crateresolve4b", vers = "0.1")];
+#[crate_type = "lib"];
+
+use crateresolve4a(vers="0.2");
+
+fn f() -> int { crateresolve4a::g() }
--- /dev/null
+// aux-build:crateresolve4a-1.rs
+// aux-build:crateresolve4a-2.rs
+#[link(name = "crateresolve4b", vers = "0.2")];
+#[crate_type = "lib"];
+
+use crateresolve4a(vers="0.1");
+
+fn g() -> int { crateresolve4a::f() }
--- /dev/null
+#[link(name = "crateresolve5",
+ vers = "0.1")];
+
+#[crate_type = "lib"];
+
+fn structural() -> { name: str, val: int } {
+ { name: "crateresolve5", val: 10 }
+}
+
+enum e {
+ e_val
+}
+
+fn nominal() -> e { e_val }
+
+fn f() -> int { 10 }
--- /dev/null
+#[link(name = "crateresolve5",
+ vers = "0.2")];
+
+#[crate_type = "lib"];
+
+fn structural() -> { name: str, val: int } {
+ { name: "crateresolve5", val: 10 }
+}
+
+enum e {
+ e_val
+}
+
+fn nominal() -> e { e_val }
+
+fn f() -> int { 20 }
--- /dev/null
+#[link(name = "crateresolve6",
+ vers = "0.1",
+ calories = "100")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 100 }
--- /dev/null
+#[link(name = "crateresolve6",
+ vers = "0.1",
+ calories = "200")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 200 }
--- /dev/null
+#[link(name = "crateresolve7",
+ vers = "0.1",
+ calories = "100")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 100 }
--- /dev/null
+#[link(name = "crateresolve7",
+ vers = "0.1",
+ calories = "200")];
+
+#[crate_type = "lib"];
+
+fn f() -> int { 200 }
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve7-1.rs
+// aux-build:crateresolve7-2.rs
+
+// These both have the same version but differ in other metadata
+mod a {
+ use cr7_1 (name = "crateresolve7", vers = "0.1", calories="100");
+ fn f() -> int { cr7_1::f() }
+}
+
+mod b {
+ use cr7_2 (name = "crateresolve7", vers = "0.1", calories="200");
+ fn f() -> int { cr7_2::f() }
+}
let to_child = to_child;
let mut worker_results = [];
uint::range(0u, workers) {|_i|
- let builder = task::task_builder();
+ let builder = task::builder();
worker_results += [task::future_result(builder)];
task::run(builder) {||
uint::range(0u, size / workers) {|_i|
fn make_cumulative(aa: [aminoacids]) -> [aminoacids] {
let mut cp: u32 = 0u32;
let mut ans: [aminoacids] = [];
- for a: aminoacids in aa { cp += a.prob; ans += [{ch: a.ch, prob: cp}]; }
+ for aa.each {|a| cp += a.prob; ans += [{ch: a.ch, prob: cp}]; }
ret ans;
}
fn stress(num_tasks: int) {
let mut results = [];
range(0, num_tasks) {|i|
- let builder = task::task_builder();
+ let builder = task::builder();
results += [task::future_result(builder)];
task::run(builder) {|| stress_task(i); }
}
- for r in results { future::get(r); }
+ for results.each {|r| future::get(r); }
}
fn main(argv: [str]) {
ctrl: chan<ctrl_proto<K2, V>>, inputs: [K1]) ->
[joinable_task] {
let tasks = [];
- for i in inputs {
+ for inputs.each {|i|
let m = map, c = ctrl, ii = i;
tasks += [task::spawn_joinable {|| map_task(m, c, ii)}];
}
}
treemap::traverse(reducers, finish);
- for t in tasks { task::join(t); }
+ for tasks.each {|t| task::join(t); }
}
}
}
let iargs = [];
- for a in vec::slice(argv, 1u, vec::len(argv)) {
+ vec::iter_between(argv, 1u, vec::len(argv)) {|a|
iargs += [str::bytes(a)];
}
fn start_mappers(ctrl: chan<ctrl_proto>, -inputs: [str]) ->
[future::future<task::task_result>] {
let mut results = [];
- for i: str in inputs {
- let builder = task::task_builder();
+ for inputs.each {|i|
+ let builder = task::builder();
results += [task::future_result(builder)];
task::run(builder) {|| map_task(ctrl, i)}
}
// log(error, "creating new reducer for " + k);
let p = port();
let ch = chan(p);
- let builder = task::task_builder();
+ let builder = task::builder();
results += [task::future_result(builder)];
task::run(builder) {||reduce_task(k, ch)}
c = recv(p);
reducers.values {|v| send(v, done); }
- for r in results { future::get(r); }
+ for results.each {|r| future::get(r); }
}
}
fn bad_bang(i: uint) -> ! {
ret 7u;
- //!^ ERROR expected `_|_` but found `uint` (types differ)
+ //!^ ERROR expected `_|_` but found `uint`
}
fn main() { bad_bang(5u); }
fn bad_bang(i: uint) -> ! {
if i < 0u { } else { fail; }
- //!^ ERROR expected `_|_` but found `()` (types differ)
+ //!^ ERROR expected `_|_` but found `()`
}
fn main() { bad_bang(5u); }
fn f() -> ! {
- 3 //! ERROR expected `_|_` but found `int` (types differ)
+ 3 //! ERROR expected `_|_` but found `int`
}
fn main() { }
// error-pattern:mismatched types: expected `()` but found `bool`
fn main() {
- for i in [0] {
+ for vec::iter([0]) {|_i|
true
}
}
\ No newline at end of file
--- /dev/null
+// aux-build:crateresolve1-1.rs
+// aux-build:crateresolve1-2.rs
+// aux-build:crateresolve1-3.rs
+// error-pattern:multiple matching crates for `crateresolve1`
+
+use crateresolve1;
+
+fn main() {
+}
--- /dev/null
+// aux-build:crateresolve2-1.rs
+// aux-build:crateresolve2-2.rs
+// aux-build:crateresolve2-3.rs
+// error-pattern:using multiple versions of crate `crateresolve2`
+
+use crateresolve2(vers = "0.1");
+
+mod m {
+ use crateresolve2(vers = "0.2");
+}
+
+fn main() {
+ let x: int = false;
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve5-1.rs
+// aux-build:crateresolve5-2.rs
+// error-pattern:mismatched types
+
+use cr5_1 (name = "crateresolve5", vers = "0.1");
+use cr5_2 (name = "crateresolve5", vers = "0.2");
+
+fn main() {
+ // Nominal types from two multiple versions of a crate are different types
+ assert cr5_1::nominal() == cr5_2::nominal();
+}
--- /dev/null
+iface monad<A> {
+ fn bind<B>(fn(A) -> self<B>);
+}
+impl monad<A> of monad<A> for [A] {
+ fn bind<B>(f: fn(A) -> [B]) {
+ let mut r = fail;
+ for self.each {|elt| r += f(elt); }
+ //!^ WARNING unreachable expression
+ //!^^ ERROR the type of this value must be known
+ }
+}
+fn main() {
+ ["hi"].bind {|x| [x] };
+}
\ No newline at end of file
--- /dev/null
+fn fail_len(v: [const int]) -> uint {
+ let mut i = fail;
+ for v.each {|x| i += 1u; }
+ //!^ WARNING unreachable statement
+ //!^^ ERROR the type of this value must be known
+ ret i;
+}
+fn main() {}
\ No newline at end of file
--- /dev/null
+fn main() {
+ vec::iter(fail) {|i|
+ log (debug, i * 2);
+ //!^ ERROR the type of this value must be known
+ };
+}
\ No newline at end of file
fn g() -> ! { fail; }
fn f() -> ! {
- ret 42; //! ERROR expected `_|_` but found `int` (types differ)
+ ret 42; //! ERROR expected `_|_` but found `int`
g(); //! WARNING unreachable statement
}
fn main() { }
fn f() -> ! {
- ret 42; //! ERROR expected `_|_` but found `int` (types differ)
+ ret 42; //! ERROR expected `_|_` but found `int`
fail; //! WARNING unreachable statement
}
fn main() { }
loop {
break;
}
- ret 42; //! ERROR expected `_|_` but found `int` (types differ)
+ ret 42; //! ERROR expected `_|_` but found `int`
}
fn main() {
--- /dev/null
+type foo = {a: int};
+type bar = {b: int};
+
+fn want_foo(f: foo) {}
+fn have_bar(b: bar) {
+ want_foo(b); //! ERROR expected a record with field `a`
+}
+
+fn main() {}
\ No newline at end of file
--- /dev/null
+// The type of `y` ends up getting inferred to the type of the block.
+// This generates a ton of error msgs at the moment.
+fn broken() -> int {
+ let mut x = 3;
+ let mut y = [&x]; //! ERROR reference escapes its block
+ while x < 10 {
+ let z = x;
+ y += [&z];
+ x += 1;
+ }
+ vec::foldl(0, y) {|v, p| v + *p }
+ //!^ ERROR reference escapes its block
+ //!^^ ERROR reference escapes its block
+ //!^^^ ERROR reference escapes its block
+ //!^^^^ ERROR reference escapes its block
+ //!^^^^^ ERROR reference escapes its block
+}
+
+fn main() { }
\ No newline at end of file
--- /dev/null
+// xfail-test
+
+fn ignore<T>(t: T) {}
+
+fn nested(x: &x.int) {
+ let y = 3;
+ let mut ay = &y;
+
+ ignore(fn&(z: &z.int) {
+ ay = x;
+ ay = &y;
+ ay = z; //! ERROR foo
+ });
+
+ ignore(fn&(z: &z.int) -> &z.int {
+ if false { ret x; } //! ERROR bar
+ if false { ret &y; } //! ERROR bar
+ if false { ret ay; } //! ERROR bar
+ ret z;
+ });
+}
+
+fn main() {}
\ No newline at end of file
--- /dev/null
+type foo = {a: int, b: int};
+type bar = {a: int, b: uint};
+
+fn want_foo(f: foo) {}
+fn have_bar(b: bar) {
+ want_foo(b); //! ERROR (in field `b`, int vs uint)
+}
+
+fn main() {}
--- /dev/null
+type foo = {a: int, b: int};
+type bar = @foo;
+
+fn want_foo(f: foo) {}
+fn have_bar(b: bar) {
+ want_foo(b); //! ERROR (record vs @-ptr)
+}
+
+fn main() {}
--- /dev/null
+class box_impl<T> {
+ let mut f: T;
+
+ new(f: T) {
+ self.f = f;
+ }
+}
+
+fn set_box_impl<T>(b: box_impl<@const T>, v: @const T) {
+ b.f = v;
+}
+
+fn main() {
+ let b = box_impl::<@int>(@3);
+ set_box_impl(b, @mut 5);
+ //!^ ERROR values differ in mutability
+
+ // No error when type of parameter actually IS @const int
+ let b = box_impl::<@const int>(@3);
+ set_box_impl(b, @mut 5);
+}
\ No newline at end of file
--- /dev/null
+enum box_impl<T> = {
+ mut f: T
+};
+
+fn set_box_impl<T>(b: box_impl<@const T>, v: @const T) {
+ b.f = v;
+}
+
+fn main() {
+ let b = box_impl::<@int>({mut f: @3});
+ set_box_impl(b, @mut 5);
+ //!^ ERROR values differ in mutability
+
+ // No error when type of parameter actually IS @const int
+ let x: @const int = @3; // only way I could find to upcast
+ let b = box_impl::<@const int>({mut f: x});
+ set_box_impl(b, @mut 5);
+}
\ No newline at end of file
--- /dev/null
+iface box_iface<T> {
+ fn get() -> T;
+ fn set(t: T);
+}
+
+enum box_impl<T> = {
+ mut f: T
+};
+
+impl<T:copy> of box_iface<T> for box_impl<T> {
+ fn get() -> T { ret self.f; }
+ fn set(t: T) { self.f = t; }
+}
+
+fn set_box_iface<T>(b: box_iface<@const T>, v: @const T) {
+ b.set(v);
+}
+
+fn set_box_impl<T>(b: box_impl<@const T>, v: @const T) {
+ b.set(v);
+}
+
+fn main() {
+ let b = box_impl::<@int>({mut f: @3});
+ set_box_iface(b as box_iface::<@int>, @mut 5);
+ //!^ ERROR values differ in mutability
+ set_box_impl(b, @mut 5);
+ //!^ ERROR values differ in mutability
+}
\ No newline at end of file
--- /dev/null
+// 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() {
+}
+++ /dev/null
-// error-pattern:invalidate reference x
-
-fn main() {
- let v: [mut {mut x: int}] = [mut {mut x: 1}];
- for x in v { v[0] = {mut x: 2}; log(debug, x); }
-}
--- /dev/null
+fn add(i: [int], m: [mut int], c: [const int]) {
+
+ // Check that:
+ // (1) vectors of any two mutabilities can be added
+ // (2) result has mutability of lhs
+
+ add(i + [3],
+ m + [3],
+ c + [3]);
+
+ add(i + [mut 3],
+ m + [mut 3],
+ c + [mut 3]);
+
+ add(i + i,
+ m + i,
+ c + i);
+
+ add(i + m,
+ m + m,
+ c + m);
+
+ add(i + c,
+ m + c,
+ c + c);
+
+ add(m + [3], //! ERROR mismatched types
+ m + [3],
+ m + [3]);
+
+ add(i + [3],
+ i + [3], //! ERROR mismatched types
+ i + [3]);
+
+ add(c + [3], //! ERROR mismatched types
+ c + [3], //! ERROR mismatched types
+ c + [3]);
+
+ add(m + [mut 3], //! ERROR mismatched types
+ m + [mut 3],
+ m + [mut 3]);
+
+ add(i + [mut 3],
+ i + [mut 3], //! ERROR mismatched types
+ i + [mut 3]);
+
+ add(c + [mut 3], //! ERROR mismatched types
+ c + [mut 3], //! ERROR mismatched types
+ c + [mut 3]);
+
+ add(m + i, //! ERROR mismatched types
+ m + i,
+ m + i);
+
+ add(i + i,
+ i + i, //! ERROR mismatched types
+ i + i);
+
+ add(c + i, //! ERROR mismatched types
+ c + i, //! ERROR mismatched types
+ c + i);
+
+ add(m + m, //! ERROR mismatched types
+ m + m,
+ m + m);
+
+ add(i + m,
+ i + m, //! ERROR mismatched types
+ i + m);
+
+ add(c + m, //! ERROR mismatched types
+ c + m, //! ERROR mismatched types
+ c + m);
+
+ add(m + c, //! ERROR mismatched types
+ m + c,
+ m + c);
+
+ add(i + c,
+ i + c, //! ERROR mismatched types
+ i + c);
+
+ add(c + c, //! ERROR mismatched types
+ c + c, //! ERROR mismatched types
+ c + c);
+}
+
+fn main() {
+}
+// xfail-test
+
fn concat<T: copy>(v: [const [const T]]) -> [T] {
let mut r = [];
// Earlier versions of our type checker accepted this:
- for inner: [T] in v {
+ for v.each {|inner|
//!^ ERROR found `[const 'a]` (values differ in mutability)
r += inner;
}
// preserved. They are needed to disambiguate `{ret n+1}; - 0` from
// `({ret n+1}-0)`.
-fn wsucc(n: int) -> int { ({ ret n + 1 }) - 0; }
+fn id(f: fn() -> int) -> int { f() }
+
+fn wsucc(n: int) -> int { (id {|| 1 }) - 0 }
fn main() { }
fn main(args: [str]) {
let vs: [str] = ["hi", "there", "this", "is", "a", "vec"];
let vvs: [[str]] = [args, vs];
- for vs: [str] in vvs { for s: str in vs { log(debug, s); } }
+ for vvs.each {|vs| for vs.each {|s| log(debug, s); } }
}
fn main() {
let mut sum = 0;
- for x in [1, 2, 3, 4, 5] { sum += x; }
+ for vec::each([1, 2, 3, 4, 5]) {|x| sum += x; }
assert (sum == 15);
}
// From #1174:
-// xfail-test bots are crashing on this on x86_64
+// xfail-fast
use std;
import str;
#[nolink]
native mod libc {
- fn write(fd: c_int, buf: *u8, nbyte: size_t);
+ fn write(fd: core::libc::c_int, buf: *u8, nbyte: core::libc::size_t);
}
fn main() {
-fn iter_vec<T>(v: [T], f: fn(T)) { for x: T in v { f(x); } }
+fn iter_vec<T>(v: [T], f: fn(T)) { for v.each {|x| f(x); } }
fn main() {
let v = [1, 2, 3, 4, 5, 6, 7];
-fn iter_vec<T>(v: [T], f: fn(T)) { for x: T in v { f(x); } }
+fn iter_vec<T>(v: [T], f: fn(T)) { for v.each {|x| f(x); } }
fn main() {
let v = [1, 2, 3, 4, 5];
assert (i == 10);
do { i += 1; if i == 20 { break; } } while i < 30
assert (i == 20);
- for x: int in [1, 2, 3, 4, 5, 6] { if x == 3 { break; } assert (x <= 3); }
+ for vec::each([1, 2, 3, 4, 5, 6]) {|x|
+ if x == 3 { break; } assert (x <= 3);
+ }
i = 0;
while i < 10 { i += 1; if i % 2 == 0 { cont; } assert (i % 2 != 0); }
i = 0;
do { i += 1; if i % 2 == 0 { cont; } assert (i % 2 != 0); } while i < 10
- for x: int in [1, 2, 3, 4, 5, 6] {
+ for vec::each([1, 2, 3, 4, 5, 6]) {|x|
if x % 2 == 0 { cont; }
assert (x % 2 != 0);
}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve1-1.rs
+// aux-build:crateresolve1-2.rs
+// aux-build:crateresolve1-3.rs
+
+use crateresolve1(vers = "0.2");
+
+fn main() {
+ assert crateresolve1::f() == 20;
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve2-1.rs
+// aux-build:crateresolve2-2.rs
+// aux-build:crateresolve2-3.rs
+
+mod a {
+ use crateresolve2(vers = "0.1");
+ fn f() { assert crateresolve2::f() == 10; }
+}
+
+mod b {
+ use crateresolve2(vers = "0.2");
+ fn f() { assert crateresolve2::f() == 20; }
+}
+
+mod c {
+ use crateresolve2(vers = "0.3");
+ fn f() { assert crateresolve2::f() == 30; }
+}
+
+fn main() {
+ a::f();
+ b::f();
+ c::f();
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve3-1.rs
+// aux-build:crateresolve3-2.rs
+
+// verify able to link with crates with same name but different versions
+// as long as no name collision on invoked functions.
+
+mod a {
+ use crateresolve3(vers = "0.1");
+ fn f() { assert crateresolve3::f() == 10; }
+}
+
+mod b {
+ use crateresolve3(vers = "0.2");
+ fn f() { assert crateresolve3::g() == 20; }
+}
+
+fn main() {
+ a::f();
+ b::f();
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve4a-1.rs
+// aux-build:crateresolve4a-2.rs
+// aux-build:crateresolve4b-1.rs
+// aux-build:crateresolve4b-2.rs
+
+mod a {
+ use crateresolve4b(vers = "0.1");
+ fn f() { assert crateresolve4b::f() == 20; }
+}
+
+mod b {
+ use crateresolve4b(vers = "0.2");
+ fn f() { assert crateresolve4b::g() == 10; }
+}
+
+fn main() {
+ a::f();
+ b::f();
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve5-1.rs
+// aux-build:crateresolve5-2.rs
+
+use cr5_1 (name = "crateresolve5", vers = "0.1");
+use cr5_2 (name = "crateresolve5", vers = "0.2");
+
+fn main() {
+ // Structural types can be used between two versions of the same crate
+ assert cr5_1::structural() == cr5_2::structural();
+ // Make sure these are actually two different crates
+ assert cr5_1::f() == 10 && cr5_2::f() == 20;
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve6-1.rs
+// aux-build:crateresolve6-2.rs
+// error-pattern:mismatched types
+
+// These both have the same version but differ in other metadata
+use cr6_1 (name = "crateresolve6", vers = "0.1", calories="100");
+use cr6_2 (name = "crateresolve6", vers = "0.1", calories="200");
+
+fn main() {
+ assert cr6_1::f() == 100;
+ assert cr6_2::f() == 200;
+}
--- /dev/null
+// xfail-fast
+// aux-build:crateresolve7-1.rs
+// aux-build:crateresolve7-2.rs
+// aux-build:crateresolve7x.rs
+
+use crateresolve7x;
+
+fn main() {
+ assert crateresolve7x::a::f() == 100;
+ assert crateresolve7x::b::f() == 200;
+}
-fn wsucc(n: int) -> int { ({ ret n + 1 } + 0); }
+fn wsucc(n: int) -> int { 0 + { ret n + 1 } }
fn main() { }
fn main() {
- for {x: x, y: y}: {x: int, y: int} in [{x: 10, y: 20}, {x: 30, y: 0}] {
- assert (x + y == 30);
+ for vec::each([{x: 10, y: 20}, {x: 30, y: 0}]) {|elt|
+ assert (elt.x + elt.y == 30);
}
}
+++ /dev/null
-fn main() {
- let x = [@{mut a: @10, b: @20}];
- for @{a, b} in x {
- assert *a == 10;
- (*x[0]).a = @30;
- assert *a == 10;
- }
-}
-fn main() { let x: [int] = []; for i: int in x { fail "moop"; } }
+fn main() { let x: [int] = []; for x.each {|_i| fail "moop"; } }
enum ctrl_proto { find_reducer([u8], chan<int>), mapper_done, }
fn start_mappers(ctrl: chan<ctrl_proto>, inputs: [str]) {
- for i: str in inputs {
+ for inputs.each {|i|
task::spawn {|| map_task(ctrl, i); };
}
}
impl <T> of map<T> for [T] {
fn map<U>(f: fn(T) -> U) -> [U] {
let mut r = [];
- for x in self { r += [f(x)]; }
+ for self.each {|x| r += [f(x)]; }
r
}
}
fn main() {
let x = [1, 2, 3];
let mut y = 0;
- for i: int in x { log(debug, i); y += i; }
+ for x.each {|i| log(debug, i); y += i; }
log(debug, y);
assert (y == 6);
let s = "hello there";
let mut i: int = 0;
- for c: u8 in s {
+ for str::each(s) {|c|
if i == 0 { assert (c == 'h' as u8); }
if i == 1 { assert (c == 'e' as u8); }
if i == 2 { assert (c == 'l' as u8); }
fn main() {
let x = [10, 20, 30];
let mut sum = 0;
- for x in x { sum += x; }
+ for x.each {|x| sum += x; }
assert (sum == 60);
}
fn main() {
uint::range(0u, 100u) {|_i|
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| iloop(); };
}
-fn main(args: [str]) { for s in args { log(debug, s); } }
+fn main(args: [str]) { for args.each {|s| log(debug, s); } }
// -*- rust -*-
fn len(v: [const int]) -> uint {
let mut i = 0u;
- for x: int in v { i += 1u; }
+ for v.each {|x| i += 1u; }
ret i;
}
impl <A> of monad<A> for [A] {
fn bind<B>(f: fn(A) -> [B]) -> [B] {
let mut r = [];
- for elt in self { r += f(elt); }
+ for self.each {|elt| r += f(elt); }
r
}
}
calllink10
];
let rng = rand::rng();
- for f in fns {
+ for fns.each {|f|
let sz = rng.next() % 256u32 + 256u32;
let frame_backoff = rng.next() % 10u32 + 1u32;
task::try {|| runtest(f, frame_backoff) };
--- /dev/null
+fn main(args: [str]) {
+ let thing = "{{ f }}";
+ let f = str::find_str(thing, "{{");
+
+ if f.is_none() {
+ io::println("None!");
+ }
+}
\ No newline at end of file
ret;
}
- let builder = task::task_builder();
+ let builder = task::builder();
let opts = {
sched: some({
mode: task::osmain,
task::unsupervise(builder);
task::run(builder) {||
task::yield();
- let builder = task::task_builder();
+ let builder = task::builder();
let opts = {
sched: some({
mode: task::single_threaded,
+++ /dev/null
-fn region_identity(x: &r.uint) -> &r.uint { x }
-
-fn apply<T>(t: T, f: fn(T) -> T) -> T { f(t) }
-
-fn parameterized(x: &uint) -> uint {
- let z = apply(x) {|y|
- region_identity(y)
- };
- *z
-}
-
-fn main() {
- let x = 3u;
- assert parameterized(&x) == 3u;
-}
\ No newline at end of file
--- /dev/null
+// A very limited test of the "bottom" region
+
+fn produce_static<T>() -> &static.T { fail; }
+
+fn foo<T>(x: &T) -> &uint { produce_static() }
+
+fn main() {
+}
\ No newline at end of file
--- /dev/null
+fn region_identity(x: &r.uint) -> &r.uint { x }
+
+fn apply<T>(t: T, f: fn(T) -> T) -> T { f(t) }
+
+fn parameterized(x: &uint) -> uint {
+ let z = apply(x) {|y|
+ region_identity(y)
+ };
+ *z
+}
+
+fn main() {
+ let x = 3u;
+ assert parameterized(&x) == 3u;
+}
\ No newline at end of file
fn main() {
uint::range(0u, 16u) {|_i|
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| iloop(); }
}
alt none::<int> {
some::<int>(_) {
- for i: int in c {
+ for c.each {|i|
log(debug, a);
let a = 17;
b += [a];
impl util<T> for [T] {
fn length_() -> uint { vec::len(self) }
- fn iter_(f: fn(T)) { for x in self { f(x); } }
+ fn iter_(f: fn(T)) { for self.each {|x| f(x); } }
fn map_<U>(f: fn(T) -> U) -> [U] {
let mut r = [];
- for elt in self { r += [f(elt)]; }
+ for self.each {|elt| r += [f(elt)]; }
r
}
}
fn test00() {
let i: int = 0;
- let builder = task::task_builder();
+ let builder = task::builder();
let r = task::future_result(builder);
task::run(builder) {|| start(i); };
// Create and spawn tasks...
let mut results = [];
while i < number_of_tasks {
- let builder = task::task_builder();
+ let builder = task::builder();
results += [task::future_result(builder)];
task::run(builder) {||
test00_start(ch, i, number_of_messages)
// Read from spawned tasks...
let mut sum = 0;
- for r in results {
+ for results.each {|r|
i = 0;
while i < number_of_messages {
let value = recv(po);
}
// Join spawned tasks...
- for r in results { future::get(r); }
+ for results.each {|r| future::get(r); }
#debug("Completed: Final number is: ");
log(error, sum);
let number_of_messages: int = 10;
let ch = comm::chan(p);
- let builder = task::task_builder();
+ let builder = task::builder();
let r = task::future_result(builder);
task::run(builder) {||
test00_start(ch, number_of_messages);
let mut results = [];
while i < number_of_tasks {
i = i + 1;
- let builder = task::task_builder();
+ let builder = task::builder();
results += [task::future_result(builder)];
task::run(builder) {|| test00_start(ch, i, number_of_messages);}
}
let mut sum: int = 0;
- for r in results {
+ for results.each {|r|
i = 0;
while i < number_of_messages { sum += recv(po); i = i + 1; }
}
- for r in results { future::get(r); }
+ for results.each {|r| future::get(r); }
#debug("Completed: Final number is: ");
assert (sum ==
let mut results = [];
while i < number_of_tasks {
i = i + 1;
- let builder = task::task_builder();
+ let builder = task::builder();
results += [task::future_result(builder)];
task::run(builder) {|| test06_start(i);};
}
- for r in results { future::get(r); }
+ for results.each {|r| future::get(r); }
}
}
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| supervisor(); }
}
// that it doesn't bring down the whole proc
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {||
fn f() { f() };
fn call_id_2() { id(true) && id(ret); }
-fn call_id_3() { id(ret) && id(ret); }
-
fn call_id_4() { while id(ret) { } }
fn bind_id_1() { bind id(fail); }
fn log_cont() { do { log(error, cont); } while false }
-fn ret_ret() -> int { ret (ret 2) + 3; }
+fn ret_ret() -> int { ret 3 + (ret 2); }
fn ret_guard() {
alt check 2 {
ret_ret();
log_ret();
call_id_2();
- call_id_3();
call_id_4();
bind_id_2();
ret_guard();
}
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| f(); }
}
\ No newline at end of file
fn main() {
let p = comm::port();
let c = comm::chan(p);
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| f(c); }
assert comm::recv(p);
}
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| f(); }
}
\ No newline at end of file
}
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {|| f(); }
}
\ No newline at end of file
--- /dev/null
+// Issue #1706
+use stdlib(name="std");
+
+fn main() {}
fn check_str_eq(a: str, b: str) {
let mut i: int = 0;
- for ab: u8 in a {
+ for str::each(a) {|ab|
log(debug, i);
log(debug, ab);
let bb: u8 = b[i];
import task::*;
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
let result = task::future_result(builder);
task::run(builder) {|| child(); }
#error("1");
import task::*;
fn main() {
- let builder = task::task_builder();
+ let builder = task::builder();
let result = task::future_result(builder);
task::run(builder) {|| child(); }
#error("1");