diff options
| author | Simon BD <simon@server> | 2012-10-22 18:33:41 -0500 |
|---|---|---|
| committer | Simon BD <simon@server> | 2012-10-22 18:33:41 -0500 |
| commit | cc0f2c6bb26ba38d3487a396fa8625e938af6820 (patch) | |
| tree | 6c2063df35144c5477b0adc9e49933d71224dc2a /src | |
| parent | 9aec7a3e85c5b07923eab05d3ebe9d031bf258f3 (diff) | |
| parent | 9ee5fff4f16cfc3390bd69abbb46b0a68521667c (diff) | |
Merge remote-tracking branch 'original/incoming' into incoming
Diffstat (limited to 'src')
387 files changed, 8948 insertions, 8309 deletions
diff --git a/src/cargo/cargo.rc b/src/cargo/cargo.rc index 17ddacfd7eb..76c15146310 100644 --- a/src/cargo/cargo.rc +++ b/src/cargo/cargo.rc @@ -10,7 +10,7 @@ // End: #[link(name = "cargo", - vers = "0.4", + vers = "0.5", uuid = "9ff87a04-8fed-4295-9ff8-f99bb802650b", url = "https://github.com/mozilla/rust/tree/master/src/cargo")]; @@ -27,10 +27,10 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod rustc(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod rustc(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 179a8941587..6f4e54080ca 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -705,7 +705,7 @@ fn configure(opts: Options) -> Cargo { ~" or package manager to get it to work correctly"); } - c + move c } fn for_each_package(c: &Cargo, b: fn(s: @Source, p: &Package)) { @@ -1162,20 +1162,20 @@ fn sync_one_file(c: &Cargo, dir: &Path, src: @Source) -> bool { } match (src.key, src.keyfp) { (Some(_), Some(f)) => { - let r = pgp::verify(&c.root, &pkgfile, &sigfile, f); + let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with \ + key %s", name, f)); return false; } if has_src_file { - let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f); + let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s \ + with key %s", name, f)); return false; } } @@ -1273,21 +1273,21 @@ fn sync_one_git(c: &Cargo, dir: &Path, src: @Source) -> bool { } match (src.key, src.keyfp) { (Some(_), Some(f)) => { - let r = pgp::verify(&c.root, &pkgfile, &sigfile, f); + let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with \ + key %s", name, f)); rollback(name, dir, false); return false; } if has_src_file { - let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f); + let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s \ + with key %s", name, f)); rollback(name, dir, false); return false; } @@ -1370,11 +1370,11 @@ fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool { return false; } - let r = pgp::verify(&c.root, &pkgfile, &sigfile, f); + let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with \ + key %s", name, f)); return false; } @@ -1390,11 +1390,11 @@ fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool { return false; } - let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f); + let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { error(~"signature verification failed for " + - ~"source " + name); + ~"source " + name + ~" with key " + f); return false; } } @@ -1463,8 +1463,7 @@ fn cmd_init(c: &Cargo) { return; } - let r = pgp::verify(&c.root, &srcfile, &sigfile, - pgp::signing_key_fp()); + let r = pgp::verify(&c.root, &srcfile, &sigfile); if !r { error(fmt!("signature verification failed for '%s'", srcfile.to_str())); @@ -1615,10 +1614,10 @@ fn dump_sources(c: &Cargo) { _ => () } - hash.insert(copy k, json::Object(chash)); + hash.insert(copy k, json::Object(move chash)); } - json::to_writer(writer, &json::Object(hash)) + json::to_writer(writer, &json::Object(move hash)) } result::Err(e) => { error(fmt!("could not dump sources: %s", e)); diff --git a/src/cargo/pgp.rs b/src/cargo/pgp.rs index 17cb8dc6487..5fbfa55838c 100644 --- a/src/cargo/pgp.rs +++ b/src/cargo/pgp.rs @@ -1,5 +1,5 @@ -fn gpg(args: ~[~str]) -> { status: int, out: ~str, err: ~str } { - return run::program_output(~"gpg", args); +fn gpgv(args: ~[~str]) -> { status: int, out: ~str, err: ~str } { + return run::program_output(~"gpgv", args); } fn signing_key() -> ~str { @@ -59,7 +59,7 @@ fn signing_key_fp() -> ~str { } fn supported() -> bool { - let r = gpg(~[~"--version"]); + let r = gpgv(~[~"--version"]); r.status == 0 } @@ -88,15 +88,14 @@ fn add(root: &Path, key: &Path) { } } -fn verify(root: &Path, data: &Path, sig: &Path, keyfp: ~str) -> bool { +fn verify(root: &Path, data: &Path, sig: &Path) -> bool { let path = root.push("gpg"); - let p = gpg(~[~"--homedir", path.to_str(), - ~"--with-fingerprint", - ~"--verify", sig.to_str(), - data.to_str()]); - let res = ~"Primary key fingerprint: " + keyfp; - for str::split_char_each(p.err, '\n') |line| { - if line == res { return true; } + let res = gpgv(~[~"--homedir", path.to_str(), + ~"--keyring", ~"pubring.gpg", + ~"--verbose", + sig.to_str(), data.to_str()]); + if res.status != 0 { + return false; } - return false; + return true; } diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 991d2d2cb0e..db605c3caa4 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -8,8 +8,8 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); use core::*; diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 55fa6740268..e147ddc3ed7 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -145,7 +145,7 @@ fn make_tests(config: config) -> ~[test::TestDesc] { tests.push(make_test(config, file)) } } - return tests; + move tests } fn is_test(config: config, testfile: &Path) -> bool { diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index b03c3bbf42f..38102e9af35 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -60,12 +60,12 @@ fn run(lib_path: ~str, writeclose(pipe_in.out, input); let p = pipes::PortSet(); let ch = p.chan(); - do task::spawn_sched(task::SingleThreaded) { + do task::spawn_sched(task::SingleThreaded) |move ch| { let errput = readclose(pipe_err.in); ch.send((2, errput)); } let ch = p.chan(); - do task::spawn_sched(task::SingleThreaded) { + do task::spawn_sched(task::SingleThreaded) |move ch| { let output = readclose(pipe_out.in); ch.send((1, output)); } diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index b93479677ee..16a205ddc16 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE language SYSTEM "language.dtd"> -<language name="Rust" version="0.3.1" kateversion="2.4" section="Sources" extensions="*.rs;*.rc" mimetype="text/x-rust" priority="15"> +<language name="Rust" version="0.4.0" kateversion="2.4" section="Sources" extensions="*.rs;*.rc" mimetype="text/x-rust" priority="15"> <highlighting> <list name="fn"> <item> fn </item> @@ -9,59 +9,39 @@ <item> type </item> </list> <list name="keywords"> - <item> alt </item> - <item> again </item> <item> as </item> <item> assert </item> <item> break </item> - <item> check </item> - <item> claim </item> <item> const </item> <item> copy </item> <item> do </item> <item> drop </item> <item> else </item> + <item> enum </item> <item> export </item> <item> extern </item> - <item> f16 </item> - <item> f80 </item> - <item> f128 </item> <item> fail </item> <item> for </item> <item> if </item> <item> impl </item> - <item> import </item> - <item> in </item> <item> let </item> <item> log </item> <item> loop </item> - <item> m32 </item> - <item> m64 </item> - <item> m128 </item> <item> match </item> <item> mod </item> - <item> module </item> <item> move </item> <item> mut </item> - <item> new </item> - <item> of </item> - <item> owned </item> <item> priv </item> <item> pub </item> <item> pure </item> - <item> ret </item> + <item> ref </item> <item> return </item> - <item> to </item> - <item> unchecked </item> + <item> static </item> + <item> struct </item> + <item> trait </item> <item> unsafe </item> <item> use </item> <item> while </item> - <item> with </item> - <item> mod </item> - <item> trait </item> - <item> class </item> - <item> struct </item> - <item> enum </item> </list> <list name="types"> <item> bool </item> @@ -80,8 +60,9 @@ <item> float </item> <item> char </item> <item> str </item> - <item> option </item> - <item> either </item> + <item> Either </item> + <item> Option </item> + <item> Result </item> </list> <list name="ctypes"> <item> c_float </item> @@ -121,16 +102,16 @@ <list name="constants"> <item> true </item> <item> false </item> - <item> some </item> - <item> none </item> - <item> left </item> - <item> right </item> - <item> ok </item> - <item> err </item> - <item> success </item> - <item> failure </item> - <item> cons </item> - <item> nil </item> + <item> Some </item> + <item> None </item> + <item> Left </item> + <item> Right </item> + <item> Ok </item> + <item> Err </item> + <item> Success </item> + <item> Failure </item> + <item> Cons </item> + <item> Nil </item> </list> <list name="cconstants"> <item> EXIT_FAILURE </item> diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index 780ba428209..b38294d5405 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -68,7 +68,7 @@ def parse_line(n, line): match = re.match(r"([ST]) (\d{4}-\d{2}-\d{2}) ([a-fA-F\d]+)\s*$", line); if (not match): - raise Exception("%s:%d:E syntax error" % (snapshotfile, n)) + raise Exception("%s:%d:E syntax error: " % (snapshotfile, n)) return {"type": "snapshot", "date": match.group(2), "rev": match.group(3)} diff --git a/src/fuzzer/fuzzer.rc b/src/fuzzer/fuzzer.rc index 640bcccc7a8..c4d37d90434 100644 --- a/src/fuzzer/fuzzer.rc +++ b/src/fuzzer/fuzzer.rc @@ -12,9 +12,9 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs index 3e31287e3cd..a4968382cf4 100644 --- a/src/fuzzer/fuzzer.rs +++ b/src/fuzzer/fuzzer.rs @@ -104,7 +104,7 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool { } } -fn safe_to_steal_ty(t: @ast::ty, tm: test_mode) -> bool { +fn safe_to_steal_ty(t: @ast::Ty, tm: test_mode) -> bool { // Restrictions happen to be the same. safe_to_replace_ty(t.node, tm) } @@ -119,16 +119,16 @@ fn stash_expr_if(c: fn@(@ast::expr, test_mode)->bool, } else {/* now my indices are wrong :( */ } } -fn stash_ty_if(c: fn@(@ast::ty, test_mode)->bool, - es: @mut ~[ast::ty], - e: @ast::ty, +fn stash_ty_if(c: fn@(@ast::Ty, test_mode)->bool, + es: @mut ~[ast::Ty], + e: @ast::Ty, tm: test_mode) { if c(e, tm) { es.push(*e); } else {/* now my indices are wrong :( */ } } -type stolen_stuff = {exprs: ~[ast::expr], tys: ~[ast::ty]}; +type stolen_stuff = {exprs: ~[ast::expr], tys: ~[ast::Ty]}; fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff { let exprs = @mut ~[]; @@ -195,7 +195,7 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, // Replace the |i|th ty (in fold order) of |crate| with |newty|. -fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty, +fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::Ty, tm: test_mode) -> ast::crate { let j: @mut uint = @mut 0u; fn fold_ty_rep(j_: @mut uint, i_: uint, newty_: ast::ty_, @@ -225,7 +225,7 @@ fn as_str(f: fn@(+x: io::Writer)) -> ~str { io::with_str_writer(f) } -fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap, +fn check_variants_of_ast(crate: ast::crate, codemap: codemap::CodeMap, filename: &Path, cx: context) { let stolen = steal(crate, cx.mode); let extra_exprs = vec::filter(common_exprs(), @@ -239,7 +239,7 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap, fn check_variants_T<T: Copy>( crate: ast::crate, - codemap: codemap::codemap, + codemap: codemap::CodeMap, filename: &Path, thing_label: ~str, things: ~[T], @@ -296,7 +296,7 @@ fn check_variants_T<T: Copy>( } fn last_part(filename: ~str) -> ~str { - let ix = option::get(&str::rfind_char(filename, '/')); + let ix = option::get(str::rfind_char(filename, '/')); str::slice(filename, ix + 1u, str::len(filename) - 3u) } @@ -444,7 +444,7 @@ fn parse_and_print(code: @~str) -> ~str { fn has_raw_pointers(c: ast::crate) -> bool { let has_rp = @mut false; - fn visit_ty(flag: @mut bool, t: @ast::ty) { + fn visit_ty(flag: @mut bool, t: @ast::Ty) { match t.node { ast::ty_ptr(_) => { *flag = true; } _ => { } diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs index 030f05c6eea..9aaf373869c 100644 --- a/src/libcore/cast.rs +++ b/src/libcore/cast.rs @@ -122,9 +122,9 @@ pub mod tests { pub fn test_transmute() { unsafe { let x = @1; - let x: *int = transmute(x); + let x: *int = transmute(move x); assert *x == 1; - let _x: @int = transmute(x); + let _x: @int = transmute(move x); } } diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs index df6074e3200..9a3b40757a7 100644 --- a/src/libcore/cleanup.rs +++ b/src/libcore/cleanup.rs @@ -142,7 +142,7 @@ pub unsafe fn annihilate() { assert (*box).header.prev == null(); debug!("freeing box: %x", box as uint); - rt_free(transmute(box)); + rt_free(transmute(move box)); } } diff --git a/src/libcore/cmath.rs b/src/libcore/cmath.rs index b0aeb78afaa..46ac90413a6 100644 --- a/src/libcore/cmath.rs +++ b/src/libcore/cmath.rs @@ -12,7 +12,7 @@ use libc::c_double; #[link_name = "m"] #[abi = "cdecl"] -pub extern mod c_double { +pub extern mod c_double_utils { // Alpabetically sorted by link_name @@ -87,7 +87,7 @@ pub extern mod c_double { #[link_name = "m"] #[abi = "cdecl"] -pub extern mod c_float { +pub extern mod c_float_utils { // Alpabetically sorted by link_name diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs new file mode 100644 index 00000000000..77bd88e04d7 --- /dev/null +++ b/src/libcore/condition.rs @@ -0,0 +1,300 @@ +// helper for transmutation, shown below. +type RustClosure = (int,int); + +struct Condition<T, U:Copy> { + key: task::local_data::LocalDataKey<Handler<T,U>> +} + +struct Handler<T, U:Copy> { + handle: RustClosure +} + + +struct ProtectBlock<T, U:Copy> { + cond: &Condition<T, U>, + inner: RustClosure +} + +struct Guard<T, U:Copy> { + cond: &Condition<T,U>, + prev: Option<@Handler<T, U>>, + drop { + match self.prev { + None => (), + Some(p) => + unsafe { + debug!("Guard: popping handler from TLS"); + task::local_data::local_data_set(self.cond.key, p) + } + } + } +} + +struct HandleBlock<T, U:Copy> { + pb: &ProtectBlock<T,U>, + prev: Option<@Handler<T,U>>, + handler: @Handler<T,U>, + drop { + unsafe { + debug!("HandleBlock: pushing handler to TLS"); + let _g = Guard { cond: self.pb.cond, + prev: self.prev }; + task::local_data::local_data_set(self.pb.cond.key, + self.handler); + // transmutation to avoid copying non-copyable, should + // be fixable by tracking closure pointees in regionck. + let f : &fn() = ::cast::transmute(self.pb.inner); + debug!("HandleBlock: invoking protected code"); + f(); + debug!("HandleBlock: returned from protected code"); + } + } +} + +struct Trap<T, U:Copy> { + cond: &Condition<T,U>, + handler: @Handler<T, U> +} + +impl<T, U: Copy> ProtectBlock<T,U> { + fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self<T,U> { + unsafe { + debug!("ProtectBlock.handle: setting up handler block"); + let p : *RustClosure = ::cast::transmute(&h); + let prev = task::local_data::local_data_get(self.cond.key); + HandleBlock { pb: self, + prev: prev, + handler: @Handler{handle: *p} } + } + } +} + + + +impl<T, U: Copy> Trap<T,U> { + fn in<V: Copy>(&self, inner: &self/fn() -> V) -> V { + unsafe { + let prev = task::local_data::local_data_get(self.cond.key); + let _g = Guard { cond: self.cond, + prev: prev }; + debug!("Trap: pushing handler to TLS"); + task::local_data::local_data_set(self.cond.key, self.handler); + inner() + } + } +} + +impl<T, U: Copy> Condition<T,U> { + + fn guard(&self, h: &self/fn(&T) ->U) -> Guard/&self<T,U> { + unsafe { + let prev = task::local_data::local_data_get(self.key); + let g = Guard { cond: self, prev: prev }; + debug!("Guard: pushing handler to TLS"); + let p : *RustClosure = ::cast::transmute(&h); + let h = @Handler{handle: *p}; + task::local_data::local_data_set(self.key, h); + move g + } + } + + fn trap(&self, h: &self/fn(&T) ->U) -> Trap/&self<T,U> { + unsafe { + let p : *RustClosure = ::cast::transmute(&h); + let h = @Handler{handle: *p}; + move Trap { cond: self, handler: h } + } + } + + fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self<T,U> { + unsafe { + // transmutation to avoid copying non-copyable, should + // be fixable by tracking closure pointees in regionck. + debug!("Condition.protect: setting up protected block"); + let p : *RustClosure = ::cast::transmute(&inner); + ProtectBlock { cond: self, + inner: *p } + } + } + + fn raise(t:&T) -> U { + unsafe { + match task::local_data::local_data_get(self.key) { + None => { + debug!("Condition.raise: found no handler"); + fail + } + + Some(handler) => { + debug!("Condition.raise: found handler"); + let f : &fn(&T) -> U = ::cast::transmute(handler.handle); + f(t) + } + } + } + } +} + + +#[cfg(test)] +fn sadness_key(_x: @Handler<int,int>) { } + +#[cfg(test)] +fn trouble(i: int) { + // Condition should work as a const, just limitations in consts. + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + debug!("trouble: raising conition"); + let j = sadness_condition.raise(&i); + debug!("trouble: handler recovered with %d", j); +} + +#[test] +fn test1() { + + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut i = 10; + + let b = do sadness_condition.protect { + debug!("test1: in protected block"); + trouble(1); + trouble(2); + trouble(3); + }; + + do b.handle |j| { + debug!("test1: in handler"); + i += *j; + i + }; + + assert i == 16; +} +#[cfg(test)] +fn nested_test_inner() { + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut inner_trapped = false; + + let b = do sadness_condition.protect { + debug!("nested_test_inner: in protected block"); + trouble(1); + }; + + do b.handle |_j| { + debug!("nested_test_inner: in handler"); + inner_trapped = true; + 0 + }; + + assert inner_trapped; +} + +#[test] +fn nested_test_outer() { + + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut outer_trapped = false; + + let b = do sadness_condition.protect { + debug!("nested_test_outer: in protected block"); + nested_test_inner(); + trouble(1); + }; + + do b.handle |_j| { + debug!("nested_test_outer: in handler"); + outer_trapped = true; + 0 + }; + + assert outer_trapped; +} + + +#[cfg(test)] +fn nested_guard_test_inner() { + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut inner_trapped = false; + + let _g = do sadness_condition.guard |_j| { + debug!("nested_guard_test_inner: in handler"); + inner_trapped = true; + 0 + }; + + debug!("nested_guard_test_inner: in protected block"); + trouble(1); + + assert inner_trapped; +} + +#[test] +fn nested_guard_test_outer() { + + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut outer_trapped = false; + + let _g = do sadness_condition.guard |_j| { + debug!("nested_guard_test_outer: in handler"); + outer_trapped = true; + 0 + }; + + debug!("nested_guard_test_outer: in protected block"); + nested_guard_test_inner(); + trouble(1); + + assert outer_trapped; +} + + + +#[cfg(test)] +fn nested_trap_test_inner() { + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut inner_trapped = false; + + do sadness_condition.trap(|_j| { + debug!("nested_trap_test_inner: in handler"); + inner_trapped = true; + 0 + }).in { + debug!("nested_trap_test_inner: in protected block"); + trouble(1); + } + + assert inner_trapped; +} + +#[test] +fn nested_trap_test_outer() { + + let sadness_condition : Condition<int,int> = + Condition { key: sadness_key }; + + let mut outer_trapped = false; + + do sadness_condition.trap(|_j| { + debug!("nested_trap_test_outer: in handler"); + outer_trapped = true; 0 + }).in { + debug!("nested_guard_test_outer: in protected block"); + nested_trap_test_inner(); + trouble(1); + } + + + assert outer_trapped; +} diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 94e6decc4ca..9ebdad3521e 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -25,7 +25,7 @@ Implicitly, all crates behave as if they included the following prologue: */ #[link(name = "core", - vers = "0.4", + vers = "0.5", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libcore")]; @@ -200,6 +200,7 @@ pub mod flate; pub mod repr; pub mod cleanup; pub mod reflect; +pub mod condition; // Modules supporting compiler-generated code // Exported but not part of the public interface diff --git a/src/libcore/core.rs b/src/libcore/core.rs index a14b67b40f1..35131e561d9 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -11,8 +11,8 @@ pub use GenericPath = path::GenericPath; pub use WindowsPath = path::WindowsPath; pub use PosixPath = path::PosixPath; -pub use tuple::{TupleOps, ExtendedTupleOps}; -pub use str::{StrSlice, UniqueStr}; +pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; +pub use str::{StrSlice, Trimmable}; pub use vec::{ConstVector, CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; pub use vec::{MutableVector, MutableCopyableVector}; @@ -33,7 +33,7 @@ pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr, BitXor}; pub use ops::{Shl, Shr, Index}; #[cfg(test)] -extern mod coreops(name = "core", vers = "0.4"); +extern mod coreops(name = "core", vers = "0.5"); #[cfg(test)] pub use coreops::ops::{Const, Copy, Send, Owned}; @@ -72,6 +72,6 @@ mod core { // Similar to above. Some magic to make core testable. #[cfg(test)] mod std { - extern mod std(vers = "0.4"); + extern mod std(vers = "0.5"); pub use std::test; } diff --git a/src/libcore/dlist.rs b/src/libcore/dlist.rs index 3bcf486ef7e..35399878e26 100644 --- a/src/libcore/dlist.rs +++ b/src/libcore/dlist.rs @@ -208,7 +208,7 @@ impl<T> DList<T> { fn push_head_n(data: T) -> DListNode<T> { let mut nobe = self.new_link(move data); self.add_head(nobe); - option::get(&nobe) + option::get(nobe) } /// Add data to the tail of the list. O(1). fn push(data: T) { @@ -221,7 +221,7 @@ impl<T> DList<T> { fn push_n(data: T) -> DListNode<T> { let mut nobe = self.new_link(move data); self.add_tail(nobe); - option::get(&nobe) + option::get(nobe) } /** * Insert data into the middle of the list, left of the given node. @@ -245,7 +245,7 @@ impl<T> DList<T> { fn insert_before_n(data: T, neighbour: DListNode<T>) -> DListNode<T> { let mut nobe = self.new_link(move data); self.insert_left(nobe, neighbour); - option::get(&nobe) + option::get(nobe) } /** * Insert data into the middle of the list, right of the given node. @@ -269,7 +269,7 @@ impl<T> DList<T> { fn insert_after_n(data: T, neighbour: DListNode<T>) -> DListNode<T> { let mut nobe = self.new_link(move data); self.insert_right(neighbour, nobe); - option::get(&nobe) + option::get(nobe) } /// Remove a node from the head of the list. O(1). @@ -385,17 +385,17 @@ impl<T> DList<T> { let mut link = self.peek_n(); let mut rabbit = link; while option::is_some(&link) { - let nobe = option::get(&link); + let nobe = option::get(link); assert nobe.linked; // check cycle if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).next; + rabbit = option::get(rabbit).next; } if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).next; + rabbit = option::get(rabbit).next; } if option::is_some(&rabbit) { - assert !box::ptr_eq(*option::get(&rabbit), *nobe); + assert !box::ptr_eq(*option::get(rabbit), *nobe); } // advance link = nobe.next_link(); @@ -406,17 +406,17 @@ impl<T> DList<T> { link = self.peek_tail_n(); rabbit = link; while option::is_some(&link) { - let nobe = option::get(&link); + let nobe = option::get(link); assert nobe.linked; // check cycle if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).prev; + rabbit = option::get(rabbit).prev; } if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).prev; + rabbit = option::get(rabbit).prev; } if option::is_some(&rabbit) { - assert !box::ptr_eq(*option::get(&rabbit), *nobe); + assert !box::ptr_eq(*option::get(rabbit), *nobe); } // advance link = nobe.prev_link(); diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index 1540eb30fe5..1b6a7522864 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -56,7 +56,7 @@ pub enum DVec<A> { } /// Creates a new, empty dvec -pub fn DVec<A>() -> DVec<A> { +pub pure fn DVec<A>() -> DVec<A> { DVec_({mut data: ~[]}) } diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs index de2e91b2e32..d41393c2393 100644 --- a/src/libcore/extfmt.rs +++ b/src/libcore/extfmt.rs @@ -301,7 +301,7 @@ pub mod rt { unsafe { str::unshift_char(&mut s, ' ') }; } } - return unsafe { pad(cv, s, PadSigned) }; + return unsafe { pad(cv, move s, PadSigned) }; } pub pure fn conv_uint(cv: Conv, u: uint) -> ~str { let prec = get_int_precision(cv); @@ -313,7 +313,7 @@ pub mod rt { TyBits => uint_to_str_prec(u, 2u, prec), TyOctal => uint_to_str_prec(u, 8u, prec) }; - return unsafe { pad(cv, rs, PadUnsigned) }; + return unsafe { pad(cv, move rs, PadUnsigned) }; } pub pure fn conv_bool(cv: Conv, b: bool) -> ~str { let s = if b { ~"true" } else { ~"false" }; @@ -323,20 +323,20 @@ pub mod rt { } pub pure fn conv_char(cv: Conv, c: char) -> ~str { let mut s = str::from_char(c); - return unsafe { pad(cv, s, PadNozero) }; + return unsafe { pad(cv, move s, PadNozero) }; } pub pure fn conv_str(cv: Conv, s: &str) -> ~str { // For strings, precision is the maximum characters // displayed let mut unpadded = match cv.precision { - CountImplied => s.to_unique(), + CountImplied => s.to_owned(), CountIs(max) => if max as uint < str::char_len(s) { str::substr(s, 0u, max as uint) } else { - s.to_unique() + s.to_owned() } }; - return unsafe { pad(cv, unpadded, PadNozero) }; + return unsafe { pad(cv, move unpadded, PadNozero) }; } pub pure fn conv_float(cv: Conv, f: float) -> ~str { let (to_str, digits) = match cv.precision { @@ -351,7 +351,7 @@ pub mod rt { s = ~" " + s; } } - return unsafe { pad(cv, s, PadFloat) }; + return unsafe { pad(cv, move s, PadFloat) }; } pub pure fn conv_poly<T>(cv: Conv, v: &T) -> ~str { let s = sys::log_str(v); @@ -411,14 +411,14 @@ pub mod rt { pub fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str { let mut s = move s; // sadtimes let uwidth : uint = match cv.width { - CountImplied => return s, + CountImplied => return (move s), CountIs(width) => { // FIXME: width should probably be uint (see Issue #1996) width as uint } }; let strlen = str::char_len(s); - if uwidth <= strlen { return s; } + if uwidth <= strlen { return (move s); } let mut padchar = ' '; let diff = uwidth - strlen; if have_flag(cv.flags, flag_left_justify) { diff --git a/src/libcore/f32.rs b/src/libcore/f32.rs index ec0e66734fa..ed6908d110d 100644 --- a/src/libcore/f32.rs +++ b/src/libcore/f32.rs @@ -4,7 +4,7 @@ //! Operations and constants for `f32` -pub use cmath::c_float::*; +pub use cmath::c_float_utils::*; pub use cmath::c_float_targ_consts::*; // These are not defined inside consts:: for consistency with diff --git a/src/libcore/f64.rs b/src/libcore/f64.rs index 731d369649b..2d13dc86e2f 100644 --- a/src/libcore/f64.rs +++ b/src/libcore/f64.rs @@ -4,7 +4,7 @@ //! Operations and constants for `f64` -pub use cmath::c_double::*; +pub use cmath::c_double_utils::*; pub use cmath::c_double_targ_consts::*; // FIXME (#1433): obtain these in a different way @@ -59,7 +59,7 @@ pub pure fn ge(x: f64, y: f64) -> bool { return x >= y; } pub pure fn gt(x: f64, y: f64) -> bool { return x > y; } pub pure fn sqrt(x: f64) -> f64 { - cmath::c_double::sqrt(x as libc::c_double) as f64 + cmath::c_double_utils::sqrt(x as libc::c_double) as f64 } /// Returns true if `x` is a positive number, including +0.0f640 and +Infinity diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs index 7c5176494a2..b2dd468236a 100644 --- a/src/libcore/flate.rs +++ b/src/libcore/flate.rs @@ -37,7 +37,7 @@ pub fn deflate_bytes(bytes: &[const u8]) -> ~[u8] { ptr::addr_of(&outsz), lz_norm); assert res as int != 0; - let out = vec::raw::from_buf(res as *u8, + let out = vec::raw::from_buf_raw(res as *u8, outsz as uint); libc::free(res); move out @@ -55,7 +55,7 @@ pub fn inflate_bytes(bytes: &[const u8]) -> ~[u8] { ptr::addr_of(&outsz), 0); assert res as int != 0; - let out = vec::raw::from_buf(res as *u8, + let out = vec::raw::from_buf_raw(res as *u8, outsz as uint); libc::free(res); move out diff --git a/src/libcore/float.rs b/src/libcore/float.rs index 098e82f5fad..dd46d30d6ba 100644 --- a/src/libcore/float.rs +++ b/src/libcore/float.rs @@ -91,7 +91,7 @@ pub mod consts { * * digits - The number of significant digits * * exact - Whether to enforce the exact number of significant digits */ -pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { +pub pure fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { if is_NaN(num) { return ~"NaN"; } if num == infinity { return ~"inf"; } if num == neg_infinity { return ~"-inf"; } @@ -125,7 +125,8 @@ pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { // store the next digit frac *= 10.0; let digit = frac as uint; - fractionalParts.push(digit); + // Bleh: not really unsafe. + unsafe { fractionalParts.push(digit); } // calculate the next frac frac -= digit as float; @@ -140,7 +141,8 @@ pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { // turn digits into string // using stack of digits while fractionalParts.is_not_empty() { - let mut adjusted_digit = carry + fractionalParts.pop(); + // Bleh; shouldn't need to be unsafe + let mut adjusted_digit = carry + unsafe { fractionalParts.pop() }; if adjusted_digit == 10 { carry = 1; @@ -196,7 +198,7 @@ pub fn test_to_str_exact_do_decimal() { * * num - The float value * * digits - The number of significant digits */ -pub fn to_str(num: float, digits: uint) -> ~str { +pub pure fn to_str(num: float, digits: uint) -> ~str { to_str_common(num, digits, false) } @@ -361,7 +363,7 @@ pub fn from_str(num: &str) -> Option<float> { * * `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow` */ -pub fn pow_with_uint(base: uint, pow: uint) -> float { +pub pure fn pow_with_uint(base: uint, pow: uint) -> float { if base == 0u { if pow == 0u { return NaN as float; diff --git a/src/libcore/future.rs b/src/libcore/future.rs index efd5ff65aa5..bc35dafde35 100644 --- a/src/libcore/future.rs +++ b/src/libcore/future.rs @@ -179,8 +179,8 @@ pub mod test { #[test] pub fn test_from_port() { let (po, ch) = future_pipe::init(); - future_pipe::server::completed(ch, ~"whale"); - let f = from_port(po); + future_pipe::server::completed(move ch, ~"whale"); + let f = from_port(move po); assert get(&f) == ~"whale"; } @@ -238,7 +238,7 @@ pub mod test { pub fn test_sendable_future() { let expected = ~"schlorf"; let f = do spawn |copy expected| { copy expected }; - do task::spawn { + do task::spawn |move f, move expected| { let actual = get(&f); assert actual == expected; } diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index 6703006650b..e3bbfbc4129 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -156,7 +156,7 @@ struct SipState { mut v1: u64, mut v2: u64, mut v3: u64, - tail: [mut u8]/8, // unprocessed bytes + tail: [mut u8 * 8], // unprocessed bytes mut ntail: uint, // how many bytes in tail are valid } @@ -359,72 +359,72 @@ impl &SipState : Streaming { #[test] pub fn test_siphash() { - let vecs : [[u8]/8]/64 = [ - [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ]/_, - [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ]/_, - [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ]/_, - [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ]/_, - [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ]/_, - [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ]/_, - [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ]/_, - [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ]/_, - [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ]/_, - [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ]/_, - [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ]/_, - [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ]/_, - [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ]/_, - [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ]/_, - [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ]/_, - [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ]/_, - [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ]/_, - [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ]/_, - [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ]/_, - [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ]/_, - [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ]/_, - [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ]/_, - [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ]/_, - [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ]/_, - [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ]/_, - [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ]/_, - [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ]/_, - [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ]/_, - [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ]/_, - [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ]/_, - [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ]/_, - [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ]/_, - [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ]/_, - [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ]/_, - [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ]/_, - [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ]/_, - [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ]/_, - [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ]/_, - [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ]/_, - [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ]/_, - [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ]/_, - [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ]/_, - [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ]/_, - [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ]/_, - [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ]/_, - [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ]/_, - [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ]/_, - [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ]/_, - [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ]/_, - [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ]/_, - [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ]/_, - [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ]/_, - [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ]/_, - [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ]/_, - [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ]/_, - [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ]/_, - [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ]/_, - [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ]/_, - [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ]/_, - [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ]/_, - [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ]/_, - [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ]/_, - [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ]/_, - [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]/_ - ]/_; + let vecs : [[u8 * 8] * 64] = [ + [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ], + [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ], + [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ], + [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ], + [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ], + [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ], + [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ], + [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ], + [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ], + [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ], + [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ], + [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ], + [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ], + [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ], + [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ], + [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ], + [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ], + [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ], + [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ], + [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ], + [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ], + [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ], + [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ], + [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ], + [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ], + [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ], + [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ], + [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ], + [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ], + [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ], + [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ], + [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ], + [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ], + [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ], + [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ], + [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ], + [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ], + [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ], + [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ], + [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ], + [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ], + [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ], + [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ], + [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ], + [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ], + [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ], + [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ], + [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ], + [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ], + [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ], + [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ], + [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ], + [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ], + [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ], + [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ], + [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ], + [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ], + [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ], + [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ], + [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ], + [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ], + [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ], + [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ], + [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] + ]; let k0 = 0x_07_06_05_04_03_02_01_00_u64; let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64; @@ -433,12 +433,12 @@ pub fn test_siphash() { let stream_inc = &State(k0,k1); let stream_full = &State(k0,k1); - fn to_hex_str(r: &[u8]/8) -> ~str { + fn to_hex_str(r: &[u8 * 8]) -> ~str { let mut s = ~""; for vec::each(*r) |b| { s += uint::to_str(*b as uint, 16u); } - return s; + move s } while t < 64 { diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 8cb689fd286..5a2b054dd3e 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -50,7 +50,6 @@ pub pure fn compl(i: T) -> T { } /// Computes the absolute value -// FIXME: abs should return an unsigned int (#2353) pub pure fn abs(i: T) -> T { if is_negative(i) { -i } else { i } } @@ -154,7 +153,7 @@ impl T : FromStr { } /// Convert to a string in a given base -pub fn to_str(n: T, radix: uint) -> ~str { +pub pure fn to_str(n: T, radix: uint) -> ~str { do to_str_bytes(n, radix) |slice| { do vec::as_imm_buf(slice) |p, len| { unsafe { str::raw::from_buf_len(p, len) } @@ -162,7 +161,7 @@ pub fn to_str(n: T, radix: uint) -> ~str { } } -pub fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { +pub pure fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { if n < 0 as T { uint::to_str_bytes(true, -n as uint, radix, f) } else { @@ -171,7 +170,7 @@ pub fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { } /// Convert to a string -pub fn str(i: T) -> ~str { return to_str(i, 10u); } +pub pure fn str(i: T) -> ~str { return to_str(i, 10u); } // FIXME: Has alignment issues on windows and 32-bit linux (#2609) #[test] diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 865b8013fb0..77f7b5023df 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -37,7 +37,7 @@ pub trait Reader { // FIXME (#2004): Seekable really should be orthogonal. // FIXME (#2982): This should probably return an error. - fn read(buf: &[mut u8], len: uint) -> uint; + fn read(bytes: &[mut u8], len: uint) -> uint; fn read_byte() -> int; fn unread_byte(int); fn eof() -> bool; @@ -65,32 +65,32 @@ pub trait ReaderUtil { impl<T: Reader> T : ReaderUtil { fn read_bytes(len: uint) -> ~[u8] { - let mut buf = vec::with_capacity(len); - unsafe { vec::raw::set_len(&mut buf, len); } + let mut bytes = vec::with_capacity(len); + unsafe { vec::raw::set_len(&mut bytes, len); } - let count = self.read(buf, len); + let count = self.read(bytes, len); - unsafe { vec::raw::set_len(&mut buf, count); } - move buf + unsafe { vec::raw::set_len(&mut bytes, count); } + move bytes } fn read_line() -> ~str { - let mut buf = ~[]; + let mut bytes = ~[]; loop { let ch = self.read_byte(); if ch == -1 || ch == 10 { break; } - buf.push(ch as u8); + bytes.push(ch as u8); } - str::from_bytes(buf) + str::from_bytes(bytes) } fn read_chars(n: uint) -> ~[char] { // returns the (consumed offset, n_req), appends characters to &chars - fn chars_from_bytes<T: Reader>(buf: &~[u8], chars: &mut ~[char]) + fn chars_from_bytes<T: Reader>(bytes: &~[u8], chars: &mut ~[char]) -> (uint, uint) { let mut i = 0; - let buf_len = buf.len(); - while i < buf_len { - let b0 = buf[i]; + let bytes_len = bytes.len(); + while i < bytes_len { + let b0 = bytes[i]; let w = str::utf8_char_width(b0); let end = i + w; i += 1; @@ -100,12 +100,12 @@ impl<T: Reader> T : ReaderUtil { loop; } // can't satisfy this char with the existing data - if end > buf_len { - return (i - 1, end - buf_len); + if end > bytes_len { + return (i - 1, end - bytes_len); } let mut val = 0; while i < end { - let next = buf[i] as int; + let next = bytes[i] as int; i += 1; assert (next > -1); assert (next & 192 == 128); @@ -119,8 +119,8 @@ impl<T: Reader> T : ReaderUtil { } return (i, 0); } - let mut buf: ~[u8] = ~[]; - let mut chars: ~[char] = ~[]; + let mut bytes = ~[]; + let mut chars = ~[]; // might need more bytes, but reading n will never over-read let mut nbread = n; while nbread > 0 { @@ -130,15 +130,15 @@ impl<T: Reader> T : ReaderUtil { // we're split in a unicode char? break; } - buf.push_all(data); - let (offset, nbreq) = chars_from_bytes::<T>(&buf, &mut chars); + bytes.push_all(data); + let (offset, nbreq) = chars_from_bytes::<T>(&bytes, &mut chars); let ncreq = n - chars.len(); // again we either know we need a certain number of bytes // to complete a character, or we make sure we don't // over-read by reading 1-byte per char needed nbread = if ncreq > nbreq { ncreq } else { nbreq }; if nbread > 0 { - buf = vec::slice(buf, offset, buf.len()); + bytes = vec::slice(bytes, offset, bytes.len()); } } move chars @@ -154,12 +154,12 @@ impl<T: Reader> T : ReaderUtil { } fn read_c_str() -> ~str { - let mut buf: ~[u8] = ~[]; + let mut bytes: ~[u8] = ~[]; loop { let ch = self.read_byte(); - if ch < 1 { break; } else { buf.push(ch as u8); } + if ch < 1 { break; } else { bytes.push(ch as u8); } } - str::from_bytes(buf) + str::from_bytes(bytes) } // FIXME deal with eof? // #2004 @@ -191,9 +191,9 @@ impl<T: Reader> T : ReaderUtil { } fn read_whole_stream() -> ~[u8] { - let mut buf: ~[u8] = ~[]; - while !self.eof() { buf.push_all(self.read_bytes(2048u)); } - move buf + let mut bytes: ~[u8] = ~[]; + while !self.eof() { bytes.push_all(self.read_bytes(2048u)); } + move bytes } fn each_byte(it: fn(int) -> bool) { @@ -226,8 +226,8 @@ fn convert_whence(whence: SeekStyle) -> i32 { } impl *libc::FILE: Reader { - fn read(buf: &[mut u8], len: uint) -> uint { - do vec::as_mut_buf(buf) |buf_p, buf_len| { + fn read(bytes: &[mut u8], len: uint) -> uint { + do vec::as_mut_buf(bytes) |buf_p, buf_len| { assert buf_len <= len; let count = libc::fread(buf_p as *mut c_void, 1u as size_t, @@ -250,7 +250,9 @@ impl *libc::FILE: Reader { // duration of its lifetime. // FIXME there really should be a better way to do this // #2004 impl<T: Reader, C> {base: T, cleanup: C}: Reader { - fn read(buf: &[mut u8], len: uint) -> uint { self.base.read(buf, len) } + fn read(bytes: &[mut u8], len: uint) -> uint { + self.base.read(bytes, len) + } fn read_byte() -> int { self.base.read_byte() } fn unread_byte(byte: int) { self.base.unread_byte(byte); } fn eof() -> bool { self.base.eof() } @@ -297,39 +299,41 @@ pub fn file_reader(path: &Path) -> Result<Reader, ~str> { } -// Byte buffer readers - -pub type ByteBuf = {buf: &[const u8], mut pos: uint}; +// Byte readers +pub struct BytesReader { + bytes: &[u8], + mut pos: uint +} -impl ByteBuf: Reader { - fn read(buf: &[mut u8], len: uint) -> uint { - let count = uint::min(len, self.buf.len() - self.pos); +impl BytesReader: Reader { + fn read(bytes: &[mut u8], len: uint) -> uint { + let count = uint::min(len, self.bytes.len() - self.pos); - let view = vec::const_view(self.buf, self.pos, self.buf.len()); - vec::bytes::memcpy(buf, view, count); + let view = vec::view(self.bytes, self.pos, self.bytes.len()); + vec::bytes::memcpy(bytes, view, count); self.pos += count; count } fn read_byte() -> int { - if self.pos == self.buf.len() { return -1; } - let b = self.buf[self.pos]; + if self.pos == self.bytes.len() { return -1; } + let b = self.bytes[self.pos]; self.pos += 1u; return b as int; } // FIXME (#2738): implement this fn unread_byte(_byte: int) { error!("Unimplemented: unread_byte"); fail; } - fn eof() -> bool { self.pos == self.buf.len() } + fn eof() -> bool { self.pos == self.bytes.len() } fn seek(offset: int, whence: SeekStyle) { let pos = self.pos; - self.pos = seek_in_buf(offset, pos, self.buf.len(), whence); + self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence); } fn tell() -> uint { self.pos } } -pub fn with_bytes_reader<t>(bytes: &[u8], f: fn(Reader) -> t) -> t { - f({buf: bytes, mut pos: 0u} as Reader) +pub pure fn with_bytes_reader<t>(bytes: &[u8], f: fn(Reader) -> t) -> t { + f(BytesReader { bytes: bytes, pos: 0u } as Reader) } pub fn with_str_reader<T>(s: &str, f: fn(Reader) -> T) -> T { @@ -602,10 +606,10 @@ impl<T: Writer> T : WriterUtil { self.write_str(&"\n"); } fn write_int(n: int) { - int::to_str_bytes(n, 10u, |buf| self.write(buf)) + int::to_str_bytes(n, 10u, |bytes| self.write(bytes)) } fn write_uint(n: uint) { - uint::to_str_bytes(false, n, 10u, |buf| self.write(buf)) + uint::to_str_bytes(false, n, 10u, |bytes| self.write(bytes)) } fn write_le_uint(n: uint) { u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v)) @@ -687,34 +691,34 @@ pub fn print(s: &str) { stdout().write_str(s); } pub fn println(s: &str) { stdout().write_line(s); } pub struct BytesWriter { - buf: DVec<u8>, + bytes: DVec<u8>, mut pos: uint, } impl BytesWriter: Writer { fn write(v: &[const u8]) { - do self.buf.swap |buf| { - let mut buf <- buf; + do self.bytes.swap |bytes| { + let mut bytes <- bytes; let v_len = v.len(); - let buf_len = buf.len(); + let bytes_len = bytes.len(); - let count = uint::max(buf_len, self.pos + v_len); - vec::reserve(&mut buf, count); - unsafe { vec::raw::set_len(&mut buf, count); } + let count = uint::max(bytes_len, self.pos + v_len); + vec::reserve(&mut bytes, count); + unsafe { vec::raw::set_len(&mut bytes, count); } { - let view = vec::mut_view(buf, self.pos, count); + let view = vec::mut_view(bytes, self.pos, count); vec::bytes::memcpy(view, v, v_len); } self.pos += v_len; - move buf + move bytes } } fn seek(offset: int, whence: SeekStyle) { let pos = self.pos; - let len = self.buf.len(); + let len = self.bytes.len(); self.pos = seek_in_buf(offset, pos, len, whence); } fn tell() -> uint { self.pos } @@ -730,24 +734,28 @@ impl @BytesWriter : Writer { fn get_type() -> WriterType { (*self).get_type() } } -pub fn BytesWriter() -> BytesWriter { - BytesWriter { buf: DVec(), mut pos: 0u } +pub pure fn BytesWriter() -> BytesWriter { + BytesWriter { bytes: DVec(), mut pos: 0u } } -pub fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { +pub pure fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { let wr = @BytesWriter(); f(wr as Writer); - wr.buf.check_out(|buf| buf) + // FIXME (#3758): This should not be needed. + unsafe { wr.bytes.check_out(|bytes| move bytes) } } -pub fn with_str_writer(f: fn(Writer)) -> ~str { +pub pure fn with_str_writer(f: fn(Writer)) -> ~str { let mut v = with_bytes_writer(f); - // Make sure the vector has a trailing null and is proper utf8. - v.push(0); + // FIXME (#3758): This should not be needed. + unsafe { + // Make sure the vector has a trailing null and is proper utf8. + v.push(0); + } assert str::is_utf8(v); - unsafe { move ::cast::transmute(v) } + unsafe { move ::cast::transmute(move v) } } // Utility functions @@ -975,15 +983,17 @@ mod tests { fn bytes_buffer_overwrite() { let wr = BytesWriter(); wr.write(~[0u8, 1u8, 2u8, 3u8]); - assert wr.buf.borrow(|buf| buf == ~[0u8, 1u8, 2u8, 3u8]); + assert wr.bytes.borrow(|bytes| bytes == ~[0u8, 1u8, 2u8, 3u8]); wr.seek(-2, SeekCur); wr.write(~[4u8, 5u8, 6u8, 7u8]); - assert wr.buf.borrow(|buf| buf == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]); + assert wr.bytes.borrow(|bytes| bytes == + ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]); wr.seek(-2, SeekEnd); wr.write(~[8u8]); wr.seek(1, SeekSet); wr.write(~[9u8]); - assert wr.buf.borrow(|buf| buf == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]); + assert wr.bytes.borrow(|bytes| bytes == + ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]); } } diff --git a/src/libcore/iter-trait/dlist.rs b/src/libcore/iter-trait/dlist.rs index 2a5bb59b0c1..1b5f11569c3 100644 --- a/src/libcore/iter-trait/dlist.rs +++ b/src/libcore/iter-trait/dlist.rs @@ -11,7 +11,7 @@ pub type IMPL_T<A> = dlist::DList<A>; pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) { let mut link = self.peek_n(); while option::is_some(&link) { - let nobe = option::get(&link); + let nobe = option::get(link); assert nobe.linked; if !f(&nobe.data) { break; } // Check (weakly) that the user didn't do a remove. diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 3665128bf3c..7ed43f619e1 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -42,8 +42,6 @@ // Initial glob-exports mean that all the contents of all the modules // wind up exported, if you're interested in writing platform-specific code. -// FIXME (#2006): change these to glob-exports when sufficiently supported. - pub use types::common::c95::*; pub use types::common::c99::*; pub use types::common::posix88::*; @@ -89,7 +87,7 @@ pub use funcs::extra::*; pub use size_t; pub use c_float, c_double, c_void, FILE, fpos_t; -pub use DIR, dirent; +pub use DIR, dirent_t; pub use c_char, c_schar, c_uchar; pub use c_short, c_ushort, c_int, c_uint, c_long, c_ulong; pub use size_t, ptrdiff_t, clock_t, time_t; @@ -149,7 +147,7 @@ mod types { } pub mod posix88 { pub enum DIR {} - pub enum dirent {} + pub enum dirent_t {} } pub mod posix01 {} pub mod posix08 {} @@ -1021,7 +1019,7 @@ pub mod funcs { pub extern mod dirent { fn opendir(dirname: *c_char) -> *DIR; fn closedir(dirp: *DIR) -> c_int; - fn readdir(dirp: *DIR) -> *dirent; + fn readdir(dirp: *DIR) -> *dirent_t; fn rewinddir(dirp: *DIR); fn seekdir(dirp: *DIR, loc: c_long); fn telldir(dirp: *DIR) -> c_long; diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs index d4f3c0ea272..958d1ac56ea 100644 --- a/src/libcore/logging.rs +++ b/src/libcore/logging.rs @@ -32,7 +32,7 @@ pub fn console_off() { #[cfg(notest)] #[lang="log_type"] pub fn log_type<T>(level: u32, object: &T) { - let bytes = do io::with_bytes_writer() |writer| { + let bytes = do io::with_bytes_writer |writer| { repr::write_repr(writer, object); }; unsafe { diff --git a/src/libcore/mutable.rs b/src/libcore/mutable.rs index b314ad61ee2..56a6df2c4dd 100644 --- a/src/libcore/mutable.rs +++ b/src/libcore/mutable.rs @@ -24,7 +24,7 @@ struct Data<T> { pub type Mut<T> = Data<T>; pub fn Mut<T>(t: T) -> Mut<T> { - Data {value: t, mode: ReadOnly} + Data {value: move t, mode: ReadOnly} } pub fn unwrap<T>(m: Mut<T>) -> T { @@ -32,7 +32,7 @@ pub fn unwrap<T>(m: Mut<T>) -> T { // is in use, as that would be a move from a borrowed value. assert (m.mode as uint) == (ReadOnly as uint); let Data {value: move value, mode: _} = move m; - return value; + move value } impl<T> Data<T> { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index c60b7b401cc..baabc35b428 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -42,7 +42,7 @@ pub enum Option<T> { Some(T), } -pub pure fn get<T: Copy>(opt: &Option<T>) -> T { +pub pure fn get<T: Copy>(opt: Option<T>) -> T { /*! Gets the value out of an option @@ -58,7 +58,7 @@ pub pure fn get<T: Copy>(opt: &Option<T>) -> T { case explicitly. */ - match *opt { + match opt { Some(copy x) => return x, None => fail ~"option::get none" } @@ -85,7 +85,7 @@ pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T { } } -pub pure fn expect<T: Copy>(opt: &Option<T>, reason: ~str) -> T { +pub pure fn expect<T: Copy>(opt: Option<T>, reason: ~str) -> T { /*! * Gets the value out of an option, printing a specified message on * failure @@ -94,7 +94,7 @@ pub pure fn expect<T: Copy>(opt: &Option<T>, reason: ~str) -> T { * * Fails if the value equals `none` */ - match *opt { Some(copy x) => x, None => fail reason } + match opt { Some(copy x) => x, None => fail reason } } pub pure fn map<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> { @@ -119,11 +119,9 @@ pub pure fn chain<T, U>(opt: Option<T>, * function that returns an option. */ - // XXX write with move match - if opt.is_some() { - f(unwrap(opt)) - } else { - None + match move opt { + Some(move t) => f(move t), + None => None } } @@ -169,10 +167,10 @@ pub pure fn is_some<T>(opt: &Option<T>) -> bool { !is_none(opt) } -pub pure fn get_default<T: Copy>(opt: &Option<T>, def: T) -> T { +pub pure fn get_default<T: Copy>(opt: Option<T>, def: T) -> T { //! Returns the contained value or a default - match *opt { Some(copy x) => x, None => def } + match opt { Some(copy x) => x, None => def } } pub pure fn map_default<T, U>(opt: &Option<T>, def: U, @@ -227,7 +225,7 @@ pub fn swap_unwrap<T>(opt: &mut Option<T>) -> T { pub pure fn unwrap_expect<T>(opt: Option<T>, reason: &str) -> T { //! As unwrap, but with a specified failure message. - if opt.is_none() { fail reason.to_unique(); } + if opt.is_none() { fail reason.to_owned(); } unwrap(move opt) } @@ -286,8 +284,8 @@ impl<T: Copy> Option<T> { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - pure fn get() -> T { get(&self) } - pure fn get_default(def: T) -> T { get_default(&self, def) } + pure fn get() -> T { get(self) } + pure fn get_default(def: T) -> T { get_default(self, def) } /** * Gets the value out of an option, printing a specified message on * failure @@ -296,7 +294,7 @@ impl<T: Copy> Option<T> { * * Fails if the value equals `none` */ - pure fn expect(reason: ~str) -> T { expect(&self, reason) } + pure fn expect(reason: ~str) -> T { expect(self, move reason) } /// Applies a function zero or more times until the result is none. pure fn while_some(blk: fn(v: T) -> Option<T>) { while_some(self, blk) } } @@ -326,8 +324,8 @@ impl<T: Eq> Option<T> : Eq { fn test_unwrap_ptr() { let x = ~0; let addr_x = ptr::addr_of(&(*x)); - let opt = Some(x); - let y = unwrap(opt); + let opt = Some(move x); + let y = unwrap(move opt); let addr_y = ptr::addr_of(&(*y)); assert addr_x == addr_y; } @@ -358,8 +356,8 @@ fn test_unwrap_resource() { let i = @mut 0; { let x = R(i); - let opt = Some(x); - let _y = unwrap(opt); + let opt = Some(move x); + let _y = unwrap(move opt); } assert *i == 1; } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 3fd98e7f298..a834bb84f8d 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -473,7 +473,7 @@ pub fn tmpdir() -> Path { #[cfg(unix)] #[allow(non_implicitly_copyable_typarams)] fn lookup() -> Path { - option::get_default(&getenv_nonempty("TMPDIR"), + option::get_default(getenv_nonempty("TMPDIR"), Path("/tmp")) } @@ -481,7 +481,7 @@ pub fn tmpdir() -> Path { #[allow(non_implicitly_copyable_typarams)] fn lookup() -> Path { option::get_default( - &option::or(getenv_nonempty("TMP"), + option::or(getenv_nonempty("TMP"), option::or(getenv_nonempty("TEMP"), option::or(getenv_nonempty("USERPROFILE"), getenv_nonempty("WINDIR")))), @@ -739,7 +739,7 @@ unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] { for uint::range(0, argc as uint) |i| { vec::push(&mut args, str::raw::from_c_str(*argv.offset(i))); } - return args; + move args } /** @@ -903,7 +903,7 @@ mod tests { let rng: rand::Rng = rand::Rng(); let n = ~"TEST" + rng.gen_str(10u); assert getenv(n).is_none(); - n + move n } #[test] @@ -937,7 +937,7 @@ mod tests { let n = make_rand_name(); setenv(n, s); log(debug, s); - assert getenv(n) == option::Some(s); + assert getenv(n) == option::Some(move s); } #[test] @@ -963,7 +963,7 @@ mod tests { // MingW seems to set some funky environment variables like // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned // from env() but not visible from getenv(). - assert v2.is_none() || v2 == option::Some(v); + assert v2.is_none() || v2 == option::Some(move v); } } @@ -976,7 +976,7 @@ mod tests { assert !vec::contains(e, &(copy n, ~"VALUE")); e = env(); - assert vec::contains(e, &(n, ~"VALUE")); + assert vec::contains(e, &(move n, ~"VALUE")); } #[test] diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 6d023ed1bfb..871e803ff1a 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -61,7 +61,7 @@ pub pure fn Path(s: &str) -> Path { } impl PosixPath : ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let mut s = ~""; if self.is_absolute { s += "/"; @@ -96,7 +96,7 @@ impl PosixPath : GenericPath { let mut components = str::split_nonempty(s, |c| c == '/'); let is_absolute = (s.len() != 0 && s[0] == '/' as u8); return PosixPath { is_absolute: is_absolute, - components: components } + components: move components } } pure fn dirname() -> ~str { @@ -192,7 +192,7 @@ impl PosixPath : GenericPath { Some(ref f) => ~[copy *f] }; return PosixPath { is_absolute: false, - components: cs } + components: move cs } } pure fn push_rel(other: &PosixPath) -> PosixPath { @@ -208,7 +208,8 @@ impl PosixPath : GenericPath { |c| windows::is_sep(c as u8)); unsafe { v.push_all_move(move ss); } } - PosixPath { components: move v, ..self } + PosixPath { is_absolute: self.is_absolute, + components: move v } } pure fn push(s: &str) -> PosixPath { @@ -223,20 +224,25 @@ impl PosixPath : GenericPath { if cs.len() != 0 { unsafe { cs.pop(); } } - return PosixPath { components: move cs, ..self } + return PosixPath { + is_absolute: self.is_absolute, + components: move cs + } + //..self } } pure fn normalize() -> PosixPath { return PosixPath { - components: normalize(self.components), - ..self + is_absolute: self.is_absolute, + components: normalize(self.components) + // ..self } } } impl WindowsPath : ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let mut s = ~""; match self.host { Some(ref h) => { s += "\\\\"; s += *h; } @@ -286,10 +292,10 @@ impl WindowsPath : GenericPath { let mut components = str::split_nonempty(rest, |c| windows::is_sep(c as u8)); let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0])); - return WindowsPath { host: host, - device: device, + return WindowsPath { host: move host, + device: move device, is_absolute: is_absolute, - components: components } + components: move components } } pure fn dirname() -> ~str { @@ -386,7 +392,7 @@ impl WindowsPath : GenericPath { return WindowsPath { host: None, device: None, is_absolute: false, - components: cs } + components: move cs } } pure fn push_rel(other: &WindowsPath) -> WindowsPath { @@ -402,7 +408,13 @@ impl WindowsPath : GenericPath { |c| windows::is_sep(c as u8)); unsafe { v.push_all_move(move ss); } } - return WindowsPath { components: move v, ..self } + // tedious, but as-is, we can't use ..self + return WindowsPath { + host: copy self.host, + device: copy self.device, + is_absolute: self.is_absolute, + components: move v + } } pure fn push(s: &str) -> WindowsPath { @@ -417,13 +429,20 @@ impl WindowsPath : GenericPath { if cs.len() != 0 { unsafe { cs.pop(); } } - return WindowsPath { components: move cs, ..self } + return WindowsPath { + host: copy self.host, + device: copy self.device, + is_absolute: self.is_absolute, + components: move cs + } } pure fn normalize() -> WindowsPath { return WindowsPath { - components: normalize(self.components), - ..self + host: copy self.host, + device: copy self.device, + is_absolute: self.is_absolute, + components: normalize(self.components) } } } diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 791c6bccde8..3f8de19498f 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -350,7 +350,8 @@ fn BufferResource<T: Send>(b: ~Buffer<T>) -> BufferResource<T> { atomic_add_acq(&mut b.header.ref_count, 1); BufferResource { - buffer: b + // tjc: ???? + buffer: move b } } @@ -448,7 +449,12 @@ pub fn try_recv<T: Send, Tbuffer: Send>(p: RecvPacketBuffered<T, Tbuffer>) let this = rustrt::rust_get_task(); rustrt::task_clear_event_reject(this); rustrt::rust_task_ref(this); + debug!("blocked = %x this = %x", p.header.blocked_task as uint, + this as uint); let old_task = swap_task(&mut p.header.blocked_task, this); + debug!("blocked = %x this = %x old_task = %x", + p.header.blocked_task as uint, + this as uint, old_task as uint); assert old_task.is_null(); let mut first = true; let mut count = SPIN_COUNT; @@ -661,7 +667,7 @@ pub fn select2<A: Send, Ab: Send, B: Send, Bb: Send>( -> Either<(Option<A>, RecvPacketBuffered<B, Bb>), (RecvPacketBuffered<A, Ab>, Option<B>)> { - let i = wait_many([a.header(), b.header()]/_); + let i = wait_many([a.header(), b.header()]); match i { 0 => Left((try_recv(move a), move b)), @@ -687,7 +693,7 @@ pub fn selecti<T: Selectable>(endpoints: &[T]) -> uint { /// Returns 0 or 1 depending on which endpoint is ready to receive pub fn select2i<A: Selectable, B: Selectable>(a: &A, b: &B) -> Either<(), ()> { - match wait_many([a.header(), b.header()]/_) { + match wait_many([a.header(), b.header()]) { 0 => Left(()), 1 => Right(()), _ => fail ~"wait returned unexpected index" @@ -1212,7 +1218,7 @@ pub mod test { c1.send(~"abc"); - match (p1, p2).select() { + match (move p1, move p2).select() { Right(_) => fail, _ => () } @@ -1224,8 +1230,8 @@ pub mod test { pub fn test_oneshot() { let (c, p) = oneshot::init(); - oneshot::client::send(c, ()); + oneshot::client::send(move c, ()); - recv_one(p) + recv_one(move p) } } diff --git a/src/libcore/private.rs b/src/libcore/private.rs index c4ef136a592..a54db3fa759 100644 --- a/src/libcore/private.rs +++ b/src/libcore/private.rs @@ -374,7 +374,7 @@ pub unsafe fn unwrap_shared_mutable_state<T: Send>(rc: SharedMutableState<T>) rc.data = ptr::null(); // Step 1 - drop our own reference. let new_count = rustrt::rust_atomic_decrement(&mut ptr.count); - assert new_count >= 0; + // assert new_count >= 0; if new_count == 0 { // We were the last owner. Can unwrap immediately. // Also we have to free the server endpoints. @@ -505,7 +505,7 @@ pub struct Exclusive<T: Send> { x: SharedMutableState<ExData<T>> } pub fn exclusive<T:Send >(user_data: T) -> Exclusive<T> { let data = ExData { - lock: LittleLock(), mut failed: false, mut data: user_data + lock: LittleLock(), mut failed: false, mut data: move user_data }; Exclusive { x: unsafe { shared_mutable_state(move data) } } } @@ -544,7 +544,7 @@ impl<T: Send> Exclusive<T> { } } -// FIXME(#2585) make this a by-move method on the exclusive +// FIXME(#3724) make this a by-move method on the exclusive pub fn unwrap_exclusive<T: Send>(arc: Exclusive<T>) -> T { let Exclusive { x: x } <- arc; let inner = unsafe { unwrap_shared_mutable_state(move x) }; @@ -558,17 +558,17 @@ pub mod tests { pub fn exclusive_arc() { let mut futures = ~[]; - let num_tasks = 10u; - let count = 10u; + let num_tasks = 10; + let count = 10; - let total = exclusive(~mut 0u); + let total = exclusive(~mut 0); - for uint::range(0u, num_tasks) |_i| { + for uint::range(0, num_tasks) |_i| { let total = total.clone(); - futures.push(future::spawn(|| { - for uint::range(0u, count) |_i| { + futures.push(future::spawn(|move total| { + for uint::range(0, count) |_i| { do total.with |count| { - **count += 1u; + **count += 1; } } })); @@ -587,7 +587,7 @@ pub mod tests { // accesses will also fail. let x = exclusive(1); let x2 = x.clone(); - do task::try { + do task::try |move x2| { do x2.with |one| { assert *one == 2; } @@ -600,27 +600,28 @@ pub mod tests { #[test] pub fn exclusive_unwrap_basic() { let x = exclusive(~~"hello"); - assert unwrap_exclusive(x) == ~~"hello"; + assert unwrap_exclusive(move x) == ~~"hello"; } #[test] pub fn exclusive_unwrap_contended() { let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone()); - do task::spawn { + do task::spawn |move x2| { let x2 = option::swap_unwrap(x2); do x2.with |_hello| { } task::yield(); } - assert unwrap_exclusive(x) == ~~"hello"; + assert unwrap_exclusive(move x) == ~~"hello"; // Now try the same thing, but with the child task blocking. let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone()); let mut res = None; - do task::task().future_result(|+r| res = Some(r)).spawn { + do task::task().future_result(|+r| res = Some(move r)).spawn + |move x2| { let x2 = option::swap_unwrap(x2); - assert unwrap_exclusive(x2) == ~~"hello"; + assert unwrap_exclusive(move x2) == ~~"hello"; } // Have to get rid of our reference before blocking. { let _x = move x; } // FIXME(#3161) util::ignore doesn't work here @@ -633,11 +634,12 @@ pub mod tests { let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone()); let mut res = None; - do task::task().future_result(|+r| res = Some(r)).spawn { + do task::task().future_result(|+r| res = Some(move r)).spawn + |move x2| { let x2 = option::swap_unwrap(x2); - assert unwrap_exclusive(x2) == ~~"hello"; + assert unwrap_exclusive(move x2) == ~~"hello"; } - assert unwrap_exclusive(x) == ~~"hello"; + assert unwrap_exclusive(move x) == ~~"hello"; let res = option::swap_unwrap(&mut res); future::get(&res); } @@ -656,7 +658,7 @@ pub mod tests { for 10.times { task::yield(); } // try to let the unwrapper go fail; // punt it awake from its deadlock } - let _z = unwrap_exclusive(x); + let _z = unwrap_exclusive(move x); do x2.with |_hello| { } }; assert result.is_err(); diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index 505804b3da8..3fa37a2fb8e 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -246,7 +246,7 @@ impl<V: TyVisitor MovePtr> MovePtrAdaptor<V>: TyVisitor { } fn visit_unboxed_vec(mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<vec::raw::UnboxedVecRepr>(); + self.align_to::<vec::UnboxedVecRepr>(); if ! self.inner.visit_vec(mtbl, inner) { return false; } true } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 0501b032d2d..b246adcb1d7 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -15,7 +15,8 @@ use to_str::ToStr; use cast::transmute; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; use reflect::{MovePtr, MovePtrAdaptor}; -use vec::raw::{VecRepr, UnboxedVecRepr, SliceRepr}; +use vec::UnboxedVecRepr; +use vec::raw::{VecRepr, SliceRepr}; pub use box::raw::BoxRepr; use box::raw::BoxHeaderRepr; @@ -155,7 +156,7 @@ impl ReprVisitor { fn visit_ptr_inner(ptr: *c_void, inner: *TyDesc) -> bool { let mut u = ReprVisitor(ptr, self.writer); let v = reflect::MovePtrAdaptor(move u); - visit_tydesc(inner, v as @TyVisitor); + visit_tydesc(inner, (move v) as @TyVisitor); true } @@ -303,7 +304,7 @@ impl ReprVisitor : TyVisitor { fn visit_unboxed_vec(mtbl: uint, inner: *TyDesc) -> bool { - do self.get::<vec::raw::UnboxedVecRepr> |b| { + do self.get::<vec::UnboxedVecRepr> |b| { self.write_unboxed_vec_repr(mtbl, b, inner); } } @@ -452,7 +453,7 @@ pub fn write_repr2<T>(writer: @Writer, object: &T) { let tydesc = intrinsic::get_tydesc::<T>(); let mut u = ReprVisitor(ptr, writer); let v = reflect::MovePtrAdaptor(move u); - visit_tydesc(tydesc, v as @TyVisitor) + visit_tydesc(tydesc, (move v) as @TyVisitor) } #[test] @@ -558,7 +559,7 @@ impl ReprPrinter { unsafe { self.align(sys::min_align_of::<T>()); let value_addr: &T = transmute(copy self.ptr); - (*value_addr).write_repr(self.writer); + value_addr.write_repr(self.writer); self.bump(sys::size_of::<T>()); true } @@ -991,7 +992,7 @@ pub fn write_repr<T>(writer: @Writer, object: &T) { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *c_void; let tydesc = sys::get_type_desc::<T>(); - let tydesc = cast::transmute(tydesc); + let tydesc = cast::transmute(move tydesc); let repr_printer = @ReprPrinter { ptr: ptr, diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 39fae8905f9..06d8c0da0d0 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -105,11 +105,9 @@ pub pure fn to_either<T: Copy, U: Copy>(res: &Result<U, T>) */ pub fn chain<T, U: Copy, V: Copy>(res: Result<T, V>, op: fn(t: T) -> Result<U, V>) -> Result<U, V> { - // XXX: Should be writable with move + match - if res.is_ok() { - op(unwrap(res)) - } else { - Err(unwrap_err(res)) + match move res { + Ok(move t) => op(move t), + Err(move e) => Err(e) } } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 0ff91749209..cb6a7f737f9 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -226,7 +226,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> Program { fn ProgRes(r: ProgRepr) -> ProgRes { ProgRes { - r: r + r: move r } } @@ -248,12 +248,14 @@ pub fn start_program(prog: &str, args: &[~str]) -> Program { } fn read_all(rd: io::Reader) -> ~str { - let mut buf = ~""; - while !rd.eof() { - let bytes = rd.read_bytes(4096u); - buf += str::from_bytes(bytes); - } - move buf + let buf = io::with_bytes_writer(|wr| { + let mut bytes = [mut 0, ..4096]; + while !rd.eof() { + let nread = rd.read(bytes, bytes.len()); + wr.write(bytes.view(0, nread)); + } + }); + str::from_bytes(buf) } /** @@ -313,10 +315,10 @@ pub fn program_output(prog: &str, args: &[~str]) -> let stream = comm::recv(p); match stream { (1, copy s) => { - outs = s; + outs = move s; } (2, copy s) => { - errs = s; + errs = move s; } (n, _) => { fail(fmt!("program_output received an unexpected file \ @@ -341,13 +343,15 @@ fn writeclose(fd: c_int, s: ~str) { fn readclose(fd: c_int) -> ~str { let file = os::fdopen(fd); let reader = io::FILE_reader(file, false); - let mut buf = ~""; - while !reader.eof() { - let bytes = reader.read_bytes(4096u); - buf += str::from_bytes(bytes); - } + let buf = io::with_bytes_writer(|writer| { + let mut bytes = [mut 0, ..4096]; + while !reader.eof() { + let nread = reader.read(bytes, bytes.len()); + writer.write(bytes.view(0, nread)); + } + }); os::fclose(file); - move buf + str::from_bytes(buf) } /// Waits for a process to exit and returns the exit code diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index 4a56ee5b896..58b35b82a31 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -17,6 +17,9 @@ pub trait SendMap<K:Eq Hash, V: Copy> { fn insert(&mut self, k: K, +v: V) -> bool; fn remove(&mut self, k: &K) -> bool; + fn pop(&mut self, k: &K) -> Option<V>; + fn swap(&mut self, k: K, +v: V) -> Option<V>; + fn consume(&mut self, f: fn(K, V)); fn clear(&mut self); pure fn len(&const self) -> uint; pure fn is_empty(&const self) -> bool; @@ -182,8 +185,8 @@ pub mod linear { debug!("insert fresh (%?->%?) at idx %?, hash %?", k, v, idx, hash); self.buckets[idx] = Some(Bucket {hash: hash, - key: k, - value: v}); + key: move k, + value: move v}); self.size += 1; true } @@ -191,13 +194,59 @@ pub mod linear { debug!("insert overwrite (%?->%?) at idx %?, hash %?", k, v, idx, hash); self.buckets[idx] = Some(Bucket {hash: hash, - key: k, - value: v}); + key: move k, + value: move v}); false } } } + fn pop_internal(&mut self, hash: uint, k: &K) -> Option<V> { + // Removing from an open-addressed hashtable + // is, well, painful. The problem is that + // the entry may lie on the probe path for other + // entries, so removing it would make you think that + // those probe paths are empty. + // + // To address this we basically have to keep walking, + // re-inserting entries we find until we reach an empty + // bucket. We know we will eventually reach one because + // we insert one ourselves at the beginning (the removed + // entry). + // + // I found this explanation elucidating: + // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf + let mut idx = match self.bucket_for_key_with_hash(self.buckets, + hash, k) { + TableFull | FoundHole(_) => return None, + FoundEntry(idx) => idx + }; + + let len_buckets = self.buckets.len(); + let mut bucket = None; + self.buckets[idx] <-> bucket; + + let value = match move bucket { + None => None, + Some(move bucket) => { + let Bucket { value: move value, _ } = move bucket; + Some(move value) + }, + }; + + idx = self.next_bucket(idx, len_buckets); + while self.buckets[idx].is_some() { + let mut bucket = None; + bucket <-> self.buckets[idx]; + self.insert_opt_bucket(move bucket); + idx = self.next_bucket(idx, len_buckets); + } + self.size -= 1; + + move value + + } + fn search(&self, hash: uint, op: fn(x: &Option<Bucket<K,V>>) -> bool) { @@ -222,37 +271,55 @@ pub mod linear { } fn remove(&mut self, k: &K) -> bool { - // Removing from an open-addressed hashtable - // is, well, painful. The problem is that - // the entry may lie on the probe path for other - // entries, so removing it would make you think that - // those probe paths are empty. - // - // To address this we basically have to keep walking, - // re-inserting entries we find until we reach an empty - // bucket. We know we will eventually reach one because - // we insert one ourselves at the beginning (the removed - // entry). - // - // I found this explanation elucidating: - // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf + match self.pop(k) { + Some(_) => true, + None => false, + } + } - let mut idx = match self.bucket_for_key(self.buckets, k) { - TableFull | FoundHole(_) => return false, - FoundEntry(idx) => idx - }; + fn pop(&mut self, k: &K) -> Option<V> { + let hash = k.hash_keyed(self.k0, self.k1) as uint; + self.pop_internal(hash, k) + } - let len_buckets = self.buckets.len(); - self.buckets[idx] = None; - idx = self.next_bucket(idx, len_buckets); - while self.buckets[idx].is_some() { - let mut bucket = None; - bucket <-> self.buckets[idx]; - self.insert_opt_bucket(move bucket); - idx = self.next_bucket(idx, len_buckets); + fn swap(&mut self, k: K, v: V) -> Option<V> { + // this could be faster. + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let old_value = self.pop_internal(hash, &k); + + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + self.insert_internal(hash, move k, move v); + + move old_value + } + + fn consume(&mut self, f: fn(K, V)) { + let mut buckets = ~[]; + self.buckets <-> buckets; + self.size = 0; + + do vec::consume(move buckets) |_i, bucket| { + match move bucket { + None => { }, + Some(move bucket) => { + let Bucket { + key: move key, + value: move value, + _ + } = move bucket; + f(move key, move value) + } + } } - self.size -= 1; - return true; } fn clear(&mut self) { @@ -350,7 +417,6 @@ pub mod linear { } option::unwrap(move value) } - } } @@ -408,6 +474,37 @@ pub mod test { } #[test] + pub fn pops() { + let mut m = ~LinearMap(); + m.insert(1, 2); + assert m.pop(&1) == Some(2); + assert m.pop(&1) == None; + } + + #[test] + pub fn swaps() { + let mut m = ~LinearMap(); + assert m.swap(1, 2) == None; + assert m.swap(1, 3) == Some(2); + assert m.swap(1, 4) == Some(3); + } + + #[test] + pub fn consumes() { + let mut m = ~LinearMap(); + assert m.insert(1, 2); + assert m.insert(2, 3); + let mut m2 = ~LinearMap(); + do m.consume |k, v| { + m2.insert(k, v); + } + assert m.len() == 0; + assert m2.len() == 2; + assert m2.find(&1) == Some(2); + assert m2.find(&2) == Some(3); + } + + #[test] pub fn iterate() { let mut m = linear::linear_map_with_capacity(4); for uint::range(0, 32) |i| { diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 285b6114957..0c722c437ee 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -49,7 +49,7 @@ pub pure fn from_byte(b: u8) -> ~str { } /// Appends a character at the end of a string -pub fn push_char(s: &const ~str, ch: char) { +pub fn push_char(s: &mut ~str, ch: char) { unsafe { let code = ch as uint; let nb = if code < max_one_b { 1u } @@ -140,7 +140,7 @@ pub pure fn from_chars(chs: &[char]) -> ~str { /// Appends a string slice to the back of a string, without overallocating #[inline(always)] -pub fn push_str_no_overallocate(lhs: &const ~str, rhs: &str) { +pub fn push_str_no_overallocate(lhs: &mut ~str, rhs: &str) { unsafe { let llen = lhs.len(); let rlen = rhs.len(); @@ -157,7 +157,7 @@ pub fn push_str_no_overallocate(lhs: &const ~str, rhs: &str) { } /// Appends a string slice to the back of a string #[inline(always)] -pub fn push_str(lhs: &const ~str, rhs: &str) { +pub fn push_str(lhs: &mut ~str, rhs: &str) { unsafe { let llen = lhs.len(); let rlen = rhs.len(); @@ -203,6 +203,13 @@ pub pure fn connect(v: &[~str], sep: &str) -> ~str { move s } +/// Given a string, make a new string with repeated copies of it +pub fn repeat(ss: &str, nn: uint) -> ~str { + let mut acc = ~""; + for nn.times { acc += ss; } + move acc +} + /* Section: Adding to and removing from a string */ @@ -214,7 +221,7 @@ Section: Adding to and removing from a string * * If the string does not contain any characters */ -pub fn pop_char(s: &const ~str) -> char { +pub fn pop_char(s: &mut ~str) -> char { let end = len(*s); assert end > 0u; let {ch, prev} = char_range_at_reverse(*s, end); @@ -573,6 +580,40 @@ pub pure fn words(s: &str) -> ~[~str] { split_nonempty(s, |c| char::is_whitespace(c)) } +/** Split a string into a vector of substrings, + * each of which is less than a limit + */ +pub fn split_within(ss: &str, lim: uint) -> ~[~str] { + let words = str::words(ss); + + // empty? + if words == ~[] { return ~[]; } + + let mut rows : ~[~str] = ~[]; + let mut row : ~str = ~""; + + for words.each |wptr| { + let word = copy *wptr; + + // if adding this word to the row would go over the limit, + // then start a new row + if row.len() + word.len() + 1 > lim { + rows.push(copy row); // save previous row + row = move word; // start a new one + } else { + if row.len() > 0 { row += ~" " } // separate words + row += word; // append to this row + } + } + + // save the last row + if row != ~"" { rows.push(move row); } + + move rows +} + + + /// Convert a string to lowercase. ASCII only pub pure fn to_lower(s: &str) -> ~str { map(s, @@ -1361,7 +1402,7 @@ pub pure fn is_whitespace(s: &str) -> bool { * * Alphanumeric characters are determined by `char::is_alphanumeric` */ -fn is_alphanumeric(s: &str) -> bool { +pure fn is_alphanumeric(s: &str) -> bool { return all(s, char::is_alphanumeric); } @@ -1473,6 +1514,11 @@ pub pure fn from_utf16(v: &[u16]) -> ~str { move buf } +pub pure fn with_capacity(capacity: uint) -> ~str { + let mut buf = ~""; + unsafe { reserve(&mut buf, capacity); } + move buf +} /** * As char_len but for a slice of a string @@ -1802,9 +1848,9 @@ pub pure fn as_buf<T>(s: &str, f: fn(*u8, uint) -> T) -> T { * * s - A string * * n - The number of bytes to reserve space for */ -pub fn reserve(s: &const ~str, n: uint) { +pub fn reserve(s: &mut ~str, n: uint) { unsafe { - let v: *mut ~[u8] = cast::transmute(copy s); + let v: *mut ~[u8] = cast::transmute(s); vec::reserve(&mut *v, n + 1); } } @@ -1829,7 +1875,7 @@ pub fn reserve(s: &const ~str, n: uint) { * * s - A string * * n - The number of bytes to reserve space for */ -pub fn reserve_at_least(s: &const ~str, n: uint) { +pub fn reserve_at_least(s: &mut ~str, n: uint) { reserve(s, uint::next_power_of_two(n + 1u) - 1u) } @@ -1906,7 +1952,7 @@ pub mod raw { } /// Converts a vector of bytes to a string. - pub pub unsafe fn from_bytes(v: &[const u8]) -> ~str { + pub unsafe fn from_bytes(v: &[const u8]) -> ~str { do vec::as_const_buf(v) |buf, len| { from_buf_len(buf, len) } @@ -1974,7 +2020,7 @@ pub mod raw { } /// Appends a byte to a string. (Not UTF-8 safe). - pub unsafe fn push_byte(s: &const ~str, b: u8) { + pub unsafe fn push_byte(s: &mut ~str, b: u8) { reserve_at_least(s, s.len() + 1); do as_buf(*s) |buf, len| { let buf: *mut u8 = ::cast::reinterpret_cast(&buf); @@ -1984,13 +2030,13 @@ pub mod raw { } /// Appends a vector of bytes to a string. (Not UTF-8 safe). - unsafe fn push_bytes(s: &const ~str, bytes: &[u8]) { + unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) { reserve_at_least(s, s.len() + bytes.len()); for vec::each(bytes) |byte| { push_byte(s, *byte); } } /// Removes the last byte from a string and returns it. (Not UTF-8 safe). - pub unsafe fn pop_byte(s: &const ~str) -> u8 { + pub unsafe fn pop_byte(s: &mut ~str) -> u8 { let len = len(*s); assert (len > 0u); let b = s[len - 1u]; @@ -2008,7 +2054,7 @@ pub mod raw { } /// Sets the length of the string and adds the null terminator - pub unsafe fn set_len(v: &const ~str, new_len: uint) { + pub unsafe fn set_len(v: &mut ~str, new_len: uint) { let v: **vec::raw::VecRepr = cast::transmute(copy v); let repr: *vec::raw::VecRepr = *v; (*repr).unboxed.fill = new_len + 1u; @@ -2029,23 +2075,23 @@ pub mod raw { } -pub trait UniqueStr { - fn trim() -> self; - fn trim_left() -> self; - fn trim_right() -> self; +pub trait Trimmable { + pure fn trim() -> self; + pure fn trim_left() -> self; + pure fn trim_right() -> self; } /// Extension methods for strings -impl ~str: UniqueStr { +impl ~str: Trimmable { /// Returns a string with leading and trailing whitespace removed #[inline] - fn trim() -> ~str { trim(self) } + pure fn trim() -> ~str { trim(self) } /// Returns a string with leading whitespace removed #[inline] - fn trim_left() -> ~str { trim_left(self) } + pure fn trim_left() -> ~str { trim_left(self) } /// Returns a string with trailing whitespace removed #[inline] - fn trim_right() -> ~str { trim_right(self) } + pure fn trim_right() -> ~str { trim_right(self) } } #[cfg(notest)] @@ -2062,31 +2108,35 @@ pub mod traits { pub mod traits {} pub trait StrSlice { - fn all(it: fn(char) -> bool) -> bool; - fn any(it: fn(char) -> bool) -> bool; - fn contains(needle: &a/str) -> bool; - fn contains_char(needle: char) -> bool; - fn each(it: fn(u8) -> bool); - fn eachi(it: fn(uint, u8) -> bool); - fn each_char(it: fn(char) -> bool); - fn each_chari(it: fn(uint, char) -> bool); - fn ends_with(needle: &str) -> bool; - fn is_empty() -> bool; - fn is_not_empty() -> bool; - fn is_whitespace() -> bool; - fn is_alphanumeric() -> bool; + pure fn all(it: fn(char) -> bool) -> bool; + pure fn any(it: fn(char) -> bool) -> bool; + pure fn contains(needle: &a/str) -> bool; + pure fn contains_char(needle: char) -> bool; + pure fn each(it: fn(u8) -> bool); + pure fn eachi(it: fn(uint, u8) -> bool); + pure fn each_char(it: fn(char) -> bool); + pure fn each_chari(it: fn(uint, char) -> bool); + pure fn ends_with(needle: &str) -> bool; + pure fn is_empty() -> bool; + pure fn is_not_empty() -> bool; + pure fn is_whitespace() -> bool; + pure fn is_alphanumeric() -> bool; pure fn len() -> uint; pure fn slice(begin: uint, end: uint) -> ~str; - fn split(sepfn: fn(char) -> bool) -> ~[~str]; - fn split_char(sep: char) -> ~[~str]; - fn split_str(sep: &a/str) -> ~[~str]; - fn starts_with(needle: &a/str) -> bool; - fn substr(begin: uint, n: uint) -> ~str; + pure fn split(sepfn: fn(char) -> bool) -> ~[~str]; + pure fn split_char(sep: char) -> ~[~str]; + pure fn split_str(sep: &a/str) -> ~[~str]; + pure fn starts_with(needle: &a/str) -> bool; + pure fn substr(begin: uint, n: uint) -> ~str; pure fn to_lower() -> ~str; pure fn to_upper() -> ~str; - fn escape_default() -> ~str; - fn escape_unicode() -> ~str; - pure fn to_unique() -> ~str; + pure fn escape_default() -> ~str; + pure fn escape_unicode() -> ~str; + pure fn trim() -> ~str; + pure fn trim_left() -> ~str; + pure fn trim_right() -> ~str; + pure fn to_owned() -> ~str; + pure fn to_managed() -> @str; pure fn char_at(i: uint) -> char; } @@ -2097,54 +2147,56 @@ impl &str: StrSlice { * contains no characters */ #[inline] - fn all(it: fn(char) -> bool) -> bool { all(self, it) } + pure fn all(it: fn(char) -> bool) -> bool { all(self, it) } /** * Return true if a predicate matches any character (and false if it * matches none or there are no characters) */ #[inline] - fn any(it: fn(char) -> bool) -> bool { any(self, it) } + pure fn any(it: fn(char) -> bool) -> bool { any(self, it) } /// Returns true if one string contains another #[inline] - fn contains(needle: &a/str) -> bool { contains(self, needle) } + pure fn contains(needle: &a/str) -> bool { contains(self, needle) } /// Returns true if a string contains a char #[inline] - fn contains_char(needle: char) -> bool { contains_char(self, needle) } + pure fn contains_char(needle: char) -> bool { + contains_char(self, needle) + } /// Iterate over the bytes in a string #[inline] - fn each(it: fn(u8) -> bool) { each(self, it) } + pure fn each(it: fn(u8) -> bool) { each(self, it) } /// Iterate over the bytes in a string, with indices #[inline] - fn eachi(it: fn(uint, u8) -> bool) { eachi(self, it) } + pure fn eachi(it: fn(uint, u8) -> bool) { eachi(self, it) } /// Iterate over the chars in a string #[inline] - fn each_char(it: fn(char) -> bool) { each_char(self, it) } + pure fn each_char(it: fn(char) -> bool) { each_char(self, it) } /// Iterate over the chars in a string, with indices #[inline] - fn each_chari(it: fn(uint, char) -> bool) { each_chari(self, it) } + pure fn each_chari(it: fn(uint, char) -> bool) { each_chari(self, it) } /// Returns true if one string ends with another #[inline] - fn ends_with(needle: &str) -> bool { ends_with(self, needle) } + pure fn ends_with(needle: &str) -> bool { ends_with(self, needle) } /// Returns true if the string has length 0 #[inline] - fn is_empty() -> bool { is_empty(self) } + pure fn is_empty() -> bool { is_empty(self) } /// Returns true if the string has length greater than 0 #[inline] - fn is_not_empty() -> bool { is_not_empty(self) } + pure fn is_not_empty() -> bool { is_not_empty(self) } /** * Returns true if the string contains only whitespace * * Whitespace characters are determined by `char::is_whitespace` */ #[inline] - fn is_whitespace() -> bool { is_whitespace(self) } + pure fn is_whitespace() -> bool { is_whitespace(self) } /** * Returns true if the string contains only alphanumerics * * Alphanumeric characters are determined by `char::is_alphanumeric` */ #[inline] - fn is_alphanumeric() -> bool { is_alphanumeric(self) } + pure fn is_alphanumeric() -> bool { is_alphanumeric(self) } #[inline] /// Returns the size in bytes not counting the null terminator pure fn len() -> uint { len(self) } @@ -2159,21 +2211,21 @@ impl &str: StrSlice { pure fn slice(begin: uint, end: uint) -> ~str { slice(self, begin, end) } /// Splits a string into substrings using a character function #[inline] - fn split(sepfn: fn(char) -> bool) -> ~[~str] { split(self, sepfn) } + pure fn split(sepfn: fn(char) -> bool) -> ~[~str] { split(self, sepfn) } /** * Splits a string into substrings at each occurrence of a given character */ #[inline] - fn split_char(sep: char) -> ~[~str] { split_char(self, sep) } + pure fn split_char(sep: char) -> ~[~str] { split_char(self, sep) } /** * Splits a string into a vector of the substrings separated by a given * string */ #[inline] - fn split_str(sep: &a/str) -> ~[~str] { split_str(self, sep) } + pure fn split_str(sep: &a/str) -> ~[~str] { split_str(self, sep) } /// Returns true if one string starts with another #[inline] - fn starts_with(needle: &a/str) -> bool { starts_with(self, needle) } + pure fn starts_with(needle: &a/str) -> bool { starts_with(self, needle) } /** * Take a substring of another. * @@ -2181,7 +2233,7 @@ impl &str: StrSlice { * `begin`. */ #[inline] - fn substr(begin: uint, n: uint) -> ~str { substr(self, begin, n) } + pure fn substr(begin: uint, n: uint) -> ~str { substr(self, begin, n) } /// Convert a string to lowercase #[inline] pure fn to_lower() -> ~str { to_lower(self) } @@ -2190,13 +2242,31 @@ impl &str: StrSlice { pure fn to_upper() -> ~str { to_upper(self) } /// Escape each char in `s` with char::escape_default. #[inline] - fn escape_default() -> ~str { escape_default(self) } + pure fn escape_default() -> ~str { escape_default(self) } /// Escape each char in `s` with char::escape_unicode. #[inline] - fn escape_unicode() -> ~str { escape_unicode(self) } + pure fn escape_unicode() -> ~str { escape_unicode(self) } + /// Returns a string with leading and trailing whitespace removed + #[inline] + pure fn trim() -> ~str { trim(self) } + /// Returns a string with leading whitespace removed #[inline] - pure fn to_unique() -> ~str { self.slice(0, self.len()) } + pure fn trim_left() -> ~str { trim_left(self) } + /// Returns a string with trailing whitespace removed + #[inline] + pure fn trim_right() -> ~str { trim_right(self) } + + #[inline] + pure fn to_owned() -> ~str { self.slice(0, self.len()) } + + #[inline] + pure fn to_managed() -> @str { + let v = at_vec::from_fn(self.len() + 1, |i| { + if i == self.len() { 0 } else { self[i] } + }); + unsafe { ::cast::transmute(v) } + } #[inline] pure fn char_at(i: uint) -> char { char_at(self, i) } @@ -2451,6 +2521,19 @@ mod tests { } #[test] + fn test_split_within() { + assert split_within(~"", 0) == ~[]; + assert split_within(~"", 15) == ~[]; + assert split_within(~"hello", 15) == ~[~"hello"]; + + let data = ~"\nMary had a little lamb\nLittle lamb\n"; + error!("~~~~ %?", split_within(data, 15)); + assert split_within(data, 15) == ~[~"Mary had a", + ~"little lamb", + ~"Little lamb"]; + } + + #[test] fn test_find_str() { // byte positions assert find_str(~"banana", ~"apple pie").is_none(); @@ -2526,6 +2609,15 @@ mod tests { } #[test] + fn test_repeat() { + assert repeat(~"x", 4) == ~"xxxx"; + assert repeat(~"hi", 4) == ~"hihihihi"; + assert repeat(~"ไท华", 3) == ~"ไท华ไท华ไท华"; + assert repeat(~"", 4) == ~""; + assert repeat(~"hi", 0) == ~""; + } + + #[test] fn test_to_upper() { // libc::toupper, and hence str::to_upper // are culturally insensitive: they only work for ASCII @@ -2547,23 +2639,23 @@ mod tests { #[test] fn test_unsafe_slice() { unsafe { - assert ~"ab" == raw::slice_bytes(~"abc", 0u, 2u); - assert ~"bc" == raw::slice_bytes(~"abc", 1u, 3u); - assert ~"" == raw::slice_bytes(~"abc", 1u, 1u); + assert ~"ab" == raw::slice_bytes(~"abc", 0, 2); + assert ~"bc" == raw::slice_bytes(~"abc", 1, 3); + assert ~"" == raw::slice_bytes(~"abc", 1, 1); fn a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; while i < 100000 { push_str(&mut rs, ~"aaaaaaaaaa"); i += 1; } - return rs; + move rs } fn half_a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; while i < 100000 { push_str(&mut rs, ~"aaaaa"); i += 1; } - return rs; + move rs } assert half_a_million_letter_a() == - raw::slice_bytes(a_million_letter_a(), 0u, 500000u); + raw::slice_bytes(a_million_letter_a(), 0u, 500000); } } @@ -2649,16 +2741,16 @@ mod tests { #[test] fn test_slice() { - assert ~"ab" == slice(~"abc", 0u, 2u); - assert ~"bc" == slice(~"abc", 1u, 3u); - assert ~"" == slice(~"abc", 1u, 1u); - assert ~"\u65e5" == slice(~"\u65e5\u672c", 0u, 3u); + assert ~"ab" == slice(~"abc", 0, 2); + assert ~"bc" == slice(~"abc", 1, 3); + assert ~"" == slice(~"abc", 1, 1); + assert ~"\u65e5" == slice(~"\u65e5\u672c", 0, 3); let data = ~"ประเทศไทย中华"; - assert ~"ป" == slice(data, 0u, 3u); - assert ~"ร" == slice(data, 3u, 6u); - assert ~"" == slice(data, 3u, 3u); - assert ~"华" == slice(data, 30u, 33u); + assert ~"ป" == slice(data, 0, 3); + assert ~"ร" == slice(data, 3, 6); + assert ~"" == slice(data, 3, 3); + assert ~"华" == slice(data, 30, 33); fn a_million_letter_X() -> ~str { let mut i = 0; @@ -2667,13 +2759,13 @@ mod tests { push_str(&mut rs, ~"华华华华华华华华华华"); i += 1; } - return rs; + move rs } fn half_a_million_letter_X() -> ~str { let mut i = 0; let mut rs = ~""; while i < 100000 { push_str(&mut rs, ~"华华华华华"); i += 1; } - return rs; + move rs } assert half_a_million_letter_X() == slice(a_million_letter_X(), 0u, 3u * 500000u); @@ -3175,4 +3267,10 @@ mod tests { assert escape_default(~"\U0001d4ea\r") == ~"\\U0001d4ea\\r"; } + #[test] + fn test_to_managed() { + assert (~"abc").to_managed() == @"abc"; + assert view("abcdef", 1, 5).to_managed() == @"bcde"; + } + } diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 12329616fbf..32a6987a672 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -153,7 +153,7 @@ pub mod tests { assert f(20) == 30; - let original_closure: Closure = cast::transmute(f); + let original_closure: Closure = cast::transmute(move f); let actual_function_pointer = original_closure.code; let environment = original_closure.env; @@ -163,7 +163,7 @@ pub mod tests { env: environment }; - let new_f: fn(int) -> int = cast::transmute(new_closure); + let new_f: fn(int) -> int = cast::transmute(move new_closure); assert new_f(20) == 30; } } diff --git a/src/libcore/task.rs b/src/libcore/task.rs index 8d7791d18d9..d9e213c7f55 100644 --- a/src/libcore/task.rs +++ b/src/libcore/task.rs @@ -217,7 +217,7 @@ pub type TaskOpts = { // sidestep that whole issue by making builders uncopyable and making // the run function move them in. -// FIXME (#2585): Replace the 'consumed' bit with move mode on self +// FIXME (#3724): Replace the 'consumed' bit with move mode on self pub enum TaskBuilder = { opts: TaskOpts, gen_body: fn@(v: fn~()) -> fn~(), @@ -349,7 +349,7 @@ impl TaskBuilder { * Fails if a future_result was already set for this task. */ fn future_result(blk: fn(v: future::Future<TaskResult>)) -> TaskBuilder { - // FIXME (#1087, #1857): Once linked failure and notification are + // FIXME (#3725): Once linked failure and notification are // handled in the library, I can imagine implementing this by just // registering an arbitrary number of task::on_exit handlers and // sending out messages. @@ -424,7 +424,11 @@ impl TaskBuilder { mut notify_chan: move notify_chan, sched: self.opts.sched }, - gen_body: |body| { wrapper(prev_gen_body(move body)) }, + // tjc: I think this is the line that gets miscompiled + // w/ last-use off, if we leave out the move prev_gen_body? + // that makes no sense, though... + gen_body: |move prev_gen_body, + body| { wrapper(prev_gen_body(move body)) }, can_not_copy: None, .. *self.consume() }) @@ -758,9 +762,9 @@ pub unsafe fn atomically<U>(f: fn() -> U) -> U { fn test_cant_dup_task_builder() { let b = task().unlinked(); do b.spawn { } - // FIXME(#2585): For now, this is a -runtime- failure, because we haven't - // got modes on self. When 2585 is fixed, this test should fail to compile - // instead, and should go in tests/compile-fail. + // FIXME(#3724): For now, this is a -runtime- failure, because we haven't + // got move mode on self. When 3724 is fixed, this test should fail to + // compile instead, and should go in tests/compile-fail. do b.spawn { } // b should have been consumed by the previous call } @@ -931,7 +935,7 @@ fn test_add_wrapper() { let ch = comm::Chan(&po); let b0 = task(); let b1 = do b0.add_wrapper |body| { - fn~() { + fn~(move body) { body(); comm::send(ch, ()); } @@ -944,14 +948,15 @@ fn test_add_wrapper() { #[ignore(cfg(windows))] fn test_future_result() { let mut result = None; - do task().future_result(|+r| { result = Some(r); }).spawn { } - assert future::get(&option::unwrap(result)) == Success; + do task().future_result(|+r| { result = Some(move r); }).spawn { } + assert future::get(&option::unwrap(move result)) == Success; result = None; - do task().future_result(|+r| { result = Some(r); }).unlinked().spawn { + do task().future_result(|+r| + { result = Some(move r); }).unlinked().spawn { fail; } - assert future::get(&option::unwrap(result)) == Failure; + assert future::get(&option::unwrap(move result)) == Failure; } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -981,7 +986,7 @@ fn test_spawn_conversation() { let (recv_str, send_int) = do spawn_conversation |recv_int, send_str| { let input = comm::recv(recv_int); let output = int::str(input); - comm::send(send_str, output); + comm::send(send_str, move output); }; comm::send(send_int, 1); assert comm::recv(recv_str) == ~"1"; @@ -1134,7 +1139,7 @@ fn avoid_copying_the_body(spawnfn: fn(v: fn~())) { let x = ~1; let x_in_parent = ptr::addr_of(&(*x)) as uint; - do spawnfn { + do spawnfn |move x| { let x_in_child = ptr::addr_of(&(*x)) as uint; comm::send(ch, x_in_child); } @@ -1160,7 +1165,7 @@ fn test_avoid_copying_the_body_spawn_listener() { #[test] fn test_avoid_copying_the_body_task_spawn() { do avoid_copying_the_body |f| { - do task().spawn { + do task().spawn |move f| { f(); } } @@ -1178,7 +1183,7 @@ fn test_avoid_copying_the_body_spawn_listener_1() { #[test] fn test_avoid_copying_the_body_try() { do avoid_copying_the_body |f| { - do try { + do try |move f| { f() }; } @@ -1187,7 +1192,7 @@ fn test_avoid_copying_the_body_try() { #[test] fn test_avoid_copying_the_body_unlinked() { do avoid_copying_the_body |f| { - do spawn_unlinked { + do spawn_unlinked |move f| { f(); } } @@ -1212,7 +1217,7 @@ fn test_unkillable() { // We want to do this after failing do spawn_unlinked { - for iter::repeat(10u) { yield() } + for iter::repeat(10) { yield() } ch.send(()); } @@ -1226,12 +1231,12 @@ fn test_unkillable() { unsafe { do unkillable { let p = ~0; - let pp: *uint = cast::transmute(p); + let pp: *uint = cast::transmute(move p); // If we are killed here then the box will leak po.recv(); - let _p: ~int = cast::transmute(pp); + let _p: ~int = cast::transmute(move pp); } } @@ -1246,8 +1251,8 @@ fn test_unkillable_nested() { let (ch, po) = pipes::stream(); // We want to do this after failing - do spawn_unlinked { - for iter::repeat(10u) { yield() } + do spawn_unlinked |move ch| { + for iter::repeat(10) { yield() } ch.send(()); } @@ -1262,12 +1267,12 @@ fn test_unkillable_nested() { do unkillable { do unkillable {} // Here's the difference from the previous test. let p = ~0; - let pp: *uint = cast::transmute(p); + let pp: *uint = cast::transmute(move p); // If we are killed here then the box will leak po.recv(); - let _p: ~int = cast::transmute(pp); + let _p: ~int = cast::transmute(move pp); } } @@ -1311,7 +1316,7 @@ fn test_child_doesnt_ref_parent() { fn test_sched_thread_per_core() { let (chan, port) = pipes::stream(); - do spawn_sched(ThreadPerCore) { + do spawn_sched(ThreadPerCore) |move chan| { let cores = rt::rust_num_threads(); let reported_threads = rt::rust_sched_threads(); assert(cores as uint == reported_threads as uint); @@ -1325,7 +1330,7 @@ fn test_sched_thread_per_core() { fn test_spawn_thread_on_demand() { let (chan, port) = pipes::stream(); - do spawn_sched(ManualThreads(2)) { + do spawn_sched(ManualThreads(2)) |move chan| { let max_threads = rt::rust_sched_threads(); assert(max_threads as int == 2); let running_threads = rt::rust_sched_current_nonlazy_threads(); @@ -1333,7 +1338,7 @@ fn test_spawn_thread_on_demand() { let (chan2, port2) = pipes::stream(); - do spawn() { + do spawn() |move chan2| { chan2.send(()); } diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 6eaace1fa1a..533e9851492 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -312,8 +312,8 @@ fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList, TCB { me: me, - tasks: tasks, - ancestors: ancestors, + tasks: move tasks, + ancestors: move ancestors, is_main: is_main, notifier: move notifier } @@ -330,7 +330,7 @@ struct AutoNotify { fn AutoNotify(chan: Chan<Notification>) -> AutoNotify { AutoNotify { - notify_chan: chan, + notify_chan: move chan, failed: true // Un-set above when taskgroup successfully made. } } @@ -652,7 +652,7 @@ fn test_spawn_raw_unsupervise() { mut notify_chan: None, .. default_task_opts() }; - do spawn_raw(opts) { + do spawn_raw(move opts) { fail; } } @@ -667,7 +667,7 @@ fn test_spawn_raw_notify_success() { notify_chan: Some(move notify_ch), .. default_task_opts() }; - do spawn_raw(opts) |move task_ch| { + do spawn_raw(move opts) |move task_ch| { task_ch.send(get_task()); } let task_ = task_po.recv(); @@ -683,10 +683,10 @@ fn test_spawn_raw_notify_failure() { let opts = { linked: false, - notify_chan: Some(notify_ch), + notify_chan: Some(move notify_ch), .. default_task_opts() }; - do spawn_raw(opts) { + do spawn_raw(move opts) |move task_ch| { task_ch.send(get_task()); fail; } diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index a3659937ad4..fb0608906a1 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -8,80 +8,82 @@ The `ToStr` trait for converting to strings #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; -pub trait ToStr { fn to_str() -> ~str; } +pub trait ToStr { pure fn to_str() -> ~str; } impl int: ToStr { - fn to_str() -> ~str { int::str(self) } + pure fn to_str() -> ~str { int::str(self) } } impl i8: ToStr { - fn to_str() -> ~str { i8::str(self) } + pure fn to_str() -> ~str { i8::str(self) } } impl i16: ToStr { - fn to_str() -> ~str { i16::str(self) } + pure fn to_str() -> ~str { i16::str(self) } } impl i32: ToStr { - fn to_str() -> ~str { i32::str(self) } + pure fn to_str() -> ~str { i32::str(self) } } impl i64: ToStr { - fn to_str() -> ~str { i64::str(self) } + pure fn to_str() -> ~str { i64::str(self) } } impl uint: ToStr { - fn to_str() -> ~str { uint::str(self) } + pure fn to_str() -> ~str { uint::str(self) } } impl u8: ToStr { - fn to_str() -> ~str { u8::str(self) } + pure fn to_str() -> ~str { u8::str(self) } } impl u16: ToStr { - fn to_str() -> ~str { u16::str(self) } + pure fn to_str() -> ~str { u16::str(self) } } impl u32: ToStr { - fn to_str() -> ~str { u32::str(self) } + pure fn to_str() -> ~str { u32::str(self) } } impl u64: ToStr { - fn to_str() -> ~str { u64::str(self) } + pure fn to_str() -> ~str { u64::str(self) } } impl float: ToStr { - fn to_str() -> ~str { float::to_str(self, 4u) } + pure fn to_str() -> ~str { float::to_str(self, 4u) } } impl f32: ToStr { - fn to_str() -> ~str { float::to_str(self as float, 4u) } + pure fn to_str() -> ~str { float::to_str(self as float, 4u) } } impl f64: ToStr { - fn to_str() -> ~str { float::to_str(self as float, 4u) } + pure fn to_str() -> ~str { float::to_str(self as float, 4u) } } impl bool: ToStr { - fn to_str() -> ~str { bool::to_str(self) } + pure fn to_str() -> ~str { bool::to_str(self) } } impl (): ToStr { - fn to_str() -> ~str { ~"()" } + pure fn to_str() -> ~str { ~"()" } } impl ~str: ToStr { - fn to_str() -> ~str { copy self } + pure fn to_str() -> ~str { copy self } } impl &str: ToStr { - fn to_str() -> ~str { str::from_slice(self) } + pure fn to_str() -> ~str { str::from_slice(self) } } impl @str: ToStr { - fn to_str() -> ~str { str::from_slice(self) } + pure fn to_str() -> ~str { str::from_slice(self) } } impl<A: ToStr Copy, B: ToStr Copy> (A, B): ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let (a, b) = self; ~"(" + a.to_str() + ~", " + b.to_str() + ~")" } } impl<A: ToStr Copy, B: ToStr Copy, C: ToStr Copy> (A, B, C): ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let (a, b, c) = self; ~"(" + a.to_str() + ~", " + b.to_str() + ~", " + c.to_str() + ~")" } } impl<A: ToStr> ~[A]: ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str unsafe { + // Bleh -- not really unsafe + // push_str and push_char let mut acc = ~"[", first = true; - for vec::each(self) |elt| { + for vec::each(self) |elt| unsafe { if first { first = false; } else { str::push_str(&mut acc, ~", "); } str::push_str(&mut acc, elt.to_str()); @@ -92,10 +94,10 @@ impl<A: ToStr> ~[A]: ToStr { } impl<A: ToStr> @A: ToStr { - fn to_str() -> ~str { ~"@" + (*self).to_str() } + pure fn to_str() -> ~str { ~"@" + (*self).to_str() } } impl<A: ToStr> ~A: ToStr { - fn to_str() -> ~str { ~"~" + (*self).to_str() } + pure fn to_str() -> ~str { ~"~" + (*self).to_str() } } #[cfg(test)] diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 246ce16c813..ee9e0c84be6 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -6,13 +6,13 @@ use cmp::{Eq, Ord}; -pub trait TupleOps<T,U> { +pub trait CopyableTuple<T, U> { pure fn first() -> T; pure fn second() -> U; pure fn swap() -> (U, T); } -impl<T: Copy, U: Copy> (T, U): TupleOps<T,U> { +impl<T: Copy, U: Copy> (T, U): CopyableTuple<T, U> { /// Return the first element of self pure fn first() -> T { @@ -34,6 +34,24 @@ impl<T: Copy, U: Copy> (T, U): TupleOps<T,U> { } +pub trait ImmutableTuple<T, U> { + pure fn first_ref(&self) -> &self/T; + pure fn second_ref(&self) -> &self/U; +} + +impl<T, U> (T, U): ImmutableTuple<T, U> { + pure fn first_ref(&self) -> &self/T { + match *self { + (ref t, _) => t, + } + } + pure fn second_ref(&self) -> &self/U { + match *self { + (_, ref u) => u, + } + } +} + pub trait ExtendedTupleOps<A,B> { fn zip(&self) -> ~[(A, B)]; fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C]; @@ -146,6 +164,13 @@ impl<A: Ord, B: Ord, C: Ord> (A, B, C) : Ord { } #[test] +fn test_tuple_ref() { + let x = (~"foo", ~"bar"); + assert x.first_ref() == &~"foo"; + assert x.second_ref() == &~"bar"; +} + +#[test] #[allow(non_implicitly_copyable_typarams)] fn test_tuple() { assert (948, 4039.48).first() == 948; diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 7d0421c0730..3199262ae16 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -187,19 +187,7 @@ pub pure fn to_str_bytes<U>(neg: bool, num: T, radix: uint, // Enough room to hold any number in any radix. // Worst case: 64-bit number, binary-radix, with // a leading negative sign = 65 bytes. - let buf : [mut u8]/65 = - [mut - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - - 0u8,0u8,0u8,0u8,0u8 - ]/65; + let buf : [mut u8 * 65] = [mut 0u8, ..65]; // FIXME (#2649): post-snapshot, you can do this without the raw // pointers and unsafe bits, and the codegen will prove it's all @@ -232,7 +220,7 @@ pub pure fn to_str_bytes<U>(neg: bool, num: T, radix: uint, } /// Convert to a string -pub fn str(i: T) -> ~str { return to_str(i, 10u); } +pub pure fn str(i: T) -> ~str { return to_str(i, 10u); } #[test] pub fn test_to_str() { diff --git a/src/libcore/util.rs b/src/libcore/util.rs index 6c633f16abf..8380cbf6b63 100644 --- a/src/libcore/util.rs +++ b/src/libcore/util.rs @@ -100,7 +100,7 @@ mod tests { let x = ~[(5, false)]; //FIXME #3387 assert x.eq(id(copy x)); let y = copy x; - assert x.eq(&id(y)); + assert x.eq(&id(move y)); } #[test] fn test_swap() { diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 3a2b73f5b5b..2e91c4b22c4 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -340,15 +340,15 @@ pub fn splitn<T: Copy>(v: &[T], n: uint, f: fn(t: &T) -> bool) -> ~[~[T]] { */ pub fn rsplit<T: Copy>(v: &[T], f: fn(t: &T) -> bool) -> ~[~[T]] { let ln = len(v); - if (ln == 0u) { return ~[] } + if (ln == 0) { return ~[] } let mut end = ln; let mut result = ~[]; - while end > 0u { - match rposition_between(v, 0u, end, f) { + while end > 0 { + match rposition_between(v, 0, end, f) { None => break, Some(i) => { - result.push(slice(v, i + 1u, end)); + result.push(slice(v, i + 1, end)); end = i; } } @@ -416,7 +416,7 @@ pub fn shift<T>(v: &mut ~[T]) -> T { pub fn unshift<T>(v: &mut ~[T], x: T) { let mut vv = ~[move x]; *v <-> vv; - v.push_all_move(vv); + v.push_all_move(move vv); } pub fn consume<T>(v: ~[T], f: fn(uint, v: T)) unsafe { @@ -433,7 +433,7 @@ pub fn consume<T>(v: ~[T], f: fn(uint, v: T)) unsafe { } pub fn consume_mut<T>(v: ~[mut T], f: fn(uint, v: T)) { - consume(vec::from_mut(v), f) + consume(vec::from_mut(move v), f) } /// Remove the last element from a vector and return it @@ -591,7 +591,7 @@ pub pure fn append_one<T>(lhs: ~[T], x: T) -> ~[T] { #[inline(always)] pure fn append_mut<T: Copy>(lhs: ~[mut T], rhs: &[const T]) -> ~[mut T] { - to_mut(append(from_mut(lhs), rhs)) + to_mut(append(from_mut(move lhs), rhs)) } /** @@ -1621,7 +1621,7 @@ impl<T> ~[T]: MutableVector<T> { } fn unshift(&mut self, x: T) { - unshift(self, x) + unshift(self, move x) } fn swap_remove(&mut self, index: uint) -> T { @@ -1657,9 +1657,29 @@ impl<T: Eq> ~[T]: MutableEqVector<T> { } } + +/** +* Constructs a vector from an unsafe pointer to a buffer +* +* # Arguments +* +* * ptr - An unsafe pointer to a buffer of `T` +* * elts - The number of elements in the buffer +*/ +// Wrapper for fn in raw: needs to be called by net_tcp::on_tcp_read_cb +pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> ~[T] { + raw::from_buf_raw(ptr, elts) +} + +/// The internal 'unboxed' representation of a vector +pub struct UnboxedVecRepr { + mut fill: uint, + mut alloc: uint, + data: u8 +} + /// Unsafe operations -pub mod raw { - // FIXME: This should have crate visibility (#1893 blocks that) +mod raw { /// The internal representation of a (boxed) vector pub struct VecRepr { @@ -1667,35 +1687,12 @@ pub mod raw { unboxed: UnboxedVecRepr } - /// The internal 'unboxed' representation of a vector - pub struct UnboxedVecRepr { - mut fill: uint, - mut alloc: uint, - data: u8 - } - pub type SliceRepr = { mut data: *u8, mut len: uint }; /** - * Constructs a vector from an unsafe pointer to a buffer - * - * # Arguments - * - * * ptr - An unsafe pointer to a buffer of `T` - * * elts - The number of elements in the buffer - */ - #[inline(always)] - pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> ~[T] { - let mut dst = with_capacity(elts); - set_len(&mut dst, elts); - as_mut_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts)); - move dst - } - - /** * Sets the length of a vector * * This will explicitly set the size of the vector, without actually @@ -1776,6 +1773,23 @@ pub mod raw { } /** + * Constructs a vector from an unsafe pointer to a buffer + * + * # Arguments + * + * * ptr - An unsafe pointer to a buffer of `T` + * * elts - The number of elements in the buffer + */ + // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb + #[inline(always)] + pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] { + let mut dst = with_capacity(elts); + set_len(&mut dst, elts); + as_mut_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts)); + move dst + } + + /** * Copies data from one vector to another. * * Copies `count` bytes from `src` to `dst`. The source and destination @@ -1959,7 +1973,7 @@ mod tests { // Test on-stack copy-from-buf. let a = ~[1, 2, 3]; let mut ptr = raw::to_ptr(a); - let b = raw::from_buf(ptr, 3u); + let b = from_buf(ptr, 3u); assert (len(b) == 3u); assert (b[0] == 1); assert (b[1] == 2); @@ -1968,7 +1982,7 @@ mod tests { // Test on-heap copy-from-buf. let c = ~[1, 2, 3, 4, 5]; ptr = raw::to_ptr(c); - let d = raw::from_buf(ptr, 5u); + let d = from_buf(ptr, 5u); assert (len(d) == 5u); assert (d[0] == 1); assert (d[1] == 2); @@ -2194,7 +2208,7 @@ mod tests { #[test] fn test_dedup() { fn case(a: ~[uint], b: ~[uint]) { - let mut v = a; + let mut v = move a; v.dedup(); assert(v == b); } @@ -2450,13 +2464,13 @@ mod tests { let v1 = ~[1, 2, 3]; let v2 = ~[4, 5, 6]; - let z1 = zip(v1, v2); + let z1 = zip(move v1, move v2); assert ((1, 4) == z1[0]); assert ((2, 5) == z1[1]); assert ((3, 6) == z1[2]); - let (left, right) = unzip(z1); + let (left, right) = unzip(move z1); assert ((1, 4) == (left[0], right[0])); assert ((2, 5) == (left[1], right[1])); @@ -2754,7 +2768,7 @@ mod tests { unsafe { let x = ~[1, 2, 3]; let addr = raw::to_ptr(x); - let x_mut = to_mut(x); + let x_mut = to_mut(move x); let addr_mut = raw::to_ptr(x_mut); assert addr == addr_mut; } @@ -2765,7 +2779,7 @@ mod tests { unsafe { let x = ~[mut 1, 2, 3]; let addr = raw::to_ptr(x); - let x_imm = from_mut(x); + let x_imm = from_mut(move x); let addr_imm = raw::to_ptr(x_imm); assert addr == addr_imm; } @@ -2963,7 +2977,7 @@ mod tests { fn test_consume_fail() { let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do consume(v) |_i, _elt| { + do consume(move v) |_i, _elt| { if i == 2 { fail } @@ -2977,7 +2991,7 @@ mod tests { fn test_consume_mut_fail() { let v = ~[mut (~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do consume_mut(v) |_i, _elt| { + do consume_mut(move v) |_i, _elt| { if i == 2 { fail } @@ -3020,7 +3034,7 @@ mod tests { fn test_map_consume_fail() { let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do map_consume(v) |_elt| { + do map_consume(move v) |_elt| { if i == 2 { fail } diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index addabb2ddb9..9c793028a52 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -124,7 +124,7 @@ pub fn mutex_arc_with_condvars<T: Send>(user_data: T, num_condvars: uint) -> MutexARC<T> { let data = MutexARCInner { lock: mutex_with_condvars(num_condvars), - failed: false, data: user_data }; + failed: false, data: move user_data }; MutexARC { x: unsafe { shared_mutable_state(move data) } } } @@ -190,7 +190,7 @@ impl<T: Send> &MutexARC<T> { * * Will additionally fail if another task has failed while accessing the arc. */ -// FIXME(#2585) make this a by-move method on the arc +// FIXME(#3724) make this a by-move method on the arc pub fn unwrap_mutex_arc<T: Send>(arc: MutexARC<T>) -> T { let MutexARC { x: x } <- arc; let inner = unsafe { unwrap_shared_mutable_state(move x) }; @@ -258,7 +258,7 @@ pub fn rw_arc_with_condvars<T: Const Send>(user_data: T, num_condvars: uint) -> RWARC<T> { let data = RWARCInner { lock: rwlock_with_condvars(num_condvars), - failed: false, data: user_data }; + failed: false, data: move user_data }; RWARC { x: unsafe { shared_mutable_state(move data) }, cant_nest: () } } @@ -368,7 +368,7 @@ impl<T: Const Send> &RWARC<T> { * Will additionally fail if another task has failed while accessing the arc * in write mode. */ -// FIXME(#2585) make this a by-move method on the arc +// FIXME(#3724) make this a by-move method on the arc pub fn unwrap_rw_arc<T: Const Send>(arc: RWARC<T>) -> T { let RWARC { x: x, _ } <- arc; let inner = unsafe { unwrap_shared_mutable_state(move x) }; @@ -448,7 +448,7 @@ mod tests { let (c, p) = pipes::stream(); - do task::spawn() { + do task::spawn() |move c| { let p = pipes::PortSet(); c.send(p.chan()); @@ -471,8 +471,8 @@ mod tests { let arc = ~MutexARC(false); let arc2 = ~arc.clone(); let (c,p) = pipes::oneshot(); - let (c,p) = (~mut Some(c), ~mut Some(p)); - do task::spawn { + let (c,p) = (~mut Some(move c), ~mut Some(move p)); + do task::spawn |move arc2, move p| { // wait until parent gets in pipes::recv_one(option::swap_unwrap(p)); do arc2.access_cond |state, cond| { @@ -494,7 +494,7 @@ mod tests { let arc2 = ~arc.clone(); let (c,p) = pipes::stream(); - do task::spawn_unlinked { + do task::spawn_unlinked |move arc2, move p| { let _ = p.recv(); do arc2.access_cond |one, cond| { cond.signal(); @@ -513,7 +513,7 @@ mod tests { fn test_mutex_arc_poison() { let arc = ~MutexARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.access |one| { assert *one == 2; } @@ -527,21 +527,21 @@ mod tests { let arc = MutexARC(1); let arc2 = ~(&arc).clone(); let (c,p) = pipes::stream(); - do task::spawn { + do task::spawn |move c, move arc2| { do arc2.access |one| { c.send(()); assert *one == 2; } } let _ = p.recv(); - let one = unwrap_mutex_arc(arc); + let one = unwrap_mutex_arc(move arc); assert one == 1; } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_rw_arc_poison_wr() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write |one| { assert *one == 2; } @@ -554,7 +554,7 @@ mod tests { fn test_rw_arc_poison_ww() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write |one| { assert *one == 2; } @@ -567,7 +567,7 @@ mod tests { fn test_rw_arc_poison_dw() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write_downgrade |write_mode| { do (&write_mode).write |one| { assert *one == 2; @@ -582,7 +582,7 @@ mod tests { fn test_rw_arc_no_poison_rr() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.read |one| { assert *one == 2; } @@ -595,7 +595,7 @@ mod tests { fn test_rw_arc_no_poison_rw() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.read |one| { assert *one == 2; } @@ -608,9 +608,9 @@ mod tests { fn test_rw_arc_no_poison_dr() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write_downgrade |write_mode| { - let read_mode = arc2.downgrade(write_mode); + let read_mode = arc2.downgrade(move write_mode); do (&read_mode).read |one| { assert *one == 2; } @@ -626,7 +626,7 @@ mod tests { let arc2 = ~arc.clone(); let (c,p) = pipes::stream(); - do task::spawn { + do task::spawn |move arc2, move c| { do arc2.write |num| { for 10.times { let tmp = *num; @@ -642,7 +642,8 @@ mod tests { let mut children = ~[]; for 5.times { let arc3 = ~arc.clone(); - do task::task().future_result(|+r| children.push(r)).spawn { + do task::task().future_result(|+r| children.push(move r)).spawn + |move arc3| { do arc3.read |num| { assert *num >= 0; } @@ -670,9 +671,9 @@ mod tests { let mut reader_convos = ~[]; for 10.times { let ((rc1,rp1),(rc2,rp2)) = (pipes::stream(),pipes::stream()); - reader_convos.push((rc1,rp2)); + reader_convos.push((move rc1, move rp2)); let arcn = ~arc.clone(); - do task::spawn { + do task::spawn |move rp1, move rc2, move arcn| { rp1.recv(); // wait for downgrader to give go-ahead do arcn.read |state| { assert *state == 31337; @@ -684,7 +685,7 @@ mod tests { // Writer task let arc2 = ~arc.clone(); let ((wc1,wp1),(wc2,wp2)) = (pipes::stream(),pipes::stream()); - do task::spawn { + do task::spawn |move arc2, move wc2, move wp1| { wp1.recv(); do arc2.write_cond |state, cond| { assert *state == 0; @@ -717,7 +718,7 @@ mod tests { } } } - let read_mode = arc.downgrade(write_mode); + let read_mode = arc.downgrade(move write_mode); do (&read_mode).read |state| { // complete handshake with other readers for vec::each(reader_convos) |x| { diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 6a2ac88f714..9f40794b28a 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -244,7 +244,7 @@ fn test_arena_destructors() { do arena.alloc { @i }; // Allocate something with funny size and alignment, to keep // things interesting. - do arena.alloc { [0u8, 1u8, 2u8]/3 }; + do arena.alloc { [0u8, 1u8, 2u8] }; } } @@ -258,7 +258,7 @@ fn test_arena_destructors_fail() { do arena.alloc { @i }; // Allocate something with funny size and alignment, to keep // things interesting. - do arena.alloc { [0u8, 1u8, 2u8]/3 }; + do arena.alloc { [0u8, 1u8, 2u8] }; } // Now, fail while allocating do arena.alloc::<@int> { diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 91af4a3d653..2b8e9b6bbd9 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -96,7 +96,7 @@ struct BigBitv { } fn BigBitv(storage: ~[mut uint]) -> BigBitv { - BigBitv {storage: storage} + BigBitv {storage: move storage} } /** @@ -223,7 +223,7 @@ pub fn Bitv (nbits: uint, init: bool) -> Bitv { let s = to_mut(from_elem(nelems, elem)); Big(~BigBitv(move s)) }; - Bitv {rep: rep, nbits: nbits} + Bitv {rep: move rep, nbits: nbits} } priv impl Bitv { @@ -301,7 +301,7 @@ impl Bitv { let st = to_mut(from_elem(self.nbits / uint_bits + 1, 0)); let len = st.len(); for uint::range(0, len) |i| { st[i] = b.storage[i]; }; - Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: st})} + Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: move st})} } } } diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index c888957728a..4f79bf2b316 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -57,7 +57,7 @@ fn test_basic() { let value = value_cell.take(); assert value == ~10; assert value_cell.is_empty(); - value_cell.put_back(value); + value_cell.put_back(move value); assert !value_cell.is_empty(); } diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index 1a897a2c2fa..e604b87b2af 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -52,12 +52,12 @@ pub fn DuplexStream<T: Send, U: Send>() let (c2, p1) = pipes::stream(); let (c1, p2) = pipes::stream(); (DuplexStream { - chan: c1, - port: p1 + chan: move c1, + port: move p1 }, DuplexStream { - chan: c2, - port: p2 + chan: move c2, + port: move p2 }) } diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 3df5a70a0c1..79e491e309b 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -1,21 +1,35 @@ #[forbid(deprecated_mode)]; +use serialization; + // Simple Extensible Binary Markup Language (ebml) reader and writer on a // cursor model. See the specification here: // http://www.matroska.org/technical/specs/rfc/index.html -use core::Option; -use option::{Some, None}; -type EbmlTag = {id: uint, size: uint}; +struct EbmlTag { + id: uint, + size: uint, +} -type EbmlState = {ebml_tag: EbmlTag, tag_pos: uint, data_pos: uint}; +struct EbmlState { + ebml_tag: EbmlTag, + tag_pos: uint, + data_pos: uint, +} // FIXME (#2739): When we have module renaming, make "reader" and "writer" // separate modules within this file. // ebml reading -pub type Doc = {data: @~[u8], start: uint, end: uint}; +struct Doc { + data: @~[u8], + start: uint, + end: uint, +} -type TaggedDoc = {tag: uint, doc: Doc}; +struct TaggedDoc { + tag: uint, + doc: Doc, +} impl Doc: ops::Index<uint,Doc> { pure fn index(tag: uint) -> Doc { @@ -49,15 +63,17 @@ fn vuint_at(data: &[u8], start: uint) -> {val: uint, next: uint} { } pub fn Doc(data: @~[u8]) -> Doc { - return {data: data, start: 0u, end: vec::len::<u8>(*data)}; + Doc { data: data, start: 0u, end: vec::len::<u8>(*data) } } pub fn doc_at(data: @~[u8], start: uint) -> TaggedDoc { let elt_tag = vuint_at(*data, start); let elt_size = vuint_at(*data, elt_tag.next); let end = elt_size.next + elt_size.val; - return {tag: elt_tag.val, - doc: {data: data, start: elt_size.next, end: end}}; + TaggedDoc { + tag: elt_tag.val, + doc: Doc { data: data, start: elt_size.next, end: end } + } } pub fn maybe_get_doc(d: Doc, tg: uint) -> Option<Doc> { @@ -67,19 +83,15 @@ pub fn maybe_get_doc(d: Doc, tg: uint) -> Option<Doc> { let elt_size = vuint_at(*d.data, elt_tag.next); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { - return Some::<Doc>({ - data: d.data, - start: elt_size.next, - end: pos - }); + return Some(Doc { data: d.data, start: elt_size.next, end: pos }); } } - return None::<Doc>; + None } pub fn get_doc(d: Doc, tg: uint) -> Doc { match maybe_get_doc(d, tg) { - Some(d) => return d, + Some(d) => d, None => { error!("failed to find block with tag %u", tg); fail; @@ -93,7 +105,8 @@ pub fn docs(d: Doc, it: fn(uint, Doc) -> bool) { let elt_tag = vuint_at(*d.data, pos); let elt_size = vuint_at(*d.data, elt_tag.next); pos = elt_size.next + elt_size.val; - if !it(elt_tag.val, {data: d.data, start: elt_size.next, end: pos}) { + let doc = Doc { data: d.data, start: elt_size.next, end: pos }; + if !it(elt_tag.val, doc) { break; } } @@ -106,7 +119,8 @@ pub fn tagged_docs(d: Doc, tg: uint, it: fn(Doc) -> bool) { let elt_size = vuint_at(*d.data, elt_tag.next); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { - if !it({data: d.data, start: elt_size.next, end: pos}) { + let doc = Doc { data: d.data, start: elt_size.next, end: pos }; + if !it(doc) { break; } } @@ -116,29 +130,29 @@ pub fn tagged_docs(d: Doc, tg: uint, it: fn(Doc) -> bool) { pub fn doc_data(d: Doc) -> ~[u8] { vec::slice::<u8>(*d.data, d.start, d.end) } pub fn with_doc_data<T>(d: Doc, f: fn(x: &[u8]) -> T) -> T { - return f(vec::view(*d.data, d.start, d.end)); + f(vec::view(*d.data, d.start, d.end)) } -pub fn doc_as_str(d: Doc) -> ~str { return str::from_bytes(doc_data(d)); } +pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) } pub fn doc_as_u8(d: Doc) -> u8 { assert d.end == d.start + 1u; - return (*d.data)[d.start]; + (*d.data)[d.start] } pub fn doc_as_u16(d: Doc) -> u16 { assert d.end == d.start + 2u; - return io::u64_from_be_bytes(*d.data, d.start, 2u) as u16; + io::u64_from_be_bytes(*d.data, d.start, 2u) as u16 } pub fn doc_as_u32(d: Doc) -> u32 { assert d.end == d.start + 4u; - return io::u64_from_be_bytes(*d.data, d.start, 4u) as u32; + io::u64_from_be_bytes(*d.data, d.start, 4u) as u32 } pub fn doc_as_u64(d: Doc) -> u64 { assert d.end == d.start + 8u; - return io::u64_from_be_bytes(*d.data, d.start, 8u); + io::u64_from_be_bytes(*d.data, d.start, 8u) } pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } @@ -147,10 +161,9 @@ pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 } pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 } // ebml writing -type Writer_ = {writer: io::Writer, mut size_positions: ~[uint]}; - -pub enum Writer { - Writer_(Writer_) +struct Serializer { + writer: io::Writer, + priv mut size_positions: ~[uint], } fn write_sized_vuint(w: io::Writer, n: uint, size: uint) { @@ -173,13 +186,13 @@ fn write_vuint(w: io::Writer, n: uint) { fail fmt!("vint to write too big: %?", n); } -pub fn Writer(w: io::Writer) -> Writer { +pub fn Serializer(w: io::Writer) -> Serializer { let size_positions: ~[uint] = ~[]; - return Writer_({writer: w, mut size_positions: size_positions}); + Serializer { writer: w, mut size_positions: size_positions } } // FIXME (#2741): Provide a function to write the standard ebml header. -impl Writer { +impl Serializer { fn start_tag(tag_id: uint) { debug!("Start tag %u", tag_id); @@ -295,12 +308,7 @@ enum EbmlSerializerTag { EsLabel // Used only when debugging } -trait SerializerPriv { - fn _emit_tagged_uint(t: EbmlSerializerTag, v: uint); - fn _emit_label(label: &str); -} - -impl ebml::Writer: SerializerPriv { +priv impl Serializer { // used internally to emit things like the vector length and so on fn _emit_tagged_uint(t: EbmlSerializerTag, v: uint) { assert v <= 0xFFFF_FFFF_u; @@ -318,89 +326,123 @@ impl ebml::Writer: SerializerPriv { } } -impl ebml::Writer { - fn emit_opaque(f: fn()) { +impl Serializer { + fn emit_opaque(&self, f: fn()) { do self.wr_tag(EsOpaque as uint) { f() } } } -impl ebml::Writer: serialization::Serializer { - fn emit_nil() {} +impl Serializer: serialization::Serializer { + fn emit_nil(&self) {} - fn emit_uint(v: uint) { self.wr_tagged_u64(EsUint as uint, v as u64); } - fn emit_u64(v: u64) { self.wr_tagged_u64(EsU64 as uint, v); } - fn emit_u32(v: u32) { self.wr_tagged_u32(EsU32 as uint, v); } - fn emit_u16(v: u16) { self.wr_tagged_u16(EsU16 as uint, v); } - fn emit_u8(v: u8) { self.wr_tagged_u8 (EsU8 as uint, v); } + fn emit_uint(&self, v: uint) { + self.wr_tagged_u64(EsUint as uint, v as u64); + } + fn emit_u64(&self, v: u64) { self.wr_tagged_u64(EsU64 as uint, v); } + fn emit_u32(&self, v: u32) { self.wr_tagged_u32(EsU32 as uint, v); } + fn emit_u16(&self, v: u16) { self.wr_tagged_u16(EsU16 as uint, v); } + fn emit_u8(&self, v: u8) { self.wr_tagged_u8 (EsU8 as uint, v); } - fn emit_int(v: int) { self.wr_tagged_i64(EsInt as uint, v as i64); } - fn emit_i64(v: i64) { self.wr_tagged_i64(EsI64 as uint, v); } - fn emit_i32(v: i32) { self.wr_tagged_i32(EsI32 as uint, v); } - fn emit_i16(v: i16) { self.wr_tagged_i16(EsI16 as uint, v); } - fn emit_i8(v: i8) { self.wr_tagged_i8 (EsI8 as uint, v); } + fn emit_int(&self, v: int) { + self.wr_tagged_i64(EsInt as uint, v as i64); + } + fn emit_i64(&self, v: i64) { self.wr_tagged_i64(EsI64 as uint, v); } + fn emit_i32(&self, v: i32) { self.wr_tagged_i32(EsI32 as uint, v); } + fn emit_i16(&self, v: i16) { self.wr_tagged_i16(EsI16 as uint, v); } + fn emit_i8(&self, v: i8) { self.wr_tagged_i8 (EsI8 as uint, v); } - fn emit_bool(v: bool) { self.wr_tagged_u8(EsBool as uint, v as u8) } + fn emit_bool(&self, v: bool) { + self.wr_tagged_u8(EsBool as uint, v as u8) + } // FIXME (#2742): implement these - fn emit_f64(_v: f64) { fail ~"Unimplemented: serializing an f64"; } - fn emit_f32(_v: f32) { fail ~"Unimplemented: serializing an f32"; } - fn emit_float(_v: float) { fail ~"Unimplemented: serializing a float"; } + fn emit_f64(&self, _v: f64) { fail ~"Unimplemented: serializing an f64"; } + fn emit_f32(&self, _v: f32) { fail ~"Unimplemented: serializing an f32"; } + fn emit_float(&self, _v: float) { + fail ~"Unimplemented: serializing a float"; + } + + fn emit_char(&self, _v: char) { + fail ~"Unimplemented: serializing a char"; + } - fn emit_str(v: &str) { self.wr_tagged_str(EsStr as uint, v) } + fn emit_borrowed_str(&self, v: &str) { + self.wr_tagged_str(EsStr as uint, v) + } - fn emit_enum(name: &str, f: fn()) { + fn emit_owned_str(&self, v: &str) { + self.emit_borrowed_str(v) + } + + fn emit_managed_str(&self, v: &str) { + self.emit_borrowed_str(v) + } + + fn emit_borrowed(&self, f: fn()) { f() } + fn emit_owned(&self, f: fn()) { f() } + fn emit_managed(&self, f: fn()) { f() } + + fn emit_enum(&self, name: &str, f: fn()) { self._emit_label(name); self.wr_tag(EsEnum as uint, f) } - fn emit_enum_variant(_v_name: &str, v_id: uint, _cnt: uint, f: fn()) { + fn emit_enum_variant(&self, _v_name: &str, v_id: uint, _cnt: uint, + f: fn()) { self._emit_tagged_uint(EsEnumVid, v_id); self.wr_tag(EsEnumBody as uint, f) } - fn emit_enum_variant_arg(_idx: uint, f: fn()) { f() } + fn emit_enum_variant_arg(&self, _idx: uint, f: fn()) { f() } - fn emit_vec(len: uint, f: fn()) { + fn emit_borrowed_vec(&self, len: uint, f: fn()) { do self.wr_tag(EsVec as uint) { self._emit_tagged_uint(EsVecLen, len); f() } } - fn emit_vec_elt(_idx: uint, f: fn()) { + fn emit_owned_vec(&self, len: uint, f: fn()) { + self.emit_borrowed_vec(len, f) + } + + fn emit_managed_vec(&self, len: uint, f: fn()) { + self.emit_borrowed_vec(len, f) + } + + fn emit_vec_elt(&self, _idx: uint, f: fn()) { self.wr_tag(EsVecElt as uint, f) } - fn emit_box(f: fn()) { f() } - fn emit_uniq(f: fn()) { f() } - fn emit_rec(f: fn()) { f() } - fn emit_rec_field(f_name: &str, _f_idx: uint, f: fn()) { - self._emit_label(f_name); + fn emit_rec(&self, f: fn()) { f() } + fn emit_struct(&self, _name: &str, f: fn()) { f() } + fn emit_field(&self, name: &str, _idx: uint, f: fn()) { + self._emit_label(name); f() } - fn emit_tup(_sz: uint, f: fn()) { f() } - fn emit_tup_elt(_idx: uint, f: fn()) { f() } -} -type EbmlDeserializer_ = {mut parent: ebml::Doc, - mut pos: uint}; + fn emit_tup(&self, _len: uint, f: fn()) { f() } + fn emit_tup_elt(&self, _idx: uint, f: fn()) { f() } +} -pub enum EbmlDeserializer { - EbmlDeserializer_(EbmlDeserializer_) +struct Deserializer { + priv mut parent: Doc, + priv mut pos: uint, } -pub fn ebml_deserializer(d: ebml::Doc) -> EbmlDeserializer { - EbmlDeserializer_({mut parent: d, mut pos: d.start}) +pub fn Deserializer(d: Doc) -> Deserializer { + Deserializer { mut parent: d, mut pos: d.start } } -priv impl EbmlDeserializer { +priv impl Deserializer { fn _check_label(lbl: &str) { if self.pos < self.parent.end { - let {tag: r_tag, doc: r_doc} = - ebml::doc_at(self.parent.data, self.pos); + let TaggedDoc { tag: r_tag, doc: r_doc } = + doc_at(self.parent.data, self.pos); + if r_tag == (EsLabel as uint) { self.pos = r_doc.end; - let str = ebml::doc_as_str(r_doc); + let str = doc_as_str(r_doc); if lbl != str { fail fmt!("Expected label %s but found %s", lbl, str); } @@ -408,13 +450,13 @@ priv impl EbmlDeserializer { } } - fn next_doc(exp_tag: EbmlSerializerTag) -> ebml::Doc { + fn next_doc(exp_tag: EbmlSerializerTag) -> Doc { debug!(". next_doc(exp_tag=%?)", exp_tag); if self.pos >= self.parent.end { fail ~"no more documents in current node!"; } - let {tag: r_tag, doc: r_doc} = - ebml::doc_at(self.parent.data, self.pos); + let TaggedDoc { tag: r_tag, doc: r_doc } = + doc_at(self.parent.data, self.pos); debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?", copy self.parent.start, copy self.parent.end, copy self.pos, r_tag, r_doc.start, r_doc.end); @@ -427,10 +469,10 @@ priv impl EbmlDeserializer { r_doc.end, self.parent.end); } self.pos = r_doc.end; - return r_doc; + r_doc } - fn push_doc<T>(d: ebml::Doc, f: fn() -> T) -> T{ + fn push_doc<T>(d: Doc, f: fn() -> T) -> T{ let old_parent = self.parent; let old_pos = self.pos; self.parent = d; @@ -442,63 +484,76 @@ priv impl EbmlDeserializer { } fn _next_uint(exp_tag: EbmlSerializerTag) -> uint { - let r = ebml::doc_as_u32(self.next_doc(exp_tag)); + let r = doc_as_u32(self.next_doc(exp_tag)); debug!("_next_uint exp_tag=%? result=%?", exp_tag, r); - return r as uint; + r as uint } } -impl EbmlDeserializer { - fn read_opaque<R>(op: fn(ebml::Doc) -> R) -> R { +impl Deserializer { + fn read_opaque<R>(&self, op: fn(Doc) -> R) -> R { do self.push_doc(self.next_doc(EsOpaque)) { op(copy self.parent) } } } -impl EbmlDeserializer: serialization::Deserializer { - fn read_nil() -> () { () } +impl Deserializer: serialization::Deserializer { + fn read_nil(&self) -> () { () } - fn read_u64() -> u64 { ebml::doc_as_u64(self.next_doc(EsU64)) } - fn read_u32() -> u32 { ebml::doc_as_u32(self.next_doc(EsU32)) } - fn read_u16() -> u16 { ebml::doc_as_u16(self.next_doc(EsU16)) } - fn read_u8 () -> u8 { ebml::doc_as_u8 (self.next_doc(EsU8 )) } - fn read_uint() -> uint { - let v = ebml::doc_as_u64(self.next_doc(EsUint)); + fn read_u64(&self) -> u64 { doc_as_u64(self.next_doc(EsU64)) } + fn read_u32(&self) -> u32 { doc_as_u32(self.next_doc(EsU32)) } + fn read_u16(&self) -> u16 { doc_as_u16(self.next_doc(EsU16)) } + fn read_u8 (&self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) } + fn read_uint(&self) -> uint { + let v = doc_as_u64(self.next_doc(EsUint)); if v > (core::uint::max_value as u64) { fail fmt!("uint %? too large for this architecture", v); } - return v as uint; + v as uint } - fn read_i64() -> i64 { ebml::doc_as_u64(self.next_doc(EsI64)) as i64 } - fn read_i32() -> i32 { ebml::doc_as_u32(self.next_doc(EsI32)) as i32 } - fn read_i16() -> i16 { ebml::doc_as_u16(self.next_doc(EsI16)) as i16 } - fn read_i8 () -> i8 { ebml::doc_as_u8 (self.next_doc(EsI8 )) as i8 } - fn read_int() -> int { - let v = ebml::doc_as_u64(self.next_doc(EsInt)) as i64; + fn read_i64(&self) -> i64 { doc_as_u64(self.next_doc(EsI64)) as i64 } + fn read_i32(&self) -> i32 { doc_as_u32(self.next_doc(EsI32)) as i32 } + fn read_i16(&self) -> i16 { doc_as_u16(self.next_doc(EsI16)) as i16 } + fn read_i8 (&self) -> i8 { doc_as_u8 (self.next_doc(EsI8 )) as i8 } + fn read_int(&self) -> int { + let v = doc_as_u64(self.next_doc(EsInt)) as i64; if v > (int::max_value as i64) || v < (int::min_value as i64) { fail fmt!("int %? out of range for this architecture", v); } - return v as int; + v as int } - fn read_bool() -> bool { ebml::doc_as_u8(self.next_doc(EsBool)) as bool } + fn read_bool(&self) -> bool { doc_as_u8(self.next_doc(EsBool)) as bool } + + fn read_f64(&self) -> f64 { fail ~"read_f64()"; } + fn read_f32(&self) -> f32 { fail ~"read_f32()"; } + fn read_float(&self) -> float { fail ~"read_float()"; } - fn read_f64() -> f64 { fail ~"read_f64()"; } - fn read_f32() -> f32 { fail ~"read_f32()"; } - fn read_float() -> float { fail ~"read_float()"; } + fn read_char(&self) -> char { fail ~"read_char()"; } - fn read_str() -> ~str { ebml::doc_as_str(self.next_doc(EsStr)) } + fn read_owned_str(&self) -> ~str { doc_as_str(self.next_doc(EsStr)) } + fn read_managed_str(&self) -> @str { fail ~"read_managed_str()"; } // Compound types: - fn read_enum<T>(name: &str, f: fn() -> T) -> T { + fn read_owned<T>(&self, f: fn() -> T) -> T { + debug!("read_owned()"); + f() + } + + fn read_managed<T>(&self, f: fn() -> T) -> T { + debug!("read_managed()"); + f() + } + + fn read_enum<T>(&self, name: &str, f: fn() -> T) -> T { debug!("read_enum(%s)", name); self._check_label(name); self.push_doc(self.next_doc(EsEnum), f) } - fn read_enum_variant<T>(f: fn(uint) -> T) -> T { + fn read_enum_variant<T>(&self, f: fn(uint) -> T) -> T { debug!("read_enum_variant()"); let idx = self._next_uint(EsEnumVid); debug!(" idx=%u", idx); @@ -507,13 +562,13 @@ impl EbmlDeserializer: serialization::Deserializer { } } - fn read_enum_variant_arg<T>(idx: uint, f: fn() -> T) -> T { + fn read_enum_variant_arg<T>(&self, idx: uint, f: fn() -> T) -> T { debug!("read_enum_variant_arg(idx=%u)", idx); f() } - fn read_vec<T>(f: fn(uint) -> T) -> T { - debug!("read_vec()"); + fn read_owned_vec<T>(&self, f: fn(uint) -> T) -> T { + debug!("read_owned_vec()"); do self.push_doc(self.next_doc(EsVec)) { let len = self._next_uint(EsVecLen); debug!(" len=%u", len); @@ -521,104 +576,69 @@ impl EbmlDeserializer: serialization::Deserializer { } } - fn read_vec_elt<T>(idx: uint, f: fn() -> T) -> T { - debug!("read_vec_elt(idx=%u)", idx); - self.push_doc(self.next_doc(EsVecElt), f) + fn read_managed_vec<T>(&self, f: fn(uint) -> T) -> T { + debug!("read_managed_vec()"); + do self.push_doc(self.next_doc(EsVec)) { + let len = self._next_uint(EsVecLen); + debug!(" len=%u", len); + f(len) + } } - fn read_box<T>(f: fn() -> T) -> T { - debug!("read_box()"); - f() + fn read_vec_elt<T>(&self, idx: uint, f: fn() -> T) -> T { + debug!("read_vec_elt(idx=%u)", idx); + self.push_doc(self.next_doc(EsVecElt), f) } - fn read_uniq<T>(f: fn() -> T) -> T { - debug!("read_uniq()"); + fn read_rec<T>(&self, f: fn() -> T) -> T { + debug!("read_rec()"); f() } - fn read_rec<T>(f: fn() -> T) -> T { - debug!("read_rec()"); + fn read_struct<T>(&self, name: &str, f: fn() -> T) -> T { + debug!("read_struct(name=%s)", name); f() } - fn read_rec_field<T>(f_name: &str, f_idx: uint, f: fn() -> T) -> T { - debug!("read_rec_field(%s, idx=%u)", f_name, f_idx); - self._check_label(f_name); + fn read_field<T>(&self, name: &str, idx: uint, f: fn() -> T) -> T { + debug!("read_field(name=%s, idx=%u)", name, idx); + self._check_label(name); f() } - fn read_tup<T>(sz: uint, f: fn() -> T) -> T { - debug!("read_tup(sz=%u)", sz); + fn read_tup<T>(&self, len: uint, f: fn() -> T) -> T { + debug!("read_tup(len=%u)", len); f() } - fn read_tup_elt<T>(idx: uint, f: fn() -> T) -> T { + fn read_tup_elt<T>(&self, idx: uint, f: fn() -> T) -> T { debug!("read_tup_elt(idx=%u)", idx); f() } } - // ___________________________________________________________________________ // Testing -#[test] -fn test_option_int() { - fn serialize_1<S: serialization::Serializer>(s: &S, v: int) { - s.emit_i64(v as i64); - } - - fn serialize_0<S: serialization::Serializer>(s: &S, v: Option<int>) { - do s.emit_enum(~"core::option::t") { - match v { - None => s.emit_enum_variant( - ~"core::option::None", 0u, 0u, || { } ), - Some(v0) => { - do s.emit_enum_variant(~"core::option::some", 1u, 1u) { - s.emit_enum_variant_arg(0u, || serialize_1(s, v0)); - } - } - } +#[cfg(test)] +mod tests { + #[test] + fn test_option_int() { + fn test_v(v: Option<int>) { + debug!("v == %?", v); + let bytes = do io::with_bytes_writer |wr| { + let ebml_w = Serializer(wr); + v.serialize(&ebml_w) + }; + let ebml_doc = Doc(@bytes); + let deser = Deserializer(ebml_doc); + let v1 = serialization::deserialize(&deser); + debug!("v1 == %?", v1); + assert v == v1; } - } - fn deserialize_1<S: serialization::Deserializer>(s: &S) -> int { - s.read_i64() as int - } - - fn deserialize_0<S: serialization::Deserializer>(s: &S) -> Option<int> { - do s.read_enum(~"core::option::t") { - do s.read_enum_variant |i| { - match i { - 0 => None, - 1 => { - let v0 = do s.read_enum_variant_arg(0u) { - deserialize_1(s) - }; - Some(v0) - } - _ => { - fail #fmt("deserialize_0: unexpected variant %u", i); - } - } - } - } + test_v(Some(22)); + test_v(None); + test_v(Some(3)); } - - fn test_v(v: Option<int>) { - debug!("v == %?", v); - let bytes = do io::with_bytes_writer |wr| { - let ebml_w = ebml::Writer(wr); - serialize_0(&ebml_w, v); - }; - let ebml_doc = ebml::Doc(@bytes); - let deser = ebml_deserializer(ebml_doc); - let v1 = deserialize_0(&deser); - debug!("v1 == %?", v1); - assert v == v1; - } - - test_v(Some(22)); - test_v(None); - test_v(Some(3)); } diff --git a/src/libstd/ebml2.rs b/src/libstd/ebml2.rs deleted file mode 100644 index f88aad1ac63..00000000000 --- a/src/libstd/ebml2.rs +++ /dev/null @@ -1,644 +0,0 @@ -#[forbid(deprecated_mode)]; -use serialization2; - -// Simple Extensible Binary Markup Language (ebml) reader and writer on a -// cursor model. See the specification here: -// http://www.matroska.org/technical/specs/rfc/index.html - -struct EbmlTag { - id: uint, - size: uint, -} - -struct EbmlState { - ebml_tag: EbmlTag, - tag_pos: uint, - data_pos: uint, -} - -// FIXME (#2739): When we have module renaming, make "reader" and "writer" -// separate modules within this file. - -// ebml reading -struct Doc { - data: @~[u8], - start: uint, - end: uint, -} - -struct TaggedDoc { - tag: uint, - doc: Doc, -} - -impl Doc: ops::Index<uint,Doc> { - pure fn index(tag: uint) -> Doc { - unsafe { - get_doc(self, tag) - } - } -} - -fn vuint_at(data: &[u8], start: uint) -> {val: uint, next: uint} { - let a = data[start]; - if a & 0x80u8 != 0u8 { - return {val: (a & 0x7fu8) as uint, next: start + 1u}; - } - if a & 0x40u8 != 0u8 { - return {val: ((a & 0x3fu8) as uint) << 8u | - (data[start + 1u] as uint), - next: start + 2u}; - } else if a & 0x20u8 != 0u8 { - return {val: ((a & 0x1fu8) as uint) << 16u | - (data[start + 1u] as uint) << 8u | - (data[start + 2u] as uint), - next: start + 3u}; - } else if a & 0x10u8 != 0u8 { - return {val: ((a & 0x0fu8) as uint) << 24u | - (data[start + 1u] as uint) << 16u | - (data[start + 2u] as uint) << 8u | - (data[start + 3u] as uint), - next: start + 4u}; - } else { error!("vint too big"); fail; } -} - -pub fn Doc(data: @~[u8]) -> Doc { - Doc { data: data, start: 0u, end: vec::len::<u8>(*data) } -} - -pub fn doc_at(data: @~[u8], start: uint) -> TaggedDoc { - let elt_tag = vuint_at(*data, start); - let elt_size = vuint_at(*data, elt_tag.next); - let end = elt_size.next + elt_size.val; - TaggedDoc { - tag: elt_tag.val, - doc: Doc { data: data, start: elt_size.next, end: end } - } -} - -pub fn maybe_get_doc(d: Doc, tg: uint) -> Option<Doc> { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - return Some(Doc { data: d.data, start: elt_size.next, end: pos }); - } - } - None -} - -pub fn get_doc(d: Doc, tg: uint) -> Doc { - match maybe_get_doc(d, tg) { - Some(d) => d, - None => { - error!("failed to find block with tag %u", tg); - fail; - } - } -} - -pub fn docs(d: Doc, it: fn(uint, Doc) -> bool) { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - let doc = Doc { data: d.data, start: elt_size.next, end: pos }; - if !it(elt_tag.val, doc) { - break; - } - } -} - -pub fn tagged_docs(d: Doc, tg: uint, it: fn(Doc) -> bool) { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - let doc = Doc { data: d.data, start: elt_size.next, end: pos }; - if !it(doc) { - break; - } - } - } -} - -pub fn doc_data(d: Doc) -> ~[u8] { vec::slice::<u8>(*d.data, d.start, d.end) } - -pub fn with_doc_data<T>(d: Doc, f: fn(x: &[u8]) -> T) -> T { - f(vec::view(*d.data, d.start, d.end)) -} - -pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) } - -pub fn doc_as_u8(d: Doc) -> u8 { - assert d.end == d.start + 1u; - (*d.data)[d.start] -} - -pub fn doc_as_u16(d: Doc) -> u16 { - assert d.end == d.start + 2u; - io::u64_from_be_bytes(*d.data, d.start, 2u) as u16 -} - -pub fn doc_as_u32(d: Doc) -> u32 { - assert d.end == d.start + 4u; - io::u64_from_be_bytes(*d.data, d.start, 4u) as u32 -} - -pub fn doc_as_u64(d: Doc) -> u64 { - assert d.end == d.start + 8u; - io::u64_from_be_bytes(*d.data, d.start, 8u) -} - -pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } -pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 } -pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 } -pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 } - -// ebml writing -struct Serializer { - writer: io::Writer, - priv mut size_positions: ~[uint], -} - -fn write_sized_vuint(w: io::Writer, n: uint, size: uint) { - match size { - 1u => w.write(&[0x80u8 | (n as u8)]), - 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]), - 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8, - n as u8]), - 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8, - (n >> 8_u) as u8, n as u8]), - _ => fail fmt!("vint to write too big: %?", n) - }; -} - -fn write_vuint(w: io::Writer, n: uint) { - if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; } - if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; } - if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; } - if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; } - fail fmt!("vint to write too big: %?", n); -} - -pub fn Serializer(w: io::Writer) -> Serializer { - let size_positions: ~[uint] = ~[]; - Serializer { writer: w, mut size_positions: size_positions } -} - -// FIXME (#2741): Provide a function to write the standard ebml header. -impl Serializer { - fn start_tag(tag_id: uint) { - debug!("Start tag %u", tag_id); - - // Write the enum ID: - write_vuint(self.writer, tag_id); - - // Write a placeholder four-byte size. - self.size_positions.push(self.writer.tell()); - let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8]; - self.writer.write(zeroes); - } - - fn end_tag() { - let last_size_pos = self.size_positions.pop(); - let cur_pos = self.writer.tell(); - self.writer.seek(last_size_pos as int, io::SeekSet); - let size = (cur_pos - last_size_pos - 4u); - write_sized_vuint(self.writer, size, 4u); - self.writer.seek(cur_pos as int, io::SeekSet); - - debug!("End tag (size = %u)", size); - } - - fn wr_tag(tag_id: uint, blk: fn()) { - self.start_tag(tag_id); - blk(); - self.end_tag(); - } - - fn wr_tagged_bytes(tag_id: uint, b: &[u8]) { - write_vuint(self.writer, tag_id); - write_vuint(self.writer, vec::len(b)); - self.writer.write(b); - } - - fn wr_tagged_u64(tag_id: uint, v: u64) { - do io::u64_to_be_bytes(v, 8u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_u32(tag_id: uint, v: u32) { - do io::u64_to_be_bytes(v as u64, 4u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_u16(tag_id: uint, v: u16) { - do io::u64_to_be_bytes(v as u64, 2u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_u8(tag_id: uint, v: u8) { - self.wr_tagged_bytes(tag_id, &[v]); - } - - fn wr_tagged_i64(tag_id: uint, v: i64) { - do io::u64_to_be_bytes(v as u64, 8u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_i32(tag_id: uint, v: i32) { - do io::u64_to_be_bytes(v as u64, 4u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_i16(tag_id: uint, v: i16) { - do io::u64_to_be_bytes(v as u64, 2u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_i8(tag_id: uint, v: i8) { - self.wr_tagged_bytes(tag_id, &[v as u8]); - } - - fn wr_tagged_str(tag_id: uint, v: &str) { - str::byte_slice(v, |b| self.wr_tagged_bytes(tag_id, b)); - } - - fn wr_bytes(b: &[u8]) { - debug!("Write %u bytes", vec::len(b)); - self.writer.write(b); - } - - fn wr_str(s: &str) { - debug!("Write str: %?", s); - self.writer.write(str::to_bytes(s)); - } -} - -// FIXME (#2743): optionally perform "relaxations" on end_tag to more -// efficiently encode sizes; this is a fixed point iteration - -// Set to true to generate more debugging in EBML serialization. -// Totally lame approach. -const debug: bool = false; - -enum EbmlSerializerTag { - EsUint, EsU64, EsU32, EsU16, EsU8, - EsInt, EsI64, EsI32, EsI16, EsI8, - EsBool, - EsStr, - EsF64, EsF32, EsFloat, - EsEnum, EsEnumVid, EsEnumBody, - EsVec, EsVecLen, EsVecElt, - - EsOpaque, - - EsLabel // Used only when debugging -} - -priv impl Serializer { - // used internally to emit things like the vector length and so on - fn _emit_tagged_uint(t: EbmlSerializerTag, v: uint) { - assert v <= 0xFFFF_FFFF_u; - self.wr_tagged_u32(t as uint, v as u32); - } - - fn _emit_label(label: &str) { - // There are various strings that we have access to, such as - // the name of a record field, which do not actually appear in - // the serialized EBML (normally). This is just for - // efficiency. When debugging, though, we can emit such - // labels and then they will be checked by deserializer to - // try and check failures more quickly. - if debug { self.wr_tagged_str(EsLabel as uint, label) } - } -} - -impl Serializer { - fn emit_opaque(&self, f: fn()) { - do self.wr_tag(EsOpaque as uint) { - f() - } - } -} - -impl Serializer: serialization2::Serializer { - fn emit_nil(&self) {} - - fn emit_uint(&self, v: uint) { - self.wr_tagged_u64(EsUint as uint, v as u64); - } - fn emit_u64(&self, v: u64) { self.wr_tagged_u64(EsU64 as uint, v); } - fn emit_u32(&self, v: u32) { self.wr_tagged_u32(EsU32 as uint, v); } - fn emit_u16(&self, v: u16) { self.wr_tagged_u16(EsU16 as uint, v); } - fn emit_u8(&self, v: u8) { self.wr_tagged_u8 (EsU8 as uint, v); } - - fn emit_int(&self, v: int) { - self.wr_tagged_i64(EsInt as uint, v as i64); - } - fn emit_i64(&self, v: i64) { self.wr_tagged_i64(EsI64 as uint, v); } - fn emit_i32(&self, v: i32) { self.wr_tagged_i32(EsI32 as uint, v); } - fn emit_i16(&self, v: i16) { self.wr_tagged_i16(EsI16 as uint, v); } - fn emit_i8(&self, v: i8) { self.wr_tagged_i8 (EsI8 as uint, v); } - - fn emit_bool(&self, v: bool) { - self.wr_tagged_u8(EsBool as uint, v as u8) - } - - // FIXME (#2742): implement these - fn emit_f64(&self, _v: f64) { fail ~"Unimplemented: serializing an f64"; } - fn emit_f32(&self, _v: f32) { fail ~"Unimplemented: serializing an f32"; } - fn emit_float(&self, _v: float) { - fail ~"Unimplemented: serializing a float"; - } - - fn emit_char(&self, _v: char) { - fail ~"Unimplemented: serializing a char"; - } - - fn emit_borrowed_str(&self, v: &str) { - self.wr_tagged_str(EsStr as uint, v) - } - - fn emit_owned_str(&self, v: &str) { - self.emit_borrowed_str(v) - } - - fn emit_managed_str(&self, v: &str) { - self.emit_borrowed_str(v) - } - - fn emit_borrowed(&self, f: fn()) { f() } - fn emit_owned(&self, f: fn()) { f() } - fn emit_managed(&self, f: fn()) { f() } - - fn emit_enum(&self, name: &str, f: fn()) { - self._emit_label(name); - self.wr_tag(EsEnum as uint, f) - } - fn emit_enum_variant(&self, _v_name: &str, v_id: uint, _cnt: uint, - f: fn()) { - self._emit_tagged_uint(EsEnumVid, v_id); - self.wr_tag(EsEnumBody as uint, f) - } - fn emit_enum_variant_arg(&self, _idx: uint, f: fn()) { f() } - - fn emit_borrowed_vec(&self, len: uint, f: fn()) { - do self.wr_tag(EsVec as uint) { - self._emit_tagged_uint(EsVecLen, len); - f() - } - } - - fn emit_owned_vec(&self, len: uint, f: fn()) { - self.emit_borrowed_vec(len, f) - } - - fn emit_managed_vec(&self, len: uint, f: fn()) { - self.emit_borrowed_vec(len, f) - } - - fn emit_vec_elt(&self, _idx: uint, f: fn()) { - self.wr_tag(EsVecElt as uint, f) - } - - fn emit_rec(&self, f: fn()) { f() } - fn emit_struct(&self, _name: &str, f: fn()) { f() } - fn emit_field(&self, name: &str, _idx: uint, f: fn()) { - self._emit_label(name); - f() - } - - fn emit_tup(&self, _len: uint, f: fn()) { f() } - fn emit_tup_elt(&self, _idx: uint, f: fn()) { f() } -} - -struct Deserializer { - priv mut parent: Doc, - priv mut pos: uint, -} - -pub fn Deserializer(d: Doc) -> Deserializer { - Deserializer { mut parent: d, mut pos: d.start } -} - -priv impl Deserializer { - fn _check_label(lbl: &str) { - if self.pos < self.parent.end { - let TaggedDoc { tag: r_tag, doc: r_doc } = - doc_at(self.parent.data, self.pos); - - if r_tag == (EsLabel as uint) { - self.pos = r_doc.end; - let str = doc_as_str(r_doc); - if lbl != str { - fail fmt!("Expected label %s but found %s", lbl, str); - } - } - } - } - - fn next_doc(exp_tag: EbmlSerializerTag) -> Doc { - debug!(". next_doc(exp_tag=%?)", exp_tag); - if self.pos >= self.parent.end { - fail ~"no more documents in current node!"; - } - let TaggedDoc { tag: r_tag, doc: r_doc } = - doc_at(self.parent.data, self.pos); - debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?", - copy self.parent.start, copy self.parent.end, - copy self.pos, r_tag, r_doc.start, r_doc.end); - if r_tag != (exp_tag as uint) { - fail fmt!("expected EMBL doc with tag %? but found tag %?", - exp_tag, r_tag); - } - if r_doc.end > self.parent.end { - fail fmt!("invalid EBML, child extends to 0x%x, parent to 0x%x", - r_doc.end, self.parent.end); - } - self.pos = r_doc.end; - r_doc - } - - fn push_doc<T>(d: Doc, f: fn() -> T) -> T{ - let old_parent = self.parent; - let old_pos = self.pos; - self.parent = d; - self.pos = d.start; - let r = f(); - self.parent = old_parent; - self.pos = old_pos; - move r - } - - fn _next_uint(exp_tag: EbmlSerializerTag) -> uint { - let r = doc_as_u32(self.next_doc(exp_tag)); - debug!("_next_uint exp_tag=%? result=%?", exp_tag, r); - r as uint - } -} - -impl Deserializer { - fn read_opaque<R>(&self, op: fn(Doc) -> R) -> R { - do self.push_doc(self.next_doc(EsOpaque)) { - op(copy self.parent) - } - } -} - -impl Deserializer: serialization2::Deserializer { - fn read_nil(&self) -> () { () } - - fn read_u64(&self) -> u64 { doc_as_u64(self.next_doc(EsU64)) } - fn read_u32(&self) -> u32 { doc_as_u32(self.next_doc(EsU32)) } - fn read_u16(&self) -> u16 { doc_as_u16(self.next_doc(EsU16)) } - fn read_u8 (&self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) } - fn read_uint(&self) -> uint { - let v = doc_as_u64(self.next_doc(EsUint)); - if v > (core::uint::max_value as u64) { - fail fmt!("uint %? too large for this architecture", v); - } - v as uint - } - - fn read_i64(&self) -> i64 { doc_as_u64(self.next_doc(EsI64)) as i64 } - fn read_i32(&self) -> i32 { doc_as_u32(self.next_doc(EsI32)) as i32 } - fn read_i16(&self) -> i16 { doc_as_u16(self.next_doc(EsI16)) as i16 } - fn read_i8 (&self) -> i8 { doc_as_u8 (self.next_doc(EsI8 )) as i8 } - fn read_int(&self) -> int { - let v = doc_as_u64(self.next_doc(EsInt)) as i64; - if v > (int::max_value as i64) || v < (int::min_value as i64) { - fail fmt!("int %? out of range for this architecture", v); - } - v as int - } - - fn read_bool(&self) -> bool { doc_as_u8(self.next_doc(EsBool)) as bool } - - fn read_f64(&self) -> f64 { fail ~"read_f64()"; } - fn read_f32(&self) -> f32 { fail ~"read_f32()"; } - fn read_float(&self) -> float { fail ~"read_float()"; } - - fn read_char(&self) -> char { fail ~"read_char()"; } - - fn read_owned_str(&self) -> ~str { doc_as_str(self.next_doc(EsStr)) } - fn read_managed_str(&self) -> @str { fail ~"read_managed_str()"; } - - // Compound types: - fn read_owned<T>(&self, f: fn() -> T) -> T { - debug!("read_owned()"); - f() - } - - fn read_managed<T>(&self, f: fn() -> T) -> T { - debug!("read_managed()"); - f() - } - - fn read_enum<T>(&self, name: &str, f: fn() -> T) -> T { - debug!("read_enum(%s)", name); - self._check_label(name); - self.push_doc(self.next_doc(EsEnum), f) - } - - fn read_enum_variant<T>(&self, f: fn(uint) -> T) -> T { - debug!("read_enum_variant()"); - let idx = self._next_uint(EsEnumVid); - debug!(" idx=%u", idx); - do self.push_doc(self.next_doc(EsEnumBody)) { - f(idx) - } - } - - fn read_enum_variant_arg<T>(&self, idx: uint, f: fn() -> T) -> T { - debug!("read_enum_variant_arg(idx=%u)", idx); - f() - } - - fn read_owned_vec<T>(&self, f: fn(uint) -> T) -> T { - debug!("read_owned_vec()"); - do self.push_doc(self.next_doc(EsVec)) { - let len = self._next_uint(EsVecLen); - debug!(" len=%u", len); - f(len) - } - } - - fn read_managed_vec<T>(&self, f: fn(uint) -> T) -> T { - debug!("read_managed_vec()"); - do self.push_doc(self.next_doc(EsVec)) { - let len = self._next_uint(EsVecLen); - debug!(" len=%u", len); - f(len) - } - } - - fn read_vec_elt<T>(&self, idx: uint, f: fn() -> T) -> T { - debug!("read_vec_elt(idx=%u)", idx); - self.push_doc(self.next_doc(EsVecElt), f) - } - - fn read_rec<T>(&self, f: fn() -> T) -> T { - debug!("read_rec()"); - f() - } - - fn read_struct<T>(&self, name: &str, f: fn() -> T) -> T { - debug!("read_struct(name=%s)", name); - f() - } - - fn read_field<T>(&self, name: &str, idx: uint, f: fn() -> T) -> T { - debug!("read_field(name=%s, idx=%u)", name, idx); - self._check_label(name); - f() - } - - fn read_tup<T>(&self, len: uint, f: fn() -> T) -> T { - debug!("read_tup(len=%u)", len); - f() - } - - fn read_tup_elt<T>(&self, idx: uint, f: fn() -> T) -> T { - debug!("read_tup_elt(idx=%u)", idx); - f() - } -} - -// ___________________________________________________________________________ -// Testing - -#[cfg(test)] -mod tests { - #[test] - fn test_option_int() { - fn test_v(v: Option<int>) { - debug!("v == %?", v); - let bytes = do io::with_bytes_writer |wr| { - let ebml_w = Serializer(wr); - v.serialize(&ebml_w) - }; - let ebml_doc = Doc(@bytes); - let deser = Deserializer(ebml_doc); - let v1 = serialization2::deserialize(&deser); - debug!("v1 == %?", v1); - assert v == v1; - } - - test_v(Some(22)); - test_v(None); - test_v(Some(3)); - } -} diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index 6da51571e34..8d77b88aba2 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -82,7 +82,7 @@ pub type Opt = {name: Name, hasarg: HasArg, occur: Occur}; fn mkname(nm: &str) -> Name { let unm = str::from_slice(nm); - return if str::len(nm) == 1u { + return if nm.len() == 1u { Short(str::char_at(unm, 0u)) } else { Long(unm) }; } @@ -114,6 +114,22 @@ impl Occur : Eq { pure fn ne(other: &Occur) -> bool { !self.eq(other) } } +impl HasArg : Eq { + pure fn eq(other: &HasArg) -> bool { + (self as uint) == ((*other) as uint) + } + pure fn ne(other: &HasArg) -> bool { !self.eq(other) } +} + +impl Opt : Eq { + pure fn eq(other: &Opt) -> bool { + self.name == (*other).name && + self.hasarg == (*other).hasarg && + self.occur == (*other).occur + } + pure fn ne(other: &Opt) -> bool { !self.eq(other) } +} + /// Create an option that is required and takes an argument pub fn reqopt(name: &str) -> Opt { return {name: mkname(name), hasarg: Yes, occur: Req}; @@ -150,8 +166,29 @@ enum Optval { Val(~str), Given, } */ pub type Matches = {opts: ~[Opt], vals: ~[~[Optval]], free: ~[~str]}; +impl Optval : Eq { + pure fn eq(other: &Optval) -> bool { + match self { + Val(ref s) => match *other { Val (ref os) => s == os, + Given => false }, + Given => match *other { Val(_) => false, + Given => true } + } + } + pure fn ne(other: &Optval) -> bool { !self.eq(other) } +} + +impl Matches : Eq { + pure fn eq(other: &Matches) -> bool { + self.opts == (*other).opts && + self.vals == (*other).vals && + self.free == (*other).free + } + pure fn ne(other: &Matches) -> bool { !self.eq(other) } +} + fn is_arg(arg: &str) -> bool { - return str::len(arg) > 1u && arg[0] == '-' as u8; + return arg.len() > 1u && arg[0] == '-' as u8; } fn name_str(nm: &Name) -> ~str { @@ -177,6 +214,35 @@ pub enum Fail_ { UnexpectedArgument(~str), } +impl Fail_ : Eq { + // this whole thing should be easy to infer... + pure fn eq(other: &Fail_) -> bool { + match self { + ArgumentMissing(ref s) => { + match *other { ArgumentMissing(ref so) => s == so, + _ => false } + } + UnrecognizedOption(ref s) => { + match *other { UnrecognizedOption(ref so) => s == so, + _ => false } + } + OptionMissing(ref s) => { + match *other { OptionMissing(ref so) => s == so, + _ => false } + } + OptionDuplicated(ref s) => { + match *other { OptionDuplicated(ref so) => s == so, + _ => false } + } + UnexpectedArgument(ref s) => { + match *other { UnexpectedArgument(ref so) => s == so, + _ => false } + } + } + } + pure fn ne(other: &Fail_) -> bool { !self.eq(other) } +} + /// Convert a `fail_` enum into an error string pub fn fail_str(f: Fail_) -> ~str { return match f { @@ -220,7 +286,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe { let mut i = 0u; while i < l { let cur = args[i]; - let curlen = str::len(cur); + let curlen = cur.len(); if !is_arg(cur) { free.push(cur); } else if cur == ~"--" { @@ -444,6 +510,194 @@ impl FailType : Eq { pure fn ne(other: &FailType) -> bool { !self.eq(other) } } +/** A module which provides a way to specify descriptions and + * groups of short and long option names, together. + */ +pub mod groups { + + /** one group of options, e.g., both -h and --help, along with + * their shared description and properties + */ + pub type OptGroup = { + short_name: ~str, + long_name: ~str, + hint: ~str, + desc: ~str, + hasarg: HasArg, + occur: Occur + }; + + impl OptGroup : Eq { + pure fn eq(other: &OptGroup) -> bool { + self.short_name == (*other).short_name && + self.long_name == (*other).long_name && + self.hint == (*other).hint && + self.desc == (*other).desc && + self.hasarg == (*other).hasarg && + self.occur == (*other).occur + } + pure fn ne(other: &OptGroup) -> bool { !self.eq(other) } + } + + /// Create a long option that is required and takes an argument + pub fn reqopt(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Yes, + occur: Req}; + } + + /// Create a long option that is optional and takes an argument + pub fn optopt(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Yes, + occur: Optional}; + } + + /// Create a long option that is optional and does not take an argument + pub fn optflag(short_name: &str, long_name: &str, + desc: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: ~"", + desc: str::from_slice(desc), + hasarg: No, + occur: Optional}; + } + + /// Create a long option that is optional and takes an optional argument + pub fn optflagopt(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Maybe, + occur: Optional}; + } + + /** + * Create a long option that is optional, takes an argument, and may occur + * multiple times + */ + pub fn optmulti(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Yes, + occur: Multi}; + } + + // translate OptGroup into Opt + // (both short and long names correspond to different Opts) + pub fn long_to_short(lopt: &OptGroup) -> ~[Opt] { + match ((*lopt).short_name.len(), + (*lopt).long_name.len()) { + + (0,0) => fail ~"this long-format option was given no name", + + (0,_) => ~[{name: Long(((*lopt).long_name)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}], + + (1,0) => ~[{name: Short(str::char_at((*lopt).short_name, 0)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}], + + (1,_) => ~[{name: Short(str::char_at((*lopt).short_name, 0)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}, + {name: Long(((*lopt).long_name)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}], + + (_,_) => fail ~"something is wrong with the long-form opt" + } + } + + /* + * Parse command line args with the provided long format options + */ + pub fn getopts(args: &[~str], opts: &[OptGroup]) -> Result { + ::getopts::getopts(args, vec::flat_map(opts, long_to_short)) + } + + /** + * Derive a usage message from a set of long options + */ + pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { + + let desc_sep = ~"\n" + str::repeat(~" ", 24); + + let rows = vec::map(opts, |optref| { + let short_name = (*optref).short_name; + let long_name = (*optref).long_name; + let hint = (*optref).hint; + let desc = (*optref).desc; + let hasarg = (*optref).hasarg; + + let mut row = str::repeat(~" ", 4); + + // short option + row += match short_name.len() { + 0 => ~"", + 1 => ~"-" + short_name + " ", + _ => fail ~"the short name should only be 1 char long", + }; + + // long option + row += match long_name.len() { + 0 => ~"", + _ => ~"--" + long_name + " ", + }; + + // arg + row += match hasarg { + No => ~"", + Yes => hint, + Maybe => ~"[" + hint + ~"]", + }; + + // here we just need to indent the start of the description + let rowlen = row.len(); + row += if rowlen < 24 { + str::repeat(~" ", 24 - rowlen) + } else { + desc_sep + }; + + // wrapped description + row += str::connect(str::split_within(desc, 54), desc_sep); + + row + }); + + return str::from_slice(brief) + + ~"\n\nOptions:\n" + + str::connect(rows, ~"\n") + + ~"\n\n"; + } +} // end groups module + #[cfg(test)] mod tests { #[legacy_exports]; @@ -943,6 +1197,158 @@ mod tests { assert opts_present(matches, ~[~"L"]); assert opts_str(matches, ~[~"L"]) == ~"foo"; } + + #[test] + fn test_groups_reqopt() { + let opt = groups::reqopt(~"b", ~"banana", ~"some bananas", ~"VAL"); + assert opt == { short_name: ~"b", + long_name: ~"banana", + hint: ~"VAL", + desc: ~"some bananas", + hasarg: Yes, + occur: Req } + } + + #[test] + fn test_groups_optopt() { + let opt = groups::optopt(~"a", ~"apple", ~"some apples", ~"VAL"); + assert opt == { short_name: ~"a", + long_name: ~"apple", + hint: ~"VAL", + desc: ~"some apples", + hasarg: Yes, + occur: Optional } + } + + #[test] + fn test_groups_optflag() { + let opt = groups::optflag(~"k", ~"kiwi", ~"some kiwis"); + assert opt == { short_name: ~"k", + long_name: ~"kiwi", + hint: ~"", + desc: ~"some kiwis", + hasarg: No, + occur: Optional } + } + + #[test] + fn test_groups_optflagopt() { + let opt = groups::optflagopt(~"p", ~"pineapple", + ~"some pineapples", ~"VAL"); + assert opt == { short_name: ~"p", + long_name: ~"pineapple", + hint: ~"VAL", + desc: ~"some pineapples", + hasarg: Maybe, + occur: Optional } + } + + #[test] + fn test_groups_optmulti() { + let opt = groups::optmulti(~"l", ~"lime", + ~"some limes", ~"VAL"); + assert opt == { short_name: ~"l", + long_name: ~"lime", + hint: ~"VAL", + desc: ~"some limes", + hasarg: Yes, + occur: Multi } + } + + #[test] + fn test_groups_long_to_short() { + let short = ~[reqopt(~"b"), reqopt(~"banana")]; + let verbose = groups::reqopt(~"b", ~"banana", + ~"some bananas", ~"VAL"); + + assert groups::long_to_short(&verbose) == short; + } + + #[test] + fn test_groups_getopts() { + let short = ~[ + reqopt(~"b"), reqopt(~"banana"), + optopt(~"a"), optopt(~"apple"), + optflag(~"k"), optflagopt(~"kiwi"), + optflagopt(~"p"), + optmulti(~"l") + ]; + + let verbose = ~[ + groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), + groups::optopt(~"a", ~"apple", ~"Desc", ~"VAL"), + groups::optflag(~"k", ~"kiwi", ~"Desc"), + groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"), + groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"), + ]; + + let sample_args = ~[~"-k", ~"15", ~"--apple", ~"1", ~"k", + ~"-p", ~"16", ~"l", ~"35"]; + + // NOTE: we should sort before comparing + assert getopts(sample_args, short) + == groups::getopts(sample_args, verbose); + } + + #[test] + fn test_groups_usage() { + let optgroups = ~[ + groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), + groups::optopt(~"a", ~"012345678901234567890123456789", + ~"Desc", ~"VAL"), + groups::optflag(~"k", ~"kiwi", ~"Desc"), + groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"), + groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"), + ]; + + let expected = +~"Usage: fruits + +Options: + -b --banana VAL Desc + -a --012345678901234567890123456789 VAL + Desc + -k --kiwi Desc + -p [VAL] Desc + -l VAL Desc + +"; + + let generated_usage = groups::usage(~"Usage: fruits", optgroups); + + debug!("expected: <<%s>>", expected); + debug!("generated: <<%s>>", generated_usage); + assert generated_usage == expected; + } + + #[test] + fn test_groups_usage_description_wrapping() { + // indentation should be 24 spaces + // lines wrap after 78: or rather descriptions wrap after 54 + + let optgroups = ~[ + groups::optflag(~"k", ~"kiwi", + ~"This is a long description which won't be wrapped..+.."), // 54 + groups::optflag(~"a", ~"apple", + ~"This is a long description which _will_ be wrapped..+.."), // 55 + ]; + + let expected = +~"Usage: fruits + +Options: + -k --kiwi This is a long description which won't be wrapped..+.. + -a --apple This is a long description which _will_ be + wrapped..+.. + +"; + + let usage = groups::usage(~"Usage: fruits", optgroups); + + debug!("expected: <<%s>>", expected); + debug!("generated: <<%s>>", usage); + assert usage == expected + } } // Local Variables: diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 09d00216209..5f64389e583 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -51,7 +51,7 @@ fn escape_str(s: &str) -> ~str { fn spaces(n: uint) -> ~str { let mut ss = ~""; - for n.times { str::push_str(&ss, " "); } + for n.times { str::push_str(&mut ss, " "); } return ss; } @@ -63,7 +63,7 @@ pub fn Serializer(wr: io::Writer) -> Serializer { Serializer { wr: wr } } -pub impl Serializer: serialization2::Serializer { +pub impl Serializer: serialization::Serializer { fn emit_nil(&self) { self.wr.write_str("null") } fn emit_uint(&self, v: uint) { self.emit_float(v as float); } @@ -167,7 +167,7 @@ pub fn PrettySerializer(wr: io::Writer) -> PrettySerializer { PrettySerializer { wr: wr, indent: 0 } } -pub impl PrettySerializer: serialization2::Serializer { +pub impl PrettySerializer: serialization::Serializer { fn emit_nil(&self) { self.wr.write_str("null") } fn emit_uint(&self, v: uint) { self.emit_float(v as float); } @@ -273,8 +273,36 @@ pub impl PrettySerializer: serialization2::Serializer { } } -pub impl Json: serialization2::Serializable { - fn serialize<S: serialization2::Serializer>(&self, s: &S) { +#[cfg(stage0)] +pub impl Json: serialization::Serializable { + fn serialize<S: serialization::Serializer>(&self, s: &S) { + match *self { + Number(v) => v.serialize(s), + String(ref v) => v.serialize(s), + Boolean(v) => v.serialize(s), + List(v) => v.serialize(s), + Object(ref v) => { + do s.emit_rec || { + let mut idx = 0; + for v.each |key, value| { + do s.emit_field(*key, idx) { + value.serialize(s); + } + idx += 1; + } + } + }, + Null => s.emit_nil(), + } + } +} + +#[cfg(stage1)] +#[cfg(stage2)] +pub impl< + S: serialization::Serializer +> Json: serialization::Serializable<S> { + fn serialize(&self, s: &S) { match *self { Number(v) => v.serialize(s), String(ref v) => v.serialize(s), @@ -302,7 +330,8 @@ pub fn to_writer(wr: io::Writer, json: &Json) { } /// Serializes a json value into a string -pub fn to_str(json: &Json) -> ~str { +pub pure fn to_str(json: &Json) -> ~str unsafe { + // ugh, should be safe io::with_str_writer(|wr| to_writer(wr, json)) } @@ -328,8 +357,8 @@ pub fn Parser(rdr: io::Reader) -> Parser { Parser { rdr: rdr, ch: rdr.read_char(), - line: 1u, - col: 1u, + line: 1, + col: 1, } } @@ -341,7 +370,7 @@ pub impl Parser { self.parse_whitespace(); // Make sure there is no trailing characters. if self.eof() { - Ok(value) + Ok(move value) } else { self.error(~"trailing characters") } @@ -546,14 +575,14 @@ priv impl Parser { if (escape) { match self.ch { - '"' => str::push_char(&res, '"'), - '\\' => str::push_char(&res, '\\'), - '/' => str::push_char(&res, '/'), - 'b' => str::push_char(&res, '\x08'), - 'f' => str::push_char(&res, '\x0c'), - 'n' => str::push_char(&res, '\n'), - 'r' => str::push_char(&res, '\r'), - 't' => str::push_char(&res, '\t'), + '"' => str::push_char(&mut res, '"'), + '\\' => str::push_char(&mut res, '\\'), + '/' => str::push_char(&mut res, '/'), + 'b' => str::push_char(&mut res, '\x08'), + 'f' => str::push_char(&mut res, '\x0c'), + 'n' => str::push_char(&mut res, '\n'), + 'r' => str::push_char(&mut res, '\r'), + 't' => str::push_char(&mut res, '\t'), 'u' => { // Parse \u1234. let mut i = 0u; @@ -582,7 +611,7 @@ priv impl Parser { ~"invalid \\u escape (not four digits)"); } - str::push_char(&res, n as char); + str::push_char(&mut res, n as char); } _ => return self.error(~"invalid escape") } @@ -594,7 +623,7 @@ priv impl Parser { self.bump(); return Ok(res); } - str::push_char(&res, self.ch); + str::push_char(&mut res, self.ch); } } @@ -609,12 +638,12 @@ priv impl Parser { if self.ch == ']' { self.bump(); - return Ok(List(values)); + return Ok(List(move values)); } loop { match move self.parse_value() { - Ok(move v) => values.push(v), + Ok(move v) => values.push(move v), Err(move e) => return Err(e) } @@ -625,7 +654,7 @@ priv impl Parser { match self.ch { ',' => self.bump(), - ']' => { self.bump(); return Ok(List(values)); } + ']' => { self.bump(); return Ok(List(move values)); } _ => return self.error(~"expected `,` or `]`") } }; @@ -639,7 +668,7 @@ priv impl Parser { if self.ch == '}' { self.bump(); - return Ok(Object(values)); + return Ok(Object(move values)); } while !self.eof() { @@ -663,14 +692,14 @@ priv impl Parser { self.bump(); match move self.parse_value() { - Ok(move value) => { values.insert(key, value); } + Ok(move value) => { values.insert(key, move value); } Err(move e) => return Err(e) } self.parse_whitespace(); match self.ch { ',' => self.bump(), - '}' => { self.bump(); return Ok(Object(values)); } + '}' => { self.bump(); return Ok(Object(move values)); } _ => { if self.eof() { break; } return self.error(~"expected `,` or `}`"); @@ -702,7 +731,7 @@ pub struct Deserializer { pub fn Deserializer(rdr: io::Reader) -> Result<Deserializer, Error> { match move from_reader(rdr) { Ok(move json) => { - let des = Deserializer { json: json, stack: ~[] }; + let des = Deserializer { json: move json, stack: ~[] }; Ok(move des) } Err(move e) => Err(e) @@ -721,7 +750,7 @@ priv impl Deserializer { } } -pub impl Deserializer: serialization2::Deserializer { +pub impl Deserializer: serialization::Deserializer { fn read_nil(&self) -> () { debug!("read_nil"); match *self.pop() { @@ -818,7 +847,7 @@ pub impl Deserializer: serialization2::Deserializer { }; let res = f(len); self.pop(); - res + move res } fn read_managed_vec<T>(&self, f: fn(uint) -> T) -> T { @@ -829,7 +858,7 @@ pub impl Deserializer: serialization2::Deserializer { }; let res = f(len); self.pop(); - res + move res } fn read_vec_elt<T>(&self, idx: uint, f: fn() -> T) -> T { @@ -850,14 +879,14 @@ pub impl Deserializer: serialization2::Deserializer { debug!("read_rec()"); let value = f(); self.pop(); - value + move value } fn read_struct<T>(&self, _name: &str, f: fn() -> T) -> T { debug!("read_struct()"); let value = f(); self.pop(); - value + move value } fn read_field<T>(&self, name: &str, idx: uint, f: fn() -> T) -> T { @@ -868,7 +897,7 @@ pub impl Deserializer: serialization2::Deserializer { // FIXME(#3148) This hint should not be necessary. let obj: &self/~Object = obj; - match obj.find_ref(&name.to_unique()) { + match obj.find_ref(&name.to_owned()) { None => fail fmt!("no such field: %s", name), Some(json) => { self.stack.push(json); @@ -890,7 +919,7 @@ pub impl Deserializer: serialization2::Deserializer { debug!("read_tup(len=%u)", len); let value = f(); self.pop(); - value + move value } fn read_tup_elt<T>(&self, idx: uint, f: fn() -> T) -> T { @@ -1166,11 +1195,11 @@ impl <A: ToJson> Option<A>: ToJson { } impl Json: to_str::ToStr { - fn to_str() -> ~str { to_str(&self) } + pure fn to_str() -> ~str { to_str(&self) } } impl Error: to_str::ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { fmt!("%u:%u: %s", self.line, self.col, *self.msg) } } @@ -1182,11 +1211,11 @@ mod tests { for items.each |item| { match *item { - (copy key, copy value) => { d.insert(key, value); }, + (copy key, copy value) => { d.insert(key, move value); }, } }; - Object(d) + Object(move d) } #[test] diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 765d40339d3..e49f1abd02b 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -341,7 +341,8 @@ pub mod chained { wr.write_str(~" }"); } - fn to_str() -> ~str { + pure fn to_str() -> ~str unsafe { + // Meh -- this should be safe do io::with_str_writer |wr| { self.to_writer(wr) } } } @@ -722,7 +723,7 @@ mod tests { let map = map::HashMap::<~str, ~str>(); assert (option::is_none(&map.find(key))); map.insert(key, ~"val"); - assert (option::get(&map.find(key)) == ~"val"); + assert (option::get(map.find(key)) == ~"val"); } #[test] diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 2d9dd5bdf4e..5d78fb19bab 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -10,8 +10,10 @@ use addrinfo = uv::ll::addrinfo; use uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t; use uv_ip4_addr = uv::ll::ip4_addr; use uv_ip4_name = uv::ll::ip4_name; +use uv_ip4_port = uv::ll::ip4_port; use uv_ip6_addr = uv::ll::ip6_addr; use uv_ip6_name = uv::ll::ip6_name; +use uv_ip6_port = uv::ll::ip6_port; use uv_getaddrinfo = uv::ll::getaddrinfo; use uv_freeaddrinfo = uv::ll::freeaddrinfo; use create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t; @@ -33,11 +35,11 @@ type ParseAddrErr = { }; /** - * Convert a `ip_addr` to a str + * Convert a `IpAddr` to a str * * # Arguments * - * * ip - a `std::net::ip::ip_addr` + * * ip - a `std::net::ip::IpAddr` */ pub fn format_addr(ip: &IpAddr) -> ~str { match *ip { @@ -58,6 +60,23 @@ pub fn format_addr(ip: &IpAddr) -> ~str { } } +/** + * Get the associated port + * + * # Arguments + * * ip - a `std::net::ip::IpAddr` + */ +pub fn get_port(ip: &IpAddr) -> uint { + match *ip { + Ipv4(ref addr) => unsafe { + uv_ip4_port(addr) + }, + Ipv6(ref addr) => unsafe { + uv_ip6_port(addr) + } + } +} + /// Represents errors returned from `net::ip::get_addr()` enum IpGetAddrErr { GetAddrUnknownError @@ -128,7 +147,7 @@ pub mod v4 { */ pub fn parse_addr(ip: &str) -> IpAddr { match try_parse_addr(ip) { - result::Ok(copy addr) => addr, + result::Ok(move addr) => move addr, result::Err(ref err_data) => fail err_data.err_msg } } @@ -214,7 +233,7 @@ pub mod v6 { */ pub fn parse_addr(ip: &str) -> IpAddr { match try_parse_addr(ip) { - result::Ok(copy addr) => addr, + result::Ok(move addr) => move addr, result::Err(copy err_data) => fail err_data.err_msg } } @@ -353,7 +372,7 @@ mod test { } // note really sure how to realiably test/assert // this.. mostly just wanting to see it work, atm. - let results = result::unwrap(ga_result); + let results = result::unwrap(move ga_result); log(debug, fmt!("test_get_addr: Number of results for %s: %?", localhost_name, vec::len(results))); for vec::each(results) |r| { @@ -366,7 +385,7 @@ mod test { } // at least one result.. this is going to vary from system // to system, based on stuff like the contents of /etc/hosts - assert vec::len(results) > 0; + assert !results.is_empty(); } #[test] #[ignore(reason = "valgrind says it's leaky")] diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 249551fbb7d..942d52a3ad6 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -6,9 +6,7 @@ use ip = net_ip; use uv::iotask; use uv::iotask::IoTask; use future_spawn = future::spawn; -// FIXME #1935 -// should be able to, but can't atm, replace w/ result::{result, extensions}; -use result::*; +use result::{Result}; use libc::size_t; use io::{Reader, ReaderUtil, Writer}; use comm = core::comm; @@ -136,6 +134,10 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, stream_handle_ptr: stream_handle_ptr, connect_req: uv::ll::connect_t(), write_req: uv::ll::write_t(), + ipv6: match input_ip { + ip::Ipv4(_) => { false } + ip::Ipv6(_) => { true } + }, iotask: iotask }; let socket_data_ptr = ptr::addr_of(&(*socket_data)); @@ -477,6 +479,7 @@ pub fn accept(new_conn: TcpNewConnection) stream_handle_ptr : stream_handle_ptr, connect_req : uv::ll::connect_t(), write_req : uv::ll::write_t(), + ipv6: (*server_data_ptr).ipv6, iotask : iotask }; let client_socket_data_ptr = ptr::addr_of(&(*client_socket_data)); @@ -564,7 +567,8 @@ pub fn listen(host_ip: ip::IpAddr, port: uint, backlog: uint, new_connect_cb: fn~(TcpNewConnection, comm::Chan<Option<TcpErrData>>)) -> result::Result<(), TcpListenErrData> unsafe { - do listen_common(move host_ip, port, backlog, iotask, on_establish_cb) + do listen_common(move host_ip, port, backlog, iotask, + move on_establish_cb) // on_connect_cb |move new_connect_cb, handle| unsafe { let server_data_ptr = uv::ll::get_data_for_uv_handle(handle) @@ -591,6 +595,10 @@ fn listen_common(host_ip: ip::IpAddr, port: uint, backlog: uint, kill_ch: kill_ch, on_connect_cb: move on_connect_cb, iotask: iotask, + ipv6: match host_ip { + ip::Ipv4(_) => { false } + ip::Ipv6(_) => { true } + }, mut active: true }; let server_data_ptr = ptr::addr_of(&server_data); @@ -747,6 +755,21 @@ impl TcpSocket { -> future::Future<result::Result<(), TcpErrData>> { write_future(&self, raw_write_data) } + pub fn get_peer_addr() -> ip::IpAddr { + unsafe { + if self.socket_data.ipv6 { + let addr = uv::ll::ip6_addr("", 0); + uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr, + ptr::addr_of(&addr)); + ip::Ipv6(move addr) + } else { + let addr = uv::ll::ip4_addr("", 0); + uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr, + ptr::addr_of(&addr)); + ip::Ipv4(move addr) + } + } + } } /// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket` @@ -1004,6 +1027,7 @@ type TcpListenFcData = { kill_ch: comm::Chan<Option<TcpErrData>>, on_connect_cb: fn~(*uv::ll::uv_tcp_t), iotask: IoTask, + ipv6: bool, mut active: bool }; @@ -1093,7 +1117,7 @@ extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t, log(debug, fmt!("tcp on_read_cb nread: %d", nread as int)); let reader_ch = (*socket_data_ptr).reader_ch; let buf_base = uv::ll::get_base_from_buf(buf); - let new_bytes = vec::raw::from_buf(buf_base, nread as uint); + let new_bytes = vec::from_buf(buf_base, nread as uint); core::comm::send(reader_ch, result::Ok(new_bytes)); } } @@ -1202,6 +1226,7 @@ type TcpSocketData = { stream_handle_ptr: *uv::ll::uv_tcp_t, connect_req: uv::ll::uv_connect_t, write_req: uv::ll::uv_write_t, + ipv6: bool, iotask: IoTask }; @@ -1224,6 +1249,10 @@ mod test { impl_gl_tcp_ipv4_server_and_client(); } #[test] + fn test_gl_tcp_get_peer_addr() unsafe { + impl_gl_tcp_ipv4_get_peer_addr(); + } + #[test] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } @@ -1250,6 +1279,11 @@ mod test { } #[test] #[ignore(cfg(target_os = "linux"))] + fn test_gl_tcp_get_peer_addr() unsafe { + impl_gl_tcp_ipv4_get_peer_addr(); + } + #[test] + #[ignore(cfg(target_os = "linux"))] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } @@ -1317,6 +1351,53 @@ mod test { assert str::contains(actual_req, expected_req); assert str::contains(actual_resp, expected_resp); } + fn impl_gl_tcp_ipv4_get_peer_addr() { + let hl_loop = uv::global_loop::get(); + let server_ip = ~"127.0.0.1"; + let server_port = 8887u; + let expected_resp = ~"pong"; + + let server_result_po = core::comm::Port::<~str>(); + let server_result_ch = core::comm::Chan(&server_result_po); + + let cont_po = core::comm::Port::<()>(); + let cont_ch = core::comm::Chan(&cont_po); + // server + do task::spawn_sched(task::ManualThreads(1u)) { + let actual_req = do comm::listen |server_ch| { + run_tcp_test_server( + server_ip, + server_port, + expected_resp, + server_ch, + cont_ch, + hl_loop) + }; + server_result_ch.send(actual_req); + }; + core::comm::recv(cont_po); + // client + log(debug, ~"server started, firing up client.."); + do core::comm::listen |client_ch| { + let server_ip_addr = ip::v4::parse_addr(server_ip); + let iotask = uv::global_loop::get(); + let connect_result = connect(move server_ip_addr, server_port, + iotask); + + let sock = result::unwrap(move connect_result); + + // This is what we are actually testing! + assert net::ip::format_addr(&sock.get_peer_addr()) == + ~"127.0.0.1"; + assert net::ip::get_port(&sock.get_peer_addr()) == 8887; + + // Fulfill the protocol the test server expects + let resp_bytes = str::to_bytes(~"ping"); + tcp_write_single(&sock, resp_bytes); + let read_result = sock.read(0u); + client_ch.send(str::from_bytes(read_result.get())); + }; + } fn impl_gl_tcp_ipv4_client_error_connection_refused() { let hl_loop = uv::global_loop::get(); let server_ip = ~"127.0.0.1"; @@ -1512,8 +1593,11 @@ mod test { ~"SERVER/WORKER: send on cont ch"); cont_ch.send(()); let sock = result::unwrap(move accept_result); + let peer_addr = sock.get_peer_addr(); log(debug, ~"SERVER: successfully accepted"+ - ~"connection!"); + fmt!(" connection from %s:%u", + ip::format_addr(&peer_addr), + ip::get_port(&peer_addr))); let received_req_bytes = read(&sock, 0u); match move received_req_bytes { result::Ok(move data) => { diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index 0ab4d89f363..8ea9513d155 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -65,10 +65,10 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { str::push_char(&mut out, ch); } - _ => out += #fmt("%%%X", ch as uint) + _ => out += fmt!("%%%X", ch as uint) } } else { - out += #fmt("%%%X", ch as uint); + out += fmt!("%%%X", ch as uint); } } } @@ -94,6 +94,7 @@ pub fn encode(s: &str) -> ~str { * * This function is compliant with RFC 3986. */ + pub fn encode_component(s: &str) -> ~str { encode_inner(s, false) } @@ -163,7 +164,7 @@ fn encode_plus(s: &str) -> ~str { str::push_char(&mut out, ch); } ' ' => str::push_char(&mut out, '+'), - _ => out += #fmt("%%%X", ch as uint) + _ => out += fmt!("%%%X", ch as uint) } } @@ -189,7 +190,7 @@ pub fn encode_form_urlencoded(m: HashMap<~str, @DVec<@~str>>) -> ~str { first = false; } - out += #fmt("%s=%s", key, encode_plus(**value)); + out += fmt!("%s=%s", key, encode_plus(**value)); } } @@ -297,7 +298,7 @@ fn userinfo_from_str(uinfo: &str) -> UserInfo { return UserInfo(user, pass); } -fn userinfo_to_str(userinfo: UserInfo) -> ~str { +pure fn userinfo_to_str(userinfo: UserInfo) -> ~str { if option::is_some(&userinfo.pass) { return str::concat(~[copy userinfo.user, ~":", option::unwrap(copy userinfo.pass), @@ -325,11 +326,15 @@ fn query_from_str(rawquery: &str) -> Query { return query; } -pub fn query_to_str(query: Query) -> ~str { +pub pure fn query_to_str(query: Query) -> ~str { let mut strvec = ~[]; for query.each |kv| { let (k, v) = copy *kv; - strvec += ~[#fmt("%s=%s", encode_component(k), encode_component(v))]; + // This is really safe... + unsafe { + strvec += ~[fmt!("%s=%s", + encode_component(k), encode_component(v))]; + } }; return str::connect(strvec, ~"&"); } @@ -672,7 +677,7 @@ impl Url : FromStr { * result in just "http://somehost.com". * */ -pub fn to_str(url: Url) -> ~str { +pub pure fn to_str(url: Url) -> ~str { let user = if url.user.is_some() { userinfo_to_str(option::unwrap(copy url.user)) } else { @@ -688,7 +693,8 @@ pub fn to_str(url: Url) -> ~str { } else { str::concat(~[~"?", query_to_str(url.query)]) }; - let fragment = if url.fragment.is_some() { + // ugh, this really is safe + let fragment = if url.fragment.is_some() unsafe { str::concat(~[~"#", encode_component( option::unwrap(copy url.fragment))]) } else { @@ -704,7 +710,7 @@ pub fn to_str(url: Url) -> ~str { } impl Url: to_str::ToStr { - pub fn to_str() -> ~str { + pub pure fn to_str() -> ~str { to_str(self) } } @@ -844,7 +850,7 @@ mod tests { fn test_url_parse_host_slash() { let urlstr = ~"http://0.42.42.42/"; let url = from_str(urlstr).get(); - #debug("url: %?", url); + debug!("url: %?", url); assert url.host == ~"0.42.42.42"; assert url.path == ~"/"; } @@ -853,7 +859,7 @@ mod tests { fn test_url_with_underscores() { let urlstr = ~"http://dotcom.com/file_name.html"; let url = from_str(urlstr).get(); - #debug("url: %?", url); + debug!("url: %?", url); assert url.path == ~"/file_name.html"; } @@ -861,7 +867,7 @@ mod tests { fn test_url_with_dashes() { let urlstr = ~"http://dotcom.com/file-name.html"; let url = from_str(urlstr).get(); - #debug("url: %?", url); + debug!("url: %?", url); assert url.path == ~"/file-name.html"; } diff --git a/src/libstd/prettyprint.rs b/src/libstd/prettyprint.rs index bc528800666..6119c03cdca 100644 --- a/src/libstd/prettyprint.rs +++ b/src/libstd/prettyprint.rs @@ -2,131 +2,175 @@ use io::Writer; use io::WriterUtil; -use serialization::Serializer; +use serialization; -impl Writer: Serializer { - fn emit_nil() { - self.write_str(~"()") +pub struct Serializer { + wr: io::Writer, +} + +pub fn Serializer(wr: io::Writer) -> Serializer { + Serializer { wr: wr } +} + +pub impl Serializer: serialization::Serializer { + fn emit_nil(&self) { + self.wr.write_str(~"()") + } + + fn emit_uint(&self, v: uint) { + self.wr.write_str(fmt!("%?u", v)); + } + + fn emit_u64(&self, v: u64) { + self.wr.write_str(fmt!("%?_u64", v)); + } + + fn emit_u32(&self, v: u32) { + self.wr.write_str(fmt!("%?_u32", v)); + } + + fn emit_u16(&self, v: u16) { + self.wr.write_str(fmt!("%?_u16", v)); + } + + fn emit_u8(&self, v: u8) { + self.wr.write_str(fmt!("%?_u8", v)); } - fn emit_uint(v: uint) { - self.write_str(fmt!("%?u", v)); + fn emit_int(&self, v: int) { + self.wr.write_str(fmt!("%?", v)); } - fn emit_u64(v: u64) { - self.write_str(fmt!("%?_u64", v)); + fn emit_i64(&self, v: i64) { + self.wr.write_str(fmt!("%?_i64", v)); } - fn emit_u32(v: u32) { - self.write_str(fmt!("%?_u32", v)); + fn emit_i32(&self, v: i32) { + self.wr.write_str(fmt!("%?_i32", v)); } - fn emit_u16(v: u16) { - self.write_str(fmt!("%?_u16", v)); + fn emit_i16(&self, v: i16) { + self.wr.write_str(fmt!("%?_i16", v)); } - fn emit_u8(v: u8) { - self.write_str(fmt!("%?_u8", v)); + fn emit_i8(&self, v: i8) { + self.wr.write_str(fmt!("%?_i8", v)); } - fn emit_int(v: int) { - self.write_str(fmt!("%?", v)); + fn emit_bool(&self, v: bool) { + self.wr.write_str(fmt!("%b", v)); } - fn emit_i64(v: i64) { - self.write_str(fmt!("%?_i64", v)); + fn emit_float(&self, v: float) { + self.wr.write_str(fmt!("%?_f", v)); } - fn emit_i32(v: i32) { - self.write_str(fmt!("%?_i32", v)); + fn emit_f64(&self, v: f64) { + self.wr.write_str(fmt!("%?_f64", v)); } - fn emit_i16(v: i16) { - self.write_str(fmt!("%?_i16", v)); + fn emit_f32(&self, v: f32) { + self.wr.write_str(fmt!("%?_f32", v)); } - fn emit_i8(v: i8) { - self.write_str(fmt!("%?_i8", v)); + fn emit_char(&self, v: char) { + self.wr.write_str(fmt!("%?", v)); } - fn emit_bool(v: bool) { - self.write_str(fmt!("%b", v)); + fn emit_borrowed_str(&self, v: &str) { + self.wr.write_str(fmt!("&%?", v)); } - fn emit_float(v: float) { - self.write_str(fmt!("%?_f", v)); + fn emit_owned_str(&self, v: &str) { + self.wr.write_str(fmt!("~%?", v)); } - fn emit_f64(v: f64) { - self.write_str(fmt!("%?_f64", v)); + fn emit_managed_str(&self, v: &str) { + self.wr.write_str(fmt!("@%?", v)); } - fn emit_f32(v: f32) { - self.write_str(fmt!("%?_f32", v)); + fn emit_borrowed(&self, f: fn()) { + self.wr.write_str(~"&"); + f(); } - fn emit_str(v: &str) { - self.write_str(fmt!("%?", v)); + fn emit_owned(&self, f: fn()) { + self.wr.write_str(~"~"); + f(); + } + + fn emit_managed(&self, f: fn()) { + self.wr.write_str(~"@"); + f(); + } + + fn emit_enum(&self, _name: &str, f: fn()) { + f(); } - fn emit_enum(_name: &str, f: fn()) { + fn emit_enum_variant(&self, v_name: &str, _v_id: uint, sz: uint, + f: fn()) { + self.wr.write_str(v_name); + if sz > 0u { self.wr.write_str(~"("); } f(); + if sz > 0u { self.wr.write_str(~")"); } } - fn emit_enum_variant(v_name: &str, _v_id: uint, sz: uint, f: fn()) { - self.write_str(v_name); - if sz > 0u { self.write_str(~"("); } + fn emit_enum_variant_arg(&self, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } f(); - if sz > 0u { self.write_str(~")"); } } - fn emit_enum_variant_arg(idx: uint, f: fn()) { - if idx > 0u { self.write_str(~", "); } + fn emit_borrowed_vec(&self, _len: uint, f: fn()) { + self.wr.write_str(~"&["); f(); + self.wr.write_str(~"]"); } - fn emit_vec(_len: uint, f: fn()) { - self.write_str(~"["); + fn emit_owned_vec(&self, _len: uint, f: fn()) { + self.wr.write_str(~"~["); f(); - self.write_str(~"]"); + self.wr.write_str(~"]"); } - fn emit_vec_elt(idx: uint, f: fn()) { - if idx > 0u { self.write_str(~", "); } + fn emit_managed_vec(&self, _len: uint, f: fn()) { + self.wr.write_str(~"@["); f(); + self.wr.write_str(~"]"); } - fn emit_box(f: fn()) { - self.write_str(~"@"); + fn emit_vec_elt(&self, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } f(); } - fn emit_uniq(f: fn()) { - self.write_str(~"~"); + fn emit_rec(&self, f: fn()) { + self.wr.write_str(~"{"); f(); + self.wr.write_str(~"}"); } - fn emit_rec(f: fn()) { - self.write_str(~"{"); + fn emit_struct(&self, name: &str, f: fn()) { + self.wr.write_str(fmt!("%s {", name)); f(); - self.write_str(~"}"); + self.wr.write_str(~"}"); } - fn emit_rec_field(f_name: &str, f_idx: uint, f: fn()) { - if f_idx > 0u { self.write_str(~", "); } - self.write_str(f_name); - self.write_str(~": "); + fn emit_field(&self, name: &str, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } + self.wr.write_str(name); + self.wr.write_str(~": "); f(); } - fn emit_tup(_sz: uint, f: fn()) { - self.write_str(~"("); + fn emit_tup(&self, _len: uint, f: fn()) { + self.wr.write_str(~"("); f(); - self.write_str(~")"); + self.wr.write_str(~")"); } - fn emit_tup_elt(idx: uint, f: fn()) { - if idx > 0u { self.write_str(~", "); } + fn emit_tup_elt(&self, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } f(); } } diff --git a/src/libstd/prettyprint2.rs b/src/libstd/prettyprint2.rs deleted file mode 100644 index 87af519eb12..00000000000 --- a/src/libstd/prettyprint2.rs +++ /dev/null @@ -1,176 +0,0 @@ -#[forbid(deprecated_mode)]; - -use io::Writer; -use io::WriterUtil; -use serialization2; - -pub struct Serializer { - wr: io::Writer, -} - -pub fn Serializer(wr: io::Writer) -> Serializer { - Serializer { wr: wr } -} - -pub impl Serializer: serialization2::Serializer { - fn emit_nil(&self) { - self.wr.write_str(~"()") - } - - fn emit_uint(&self, v: uint) { - self.wr.write_str(fmt!("%?u", v)); - } - - fn emit_u64(&self, v: u64) { - self.wr.write_str(fmt!("%?_u64", v)); - } - - fn emit_u32(&self, v: u32) { - self.wr.write_str(fmt!("%?_u32", v)); - } - - fn emit_u16(&self, v: u16) { - self.wr.write_str(fmt!("%?_u16", v)); - } - - fn emit_u8(&self, v: u8) { - self.wr.write_str(fmt!("%?_u8", v)); - } - - fn emit_int(&self, v: int) { - self.wr.write_str(fmt!("%?", v)); - } - - fn emit_i64(&self, v: i64) { - self.wr.write_str(fmt!("%?_i64", v)); - } - - fn emit_i32(&self, v: i32) { - self.wr.write_str(fmt!("%?_i32", v)); - } - - fn emit_i16(&self, v: i16) { - self.wr.write_str(fmt!("%?_i16", v)); - } - - fn emit_i8(&self, v: i8) { - self.wr.write_str(fmt!("%?_i8", v)); - } - - fn emit_bool(&self, v: bool) { - self.wr.write_str(fmt!("%b", v)); - } - - fn emit_float(&self, v: float) { - self.wr.write_str(fmt!("%?_f", v)); - } - - fn emit_f64(&self, v: f64) { - self.wr.write_str(fmt!("%?_f64", v)); - } - - fn emit_f32(&self, v: f32) { - self.wr.write_str(fmt!("%?_f32", v)); - } - - fn emit_char(&self, v: char) { - self.wr.write_str(fmt!("%?", v)); - } - - fn emit_borrowed_str(&self, v: &str) { - self.wr.write_str(fmt!("&%?", v)); - } - - fn emit_owned_str(&self, v: &str) { - self.wr.write_str(fmt!("~%?", v)); - } - - fn emit_managed_str(&self, v: &str) { - self.wr.write_str(fmt!("@%?", v)); - } - - fn emit_borrowed(&self, f: fn()) { - self.wr.write_str(~"&"); - f(); - } - - fn emit_owned(&self, f: fn()) { - self.wr.write_str(~"~"); - f(); - } - - fn emit_managed(&self, f: fn()) { - self.wr.write_str(~"@"); - f(); - } - - fn emit_enum(&self, _name: &str, f: fn()) { - f(); - } - - fn emit_enum_variant(&self, v_name: &str, _v_id: uint, sz: uint, - f: fn()) { - self.wr.write_str(v_name); - if sz > 0u { self.wr.write_str(~"("); } - f(); - if sz > 0u { self.wr.write_str(~")"); } - } - - fn emit_enum_variant_arg(&self, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - f(); - } - - fn emit_borrowed_vec(&self, _len: uint, f: fn()) { - self.wr.write_str(~"&["); - f(); - self.wr.write_str(~"]"); - } - - fn emit_owned_vec(&self, _len: uint, f: fn()) { - self.wr.write_str(~"~["); - f(); - self.wr.write_str(~"]"); - } - - fn emit_managed_vec(&self, _len: uint, f: fn()) { - self.wr.write_str(~"@["); - f(); - self.wr.write_str(~"]"); - } - - fn emit_vec_elt(&self, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - f(); - } - - fn emit_rec(&self, f: fn()) { - self.wr.write_str(~"{"); - f(); - self.wr.write_str(~"}"); - } - - fn emit_struct(&self, name: &str, f: fn()) { - self.wr.write_str(fmt!("%s {", name)); - f(); - self.wr.write_str(~"}"); - } - - fn emit_field(&self, name: &str, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - self.wr.write_str(name); - self.wr.write_str(~": "); - f(); - } - - fn emit_tup(&self, _len: uint, f: fn()) { - self.wr.write_str(~"("); - f(); - self.wr.write_str(~")"); - } - - fn emit_tup_elt(&self, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - f(); - } -} diff --git a/src/libstd/serialization.rs b/src/libstd/serialization.rs index 8ba00e65dec..9df2a326a84 100644 --- a/src/libstd/serialization.rs +++ b/src/libstd/serialization.rs @@ -1,81 +1,532 @@ //! Support code for serialization. -#[allow(deprecated_mode)]; - /* Core serialization interfaces. */ +#[forbid(deprecated_mode)]; +#[forbid(non_camel_case_types)]; + pub trait Serializer { // Primitive types: - fn emit_nil(); - fn emit_uint(v: uint); - fn emit_u64(v: u64); - fn emit_u32(v: u32); - fn emit_u16(v: u16); - fn emit_u8(v: u8); - fn emit_int(v: int); - fn emit_i64(v: i64); - fn emit_i32(v: i32); - fn emit_i16(v: i16); - fn emit_i8(v: i8); - fn emit_bool(v: bool); - fn emit_float(v: float); - fn emit_f64(v: f64); - fn emit_f32(v: f32); - fn emit_str(v: &str); + fn emit_nil(&self); + fn emit_uint(&self, v: uint); + fn emit_u64(&self, v: u64); + fn emit_u32(&self, v: u32); + fn emit_u16(&self, v: u16); + fn emit_u8(&self, v: u8); + fn emit_int(&self, v: int); + fn emit_i64(&self, v: i64); + fn emit_i32(&self, v: i32); + fn emit_i16(&self, v: i16); + fn emit_i8(&self, v: i8); + fn emit_bool(&self, v: bool); + fn emit_float(&self, v: float); + fn emit_f64(&self, v: f64); + fn emit_f32(&self, v: f32); + fn emit_char(&self, v: char); + fn emit_borrowed_str(&self, v: &str); + fn emit_owned_str(&self, v: &str); + fn emit_managed_str(&self, v: &str); // Compound types: - fn emit_enum(name: &str, f: fn()); - fn emit_enum_variant(v_name: &str, v_id: uint, sz: uint, f: fn()); - fn emit_enum_variant_arg(idx: uint, f: fn()); - fn emit_vec(len: uint, f: fn()); - fn emit_vec_elt(idx: uint, f: fn()); - fn emit_box(f: fn()); - fn emit_uniq(f: fn()); - fn emit_rec(f: fn()); - fn emit_rec_field(f_name: &str, f_idx: uint, f: fn()); - fn emit_tup(sz: uint, f: fn()); - fn emit_tup_elt(idx: uint, f: fn()); + fn emit_borrowed(&self, f: fn()); + fn emit_owned(&self, f: fn()); + fn emit_managed(&self, f: fn()); + + fn emit_enum(&self, name: &str, f: fn()); + fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: fn()); + fn emit_enum_variant_arg(&self, idx: uint, f: fn()); + + fn emit_borrowed_vec(&self, len: uint, f: fn()); + fn emit_owned_vec(&self, len: uint, f: fn()); + fn emit_managed_vec(&self, len: uint, f: fn()); + fn emit_vec_elt(&self, idx: uint, f: fn()); + + fn emit_rec(&self, f: fn()); + fn emit_struct(&self, name: &str, f: fn()); + fn emit_field(&self, f_name: &str, f_idx: uint, f: fn()); + + fn emit_tup(&self, len: uint, f: fn()); + fn emit_tup_elt(&self, idx: uint, f: fn()); } pub trait Deserializer { // Primitive types: - fn read_nil() -> (); + fn read_nil(&self) -> (); + fn read_uint(&self) -> uint; + fn read_u64(&self) -> u64; + fn read_u32(&self) -> u32; + fn read_u16(&self) -> u16; + fn read_u8(&self) -> u8; + fn read_int(&self) -> int; + fn read_i64(&self) -> i64; + fn read_i32(&self) -> i32; + fn read_i16(&self) -> i16; + fn read_i8(&self) -> i8; + fn read_bool(&self) -> bool; + fn read_f64(&self) -> f64; + fn read_f32(&self) -> f32; + fn read_float(&self) -> float; + fn read_char(&self) -> char; + fn read_owned_str(&self) -> ~str; + fn read_managed_str(&self) -> @str; - fn read_uint() -> uint; - fn read_u64() -> u64; - fn read_u32() -> u32; - fn read_u16() -> u16; - fn read_u8() -> u8; + // Compound types: + fn read_enum<T>(&self, name: &str, f: fn() -> T) -> T; + fn read_enum_variant<T>(&self, f: fn(uint) -> T) -> T; + fn read_enum_variant_arg<T>(&self, idx: uint, f: fn() -> T) -> T; - fn read_int() -> int; - fn read_i64() -> i64; - fn read_i32() -> i32; - fn read_i16() -> i16; - fn read_i8() -> i8; + fn read_owned<T>(&self, f: fn() -> T) -> T; + fn read_managed<T>(&self, f: fn() -> T) -> T; + fn read_owned_vec<T>(&self, f: fn(uint) -> T) -> T; + fn read_managed_vec<T>(&self, f: fn(uint) -> T) -> T; + fn read_vec_elt<T>(&self, idx: uint, f: fn() -> T) -> T; - fn read_bool() -> bool; + fn read_rec<T>(&self, f: fn() -> T) -> T; + fn read_struct<T>(&self, name: &str, f: fn() -> T) -> T; + fn read_field<T>(&self, name: &str, idx: uint, f: fn() -> T) -> T; - fn read_str() -> ~str; + fn read_tup<T>(&self, sz: uint, f: fn() -> T) -> T; + fn read_tup_elt<T>(&self, idx: uint, f: fn() -> T) -> T; +} - fn read_f64() -> f64; - fn read_f32() -> f32; - fn read_float() -> float; +#[cfg(stage0)] +pub mod traits { +pub trait Serializable { + fn serialize<S: Serializer>(&self, s: &S); +} - // Compound types: - fn read_enum<T>(name: &str, f: fn() -> T) -> T; - fn read_enum_variant<T>(f: fn(uint) -> T) -> T; - fn read_enum_variant_arg<T>(idx: uint, f: fn() -> T) -> T; - fn read_vec<T>(f: fn(uint) -> T) -> T; - fn read_vec_elt<T>(idx: uint, f: fn() -> T) -> T; - fn read_box<T>(f: fn() -> T) -> T; - fn read_uniq<T>(f: fn() -> T) -> T; - fn read_rec<T>(f: fn() -> T) -> T; - fn read_rec_field<T>(f_name: &str, f_idx: uint, f: fn() -> T) -> T; - fn read_tup<T>(sz: uint, f: fn() -> T) -> T; - fn read_tup_elt<T>(idx: uint, f: fn() -> T) -> T; +pub trait Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> self; +} + +pub impl uint: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_uint(*self) } +} + +pub impl uint: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> uint { + d.read_uint() + } +} + +pub impl u8: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_u8(*self) } +} + +pub impl u8: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> u8 { + d.read_u8() + } +} + +pub impl u16: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_u16(*self) } +} + +pub impl u16: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> u16 { + d.read_u16() + } +} + +pub impl u32: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_u32(*self) } +} + +pub impl u32: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> u32 { + d.read_u32() + } +} + +pub impl u64: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_u64(*self) } +} + +pub impl u64: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> u64 { + d.read_u64() + } +} + +pub impl int: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_int(*self) } +} + +pub impl int: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> int { + d.read_int() + } +} + +pub impl i8: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_i8(*self) } +} + +pub impl i8: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> i8 { + d.read_i8() + } +} + +pub impl i16: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_i16(*self) } +} + +pub impl i16: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> i16 { + d.read_i16() + } +} + +pub impl i32: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_i32(*self) } +} + +pub impl i32: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> i32 { + d.read_i32() + } +} + +pub impl i64: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_i64(*self) } +} + +pub impl i64: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> i64 { + d.read_i64() + } +} + +pub impl &str: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_borrowed_str(*self) } +} + +pub impl ~str: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_owned_str(*self) } +} + +pub impl ~str: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> ~str { + d.read_owned_str() + } +} + +pub impl @str: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_managed_str(*self) } +} + +pub impl @str: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> @str { + d.read_managed_str() + } +} + +pub impl float: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_float(*self) } +} + +pub impl float: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> float { + d.read_float() + } +} + +pub impl f32: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_f32(*self) } +} + +pub impl f32: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> f32 { + d.read_f32() } +} + +pub impl f64: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_f64(*self) } +} + +pub impl f64: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> f64 { + d.read_f64() + } +} + +pub impl bool: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_bool(*self) } +} + +pub impl bool: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> bool { + d.read_bool() + } +} + +pub impl (): Serializable { + fn serialize<S: Serializer>(&self, s: &S) { s.emit_nil() } +} + +pub impl (): Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> () { + d.read_nil() + } +} + +pub impl<T: Serializable> &T: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + s.emit_borrowed(|| (**self).serialize(s)) + } +} + +pub impl<T: Serializable> ~T: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + s.emit_owned(|| (**self).serialize(s)) + } +} + +pub impl<T: Deserializable> ~T: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> ~T { + d.read_owned(|| ~deserialize(d)) + } +} + +pub impl<T: Serializable> @T: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + s.emit_managed(|| (**self).serialize(s)) + } +} + +pub impl<T: Deserializable> @T: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> @T { + d.read_managed(|| @deserialize(d)) + } +} + +pub impl<T: Serializable> &[T]: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + do s.emit_borrowed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl<T: Serializable> ~[T]: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + do s.emit_owned_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl<T: Deserializable> ~[T]: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> ~[T] { + do d.read_owned_vec |len| { + do vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl<T: Serializable> @[T]: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + do s.emit_managed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl<T: Deserializable> @[T]: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> @[T] { + do d.read_managed_vec |len| { + do at_vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl<T: Serializable> Option<T>: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + do s.emit_enum(~"option") { + match *self { + None => do s.emit_enum_variant(~"none", 0u, 0u) { + }, + + Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { + s.emit_enum_variant_arg(0u, || v.serialize(s)) + } + } + } + } +} + +pub impl<T: Deserializable> Option<T>: Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> Option<T> { + do d.read_enum(~"option") { + do d.read_enum_variant |i| { + match i { + 0 => None, + 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), + _ => fail(fmt!("Bad variant for option: %u", i)) + } + } + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable +> (T0, T1): Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + match *self { + (ref t0, ref t1) => { + do s.emit_tup(2) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable +> (T0, T1): Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> (T0, T1) { + do d.read_tup(2) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)) + ) + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable, + T2: Serializable +> (T0, T1, T2): Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2) => { + do s.emit_tup(3) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable, + T2: Deserializable +> (T0, T1, T2): Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> (T0, T1, T2) { + do d.read_tup(3) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)) + ) + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable, + T2: Serializable, + T3: Serializable +> (T0, T1, T2, T3): Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3) => { + do s.emit_tup(4) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable, + T2: Deserializable, + T3: Deserializable +> (T0, T1, T2, T3): Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) -> (T0, T1, T2, T3) { + do d.read_tup(4) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)) + ) + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable, + T2: Serializable, + T3: Serializable, + T4: Serializable +> (T0, T1, T2, T3, T4): Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3, ref t4) => { + do s.emit_tup(5) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + s.emit_tup_elt(4, || t4.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable, + T2: Deserializable, + T3: Deserializable, + T4: Deserializable +> (T0, T1, T2, T3, T4): Deserializable { + static fn deserialize<D: Deserializer>(&self, d: &D) + -> (T0, T1, T2, T3, T4) { + do d.read_tup(5) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)), + d.read_tup_elt(4, || deserialize(d)) + ) + } + } } // ___________________________________________________________________________ @@ -83,189 +534,517 @@ pub trait Deserializer { // // In some cases, these should eventually be coded as traits. -pub fn emit_from_vec<S: Serializer, T>(&&s: S, &&v: ~[T], f: fn(&&x: T)) { - do s.emit_vec(vec::len(v)) { - for vec::eachi(v) |i,e| { - do s.emit_vec_elt(i) { - f(*e) +pub trait SerializerHelpers { + fn emit_from_vec<T>(&self, v: &[T], f: fn(&T)); +} + +pub impl<S: Serializer> S: SerializerHelpers { + fn emit_from_vec<T>(&self, v: &[T], f: fn(&T)) { + do self.emit_owned_vec(v.len()) { + for v.eachi |i, e| { + do self.emit_vec_elt(i) { + f(e) + } } } } } -pub fn read_to_vec<D: Deserializer, T: Copy>(&&d: D, f: fn() -> T) -> ~[T] { - do d.read_vec |len| { - do vec::from_fn(len) |i| { - d.read_vec_elt(i, || f()) +pub trait DeserializerHelpers { + fn read_to_vec<T>(&self, f: fn() -> T) -> ~[T]; +} + +pub impl<D: Deserializer> D: DeserializerHelpers { + fn read_to_vec<T>(&self, f: fn() -> T) -> ~[T] { + do self.read_owned_vec |len| { + do vec::from_fn(len) |i| { + self.read_vec_elt(i, || f()) + } } } } +} -pub trait SerializerHelpers { - fn emit_from_vec<T>(&&v: ~[T], f: fn(&&x: T)); +#[cfg(stage1)] +#[cfg(stage2)] +pub mod traits { +pub trait Serializable<S: Serializer> { + fn serialize(&self, s: &S); +} + +pub trait Deserializable<D: Deserializer> { + static fn deserialize(&self, d: &D) -> self; +} + +pub impl<S: Serializer> uint: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_uint(*self) } } -impl<S: Serializer> S: SerializerHelpers { - fn emit_from_vec<T>(&&v: ~[T], f: fn(&&x: T)) { - emit_from_vec(self, v, f) +pub impl<D: Deserializer> uint: Deserializable<D> { + static fn deserialize(&self, d: &D) -> uint { + d.read_uint() } } -pub trait DeserializerHelpers { - fn read_to_vec<T: Copy>(f: fn() -> T) -> ~[T]; +pub impl<S: Serializer> u8: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_u8(*self) } +} + +pub impl<D: Deserializer> u8: Deserializable<D> { + static fn deserialize(&self, d: &D) -> u8 { + d.read_u8() + } +} + +pub impl<S: Serializer> u16: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_u16(*self) } +} + +pub impl<D: Deserializer> u16: Deserializable<D> { + static fn deserialize(&self, d: &D) -> u16 { + d.read_u16() + } +} + +pub impl<S: Serializer> u32: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_u32(*self) } +} + +pub impl<D: Deserializer> u32: Deserializable<D> { + static fn deserialize(&self, d: &D) -> u32 { + d.read_u32() + } +} + +pub impl<S: Serializer> u64: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_u64(*self) } +} + +pub impl<D: Deserializer> u64: Deserializable<D> { + static fn deserialize(&self, d: &D) -> u64 { + d.read_u64() + } +} + +pub impl<S: Serializer> int: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_int(*self) } +} + +pub impl<D: Deserializer> int: Deserializable<D> { + static fn deserialize(&self, d: &D) -> int { + d.read_int() + } +} + +pub impl<S: Serializer> i8: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_i8(*self) } +} + +pub impl<D: Deserializer> i8: Deserializable<D> { + static fn deserialize(&self, d: &D) -> i8 { + d.read_i8() + } +} + +pub impl<S: Serializer> i16: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_i16(*self) } +} + +pub impl<D: Deserializer> i16: Deserializable<D> { + static fn deserialize(&self, d: &D) -> i16 { + d.read_i16() + } +} + +pub impl<S: Serializer> i32: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_i32(*self) } +} + +pub impl<D: Deserializer> i32: Deserializable<D> { + static fn deserialize(&self, d: &D) -> i32 { + d.read_i32() + } +} + +pub impl<S: Serializer> i64: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_i64(*self) } } -impl<D: Deserializer> D: DeserializerHelpers { - fn read_to_vec<T: Copy>(f: fn() -> T) -> ~[T] { - read_to_vec(self, f) +pub impl<D: Deserializer> i64: Deserializable<D> { + static fn deserialize(&self, d: &D) -> i64 { + d.read_i64() } } -pub fn serialize_uint<S: Serializer>(&&s: S, v: uint) { - s.emit_uint(v); +pub impl<S: Serializer> &str: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_borrowed_str(*self) } +} + +pub impl<S: Serializer> ~str: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_owned_str(*self) } } -pub fn deserialize_uint<D: Deserializer>(&&d: D) -> uint { - d.read_uint() +pub impl<D: Deserializer> ~str: Deserializable<D> { + static fn deserialize(&self, d: &D) -> ~str { + d.read_owned_str() + } } -pub fn serialize_u8<S: Serializer>(&&s: S, v: u8) { - s.emit_u8(v); +pub impl<S: Serializer> @str: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_managed_str(*self) } } -pub fn deserialize_u8<D: Deserializer>(&&d: D) -> u8 { - d.read_u8() +pub impl<D: Deserializer> @str: Deserializable<D> { + static fn deserialize(&self, d: &D) -> @str { + d.read_managed_str() + } } -pub fn serialize_u16<S: Serializer>(&&s: S, v: u16) { - s.emit_u16(v); +pub impl<S: Serializer> float: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_float(*self) } } -pub fn deserialize_u16<D: Deserializer>(&&d: D) -> u16 { - d.read_u16() +pub impl<D: Deserializer> float: Deserializable<D> { + static fn deserialize(&self, d: &D) -> float { + d.read_float() + } } -pub fn serialize_u32<S: Serializer>(&&s: S, v: u32) { - s.emit_u32(v); +pub impl<S: Serializer> f32: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_f32(*self) } } -pub fn deserialize_u32<D: Deserializer>(&&d: D) -> u32 { - d.read_u32() +pub impl<D: Deserializer> f32: Deserializable<D> { + static fn deserialize(&self, d: &D) -> f32 { + d.read_f32() } } -pub fn serialize_u64<S: Serializer>(&&s: S, v: u64) { - s.emit_u64(v); +pub impl<S: Serializer> f64: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_f64(*self) } } -pub fn deserialize_u64<D: Deserializer>(&&d: D) -> u64 { - d.read_u64() +pub impl<D: Deserializer> f64: Deserializable<D> { + static fn deserialize(&self, d: &D) -> f64 { + d.read_f64() + } } -pub fn serialize_int<S: Serializer>(&&s: S, v: int) { - s.emit_int(v); +pub impl<S: Serializer> bool: Serializable<S> { + fn serialize(&self, s: &S) { s.emit_bool(*self) } } -pub fn deserialize_int<D: Deserializer>(&&d: D) -> int { - d.read_int() +pub impl<D: Deserializer> bool: Deserializable<D> { + static fn deserialize(&self, d: &D) -> bool { + d.read_bool() + } } -pub fn serialize_i8<S: Serializer>(&&s: S, v: i8) { - s.emit_i8(v); +pub impl<S: Serializer> (): Serializable<S> { + fn serialize(&self, s: &S) { s.emit_nil() } } -pub fn deserialize_i8<D: Deserializer>(&&d: D) -> i8 { - d.read_i8() +pub impl<D: Deserializer> (): Deserializable<D> { + static fn deserialize(&self, d: &D) -> () { + d.read_nil() + } } -pub fn serialize_i16<S: Serializer>(&&s: S, v: i16) { - s.emit_i16(v); +pub impl<S: Serializer, T: Serializable<S>> &T: Serializable<S> { + fn serialize(&self, s: &S) { + s.emit_borrowed(|| (**self).serialize(s)) + } } -pub fn deserialize_i16<D: Deserializer>(&&d: D) -> i16 { - d.read_i16() +pub impl<S: Serializer, T: Serializable<S>> ~T: Serializable<S> { + fn serialize(&self, s: &S) { + s.emit_owned(|| (**self).serialize(s)) + } } -pub fn serialize_i32<S: Serializer>(&&s: S, v: i32) { - s.emit_i32(v); +pub impl<D: Deserializer, T: Deserializable<D>> ~T: Deserializable<D> { + static fn deserialize(&self, d: &D) -> ~T { + d.read_owned(|| ~deserialize(d)) + } } -pub fn deserialize_i32<D: Deserializer>(&&d: D) -> i32 { - d.read_i32() +pub impl<S: Serializer, T: Serializable<S>> @T: Serializable<S> { + fn serialize(&self, s: &S) { + s.emit_managed(|| (**self).serialize(s)) + } } -pub fn serialize_i64<S: Serializer>(&&s: S, v: i64) { - s.emit_i64(v); +pub impl<D: Deserializer, T: Deserializable<D>> @T: Deserializable<D> { + static fn deserialize(&self, d: &D) -> @T { + d.read_managed(|| @deserialize(d)) + } } -pub fn deserialize_i64<D: Deserializer>(&&d: D) -> i64 { - d.read_i64() +pub impl<S: Serializer, T: Serializable<S>> &[T]: Serializable<S> { + fn serialize(&self, s: &S) { + do s.emit_borrowed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl<S: Serializer, T: Serializable<S>> ~[T]: Serializable<S> { + fn serialize(&self, s: &S) { + do s.emit_owned_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl<D: Deserializer, T: Deserializable<D>> ~[T]: Deserializable<D> { + static fn deserialize(&self, d: &D) -> ~[T] { + do d.read_owned_vec |len| { + do vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl<S: Serializer, T: Serializable<S>> @[T]: Serializable<S> { + fn serialize(&self, s: &S) { + do s.emit_managed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl<D: Deserializer, T: Deserializable<D>> @[T]: Deserializable<D> { + static fn deserialize(&self, d: &D) -> @[T] { + do d.read_managed_vec |len| { + do at_vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } } -pub fn serialize_str<S: Serializer>(&&s: S, v: &str) { - s.emit_str(v); +pub impl<S: Serializer, T: Serializable<S>> Option<T>: Serializable<S> { + fn serialize(&self, s: &S) { + do s.emit_enum(~"option") { + match *self { + None => do s.emit_enum_variant(~"none", 0u, 0u) { + }, + + Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { + s.emit_enum_variant_arg(0u, || v.serialize(s)) + } + } + } + } } -pub fn deserialize_str<D: Deserializer>(&&d: D) -> ~str { - d.read_str() +pub impl<D: Deserializer, T: Deserializable<D>> Option<T>: Deserializable<D> { + static fn deserialize(&self, d: &D) -> Option<T> { + do d.read_enum(~"option") { + do d.read_enum_variant |i| { + match i { + 0 => None, + 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), + _ => fail(#fmt("Bad variant for option: %u", i)) + } + } + } + } } -pub fn serialize_float<S: Serializer>(&&s: S, v: float) { - s.emit_float(v); +pub impl< + S: Serializer, + T0: Serializable<S>, + T1: Serializable<S> +> (T0, T1): Serializable<S> { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1) => { + do s.emit_tup(2) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + } + } + } + } } -pub fn deserialize_float<D: Deserializer>(&&d: D) -> float { - d.read_float() +pub impl< + D: Deserializer, + T0: Deserializable<D>, + T1: Deserializable<D> +> (T0, T1): Deserializable<D> { + static fn deserialize(&self, d: &D) -> (T0, T1) { + do d.read_tup(2) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)) + ) + } + } } -pub fn serialize_f32<S: Serializer>(&&s: S, v: f32) { - s.emit_f32(v); +pub impl< + S: Serializer, + T0: Serializable<S>, + T1: Serializable<S>, + T2: Serializable<S> +> (T0, T1, T2): Serializable<S> { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2) => { + do s.emit_tup(3) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + } + } + } + } } -pub fn deserialize_f32<D: Deserializer>(&&d: D) -> f32 { - d.read_f32() +pub impl< + D: Deserializer, + T0: Deserializable<D>, + T1: Deserializable<D>, + T2: Deserializable<D> +> (T0, T1, T2): Deserializable<D> { + static fn deserialize(&self, d: &D) -> (T0, T1, T2) { + do d.read_tup(3) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)) + ) + } + } } -pub fn serialize_f64<S: Serializer>(&&s: S, v: f64) { - s.emit_f64(v); +pub impl< + S: Serializer, + T0: Serializable<S>, + T1: Serializable<S>, + T2: Serializable<S>, + T3: Serializable<S> +> (T0, T1, T2, T3): Serializable<S> { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3) => { + do s.emit_tup(4) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + } + } + } + } } -pub fn deserialize_f64<D: Deserializer>(&&d: D) -> f64 { - d.read_f64() +pub impl< + D: Deserializer, + T0: Deserializable<D>, + T1: Deserializable<D>, + T2: Deserializable<D>, + T3: Deserializable<D> +> (T0, T1, T2, T3): Deserializable<D> { + static fn deserialize(&self, d: &D) -> (T0, T1, T2, T3) { + do d.read_tup(4) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)) + ) + } + } } -pub fn serialize_bool<S: Serializer>(&&s: S, v: bool) { - s.emit_bool(v); +pub impl< + S: Serializer, + T0: Serializable<S>, + T1: Serializable<S>, + T2: Serializable<S>, + T3: Serializable<S>, + T4: Serializable<S> +> (T0, T1, T2, T3, T4): Serializable<S> { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3, ref t4) => { + do s.emit_tup(5) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + s.emit_tup_elt(4, || t4.serialize(s)); + } + } + } + } } -pub fn deserialize_bool<D: Deserializer>(&&d: D) -> bool { - d.read_bool() +pub impl< + D: Deserializer, + T0: Deserializable<D>, + T1: Deserializable<D>, + T2: Deserializable<D>, + T3: Deserializable<D>, + T4: Deserializable<D> +> (T0, T1, T2, T3, T4): Deserializable<D> { + static fn deserialize(&self, d: &D) + -> (T0, T1, T2, T3, T4) { + do d.read_tup(5) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)), + d.read_tup_elt(4, || deserialize(d)) + ) + } + } } -pub fn serialize_Option<S: Serializer,T>(&&s: S, &&v: Option<T>, - st: fn(&&x: T)) { - do s.emit_enum(~"option") { - match v { - None => do s.emit_enum_variant(~"none", 0u, 0u) { - }, +// ___________________________________________________________________________ +// Helper routines +// +// In some cases, these should eventually be coded as traits. - Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { - do s.emit_enum_variant_arg(0u) { - st(*v) +pub trait SerializerHelpers { + fn emit_from_vec<T>(&self, v: ~[T], f: fn(v: &T)); +} + +pub impl<S: Serializer> S: SerializerHelpers { + fn emit_from_vec<T>(&self, v: ~[T], f: fn(v: &T)) { + do self.emit_owned_vec(v.len()) { + for v.eachi |i, e| { + do self.emit_vec_elt(i) { + f(e) + } } - } } } } -pub fn deserialize_Option<D: Deserializer,T: Copy>(&&d: D, st: fn() -> T) - -> Option<T> { - do d.read_enum(~"option") { - do d.read_enum_variant |i| { - match i { - 0 => None, - 1 => Some(d.read_enum_variant_arg(0u, || st() )), - _ => fail(#fmt("Bad variant for option: %u", i)) +pub trait DeserializerHelpers { + fn read_to_vec<T>(&self, f: fn() -> T) -> ~[T]; +} + +pub impl<D: Deserializer> D: DeserializerHelpers { + fn read_to_vec<T>(&self, f: fn() -> T) -> ~[T] { + do self.read_owned_vec |len| { + do vec::from_fn(len) |i| { + self.read_vec_elt(i, || f()) } } } } +} + +pub use traits::*; diff --git a/src/libstd/serialization2.rs b/src/libstd/serialization2.rs deleted file mode 100644 index 5173ef163a2..00000000000 --- a/src/libstd/serialization2.rs +++ /dev/null @@ -1,563 +0,0 @@ -//! Support code for serialization. - -/* -Core serialization interfaces. -*/ - -#[forbid(deprecated_mode)]; -#[forbid(non_camel_case_types)]; - -pub trait Serializer { - // Primitive types: - fn emit_nil(&self); - fn emit_uint(&self, v: uint); - fn emit_u64(&self, v: u64); - fn emit_u32(&self, v: u32); - fn emit_u16(&self, v: u16); - fn emit_u8(&self, v: u8); - fn emit_int(&self, v: int); - fn emit_i64(&self, v: i64); - fn emit_i32(&self, v: i32); - fn emit_i16(&self, v: i16); - fn emit_i8(&self, v: i8); - fn emit_bool(&self, v: bool); - fn emit_float(&self, v: float); - fn emit_f64(&self, v: f64); - fn emit_f32(&self, v: f32); - fn emit_char(&self, v: char); - fn emit_borrowed_str(&self, v: &str); - fn emit_owned_str(&self, v: &str); - fn emit_managed_str(&self, v: &str); - - // Compound types: - fn emit_borrowed(&self, f: fn()); - fn emit_owned(&self, f: fn()); - fn emit_managed(&self, f: fn()); - - fn emit_enum(&self, name: &str, f: fn()); - fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: fn()); - fn emit_enum_variant_arg(&self, idx: uint, f: fn()); - - fn emit_borrowed_vec(&self, len: uint, f: fn()); - fn emit_owned_vec(&self, len: uint, f: fn()); - fn emit_managed_vec(&self, len: uint, f: fn()); - fn emit_vec_elt(&self, idx: uint, f: fn()); - - fn emit_rec(&self, f: fn()); - fn emit_struct(&self, name: &str, f: fn()); - fn emit_field(&self, f_name: &str, f_idx: uint, f: fn()); - - fn emit_tup(&self, len: uint, f: fn()); - fn emit_tup_elt(&self, idx: uint, f: fn()); -} - -pub trait Deserializer { - // Primitive types: - fn read_nil(&self) -> (); - fn read_uint(&self) -> uint; - fn read_u64(&self) -> u64; - fn read_u32(&self) -> u32; - fn read_u16(&self) -> u16; - fn read_u8(&self) -> u8; - fn read_int(&self) -> int; - fn read_i64(&self) -> i64; - fn read_i32(&self) -> i32; - fn read_i16(&self) -> i16; - fn read_i8(&self) -> i8; - fn read_bool(&self) -> bool; - fn read_f64(&self) -> f64; - fn read_f32(&self) -> f32; - fn read_float(&self) -> float; - fn read_char(&self) -> char; - fn read_owned_str(&self) -> ~str; - fn read_managed_str(&self) -> @str; - - // Compound types: - fn read_enum<T>(&self, name: &str, f: fn() -> T) -> T; - fn read_enum_variant<T>(&self, f: fn(uint) -> T) -> T; - fn read_enum_variant_arg<T>(&self, idx: uint, f: fn() -> T) -> T; - - fn read_owned<T>(&self, f: fn() -> T) -> T; - fn read_managed<T>(&self, f: fn() -> T) -> T; - - fn read_owned_vec<T>(&self, f: fn(uint) -> T) -> T; - fn read_managed_vec<T>(&self, f: fn(uint) -> T) -> T; - fn read_vec_elt<T>(&self, idx: uint, f: fn() -> T) -> T; - - fn read_rec<T>(&self, f: fn() -> T) -> T; - fn read_struct<T>(&self, name: &str, f: fn() -> T) -> T; - fn read_field<T>(&self, name: &str, idx: uint, f: fn() -> T) -> T; - - fn read_tup<T>(&self, sz: uint, f: fn() -> T) -> T; - fn read_tup_elt<T>(&self, idx: uint, f: fn() -> T) -> T; -} - -pub trait Serializable { - fn serialize<S: Serializer>(&self, s: &S); -} - -pub trait Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> self; -} - -pub impl uint: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_uint(*self) } -} - -pub impl uint: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> uint { - d.read_uint() - } -} - -pub impl u8: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_u8(*self) } -} - -pub impl u8: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> u8 { - d.read_u8() - } -} - -pub impl u16: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_u16(*self) } -} - -pub impl u16: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> u16 { - d.read_u16() - } -} - -pub impl u32: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_u32(*self) } -} - -pub impl u32: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> u32 { - d.read_u32() - } -} - -pub impl u64: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_u64(*self) } -} - -pub impl u64: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> u64 { - d.read_u64() - } -} - -pub impl int: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_int(*self) } -} - -pub impl int: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> int { - d.read_int() - } -} - -pub impl i8: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_i8(*self) } -} - -pub impl i8: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> i8 { - d.read_i8() - } -} - -pub impl i16: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_i16(*self) } -} - -pub impl i16: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> i16 { - d.read_i16() - } -} - -pub impl i32: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_i32(*self) } -} - -pub impl i32: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> i32 { - d.read_i32() - } -} - -pub impl i64: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_i64(*self) } -} - -pub impl i64: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> i64 { - d.read_i64() - } -} - -pub impl &str: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_borrowed_str(*self) } -} - -pub impl ~str: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_owned_str(*self) } -} - -pub impl ~str: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> ~str { - d.read_owned_str() - } -} - -pub impl @str: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_managed_str(*self) } -} - -pub impl @str: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> @str { - d.read_managed_str() - } -} - -pub impl float: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_float(*self) } -} - -pub impl float: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> float { - d.read_float() - } -} - -pub impl f32: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_f32(*self) } -} - -pub impl f32: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> f32 { - d.read_f32() } -} - -pub impl f64: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_f64(*self) } -} - -pub impl f64: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> f64 { - d.read_f64() - } -} - -pub impl bool: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_bool(*self) } -} - -pub impl bool: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> bool { - d.read_bool() - } -} - -pub impl (): Serializable { - fn serialize<S: Serializer>(&self, s: &S) { s.emit_nil() } -} - -pub impl (): Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> () { - d.read_nil() - } -} - -pub impl<T: Serializable> &T: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - s.emit_borrowed(|| (**self).serialize(s)) - } -} - -pub impl<T: Serializable> ~T: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - s.emit_owned(|| (**self).serialize(s)) - } -} - -pub impl<T: Deserializable> ~T: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> ~T { - d.read_owned(|| ~deserialize(d)) - } -} - -pub impl<T: Serializable> @T: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - s.emit_managed(|| (**self).serialize(s)) - } -} - -pub impl<T: Deserializable> @T: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> @T { - d.read_managed(|| @deserialize(d)) - } -} - -pub impl<T: Serializable> &[T]: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - do s.emit_borrowed_vec(self.len()) { - for self.eachi |i, e| { - s.emit_vec_elt(i, || e.serialize(s)) - } - } - } -} - -pub impl<T: Serializable> ~[T]: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - do s.emit_owned_vec(self.len()) { - for self.eachi |i, e| { - s.emit_vec_elt(i, || e.serialize(s)) - } - } - } -} - -pub impl<T: Deserializable> ~[T]: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> ~[T] { - do d.read_owned_vec |len| { - do vec::from_fn(len) |i| { - d.read_vec_elt(i, || deserialize(d)) - } - } - } -} - -pub impl<T: Serializable> @[T]: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - do s.emit_managed_vec(self.len()) { - for self.eachi |i, e| { - s.emit_vec_elt(i, || e.serialize(s)) - } - } - } -} - -pub impl<T: Deserializable> @[T]: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> @[T] { - do d.read_managed_vec |len| { - do at_vec::from_fn(len) |i| { - d.read_vec_elt(i, || deserialize(d)) - } - } - } -} - -pub impl<T: Serializable> Option<T>: Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - do s.emit_enum(~"option") { - match *self { - None => do s.emit_enum_variant(~"none", 0u, 0u) { - }, - - Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { - s.emit_enum_variant_arg(0u, || v.serialize(s)) - } - } - } - } -} - -pub impl<T: Deserializable> Option<T>: Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> Option<T> { - do d.read_enum(~"option") { - do d.read_enum_variant |i| { - match i { - 0 => None, - 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), - _ => fail(#fmt("Bad variant for option: %u", i)) - } - } - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable -> (T0, T1): Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - match *self { - (ref t0, ref t1) => { - do s.emit_tup(2) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable -> (T0, T1): Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> (T0, T1) { - do d.read_tup(2) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)) - ) - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable, - T2: Serializable -> (T0, T1, T2): Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - match *self { - (ref t0, ref t1, ref t2) => { - do s.emit_tup(3) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - s.emit_tup_elt(2, || t2.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable, - T2: Deserializable -> (T0, T1, T2): Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> (T0, T1, T2) { - do d.read_tup(3) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)), - d.read_tup_elt(2, || deserialize(d)) - ) - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable, - T2: Serializable, - T3: Serializable -> (T0, T1, T2, T3): Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - match *self { - (ref t0, ref t1, ref t2, ref t3) => { - do s.emit_tup(4) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - s.emit_tup_elt(2, || t2.serialize(s)); - s.emit_tup_elt(3, || t3.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable, - T2: Deserializable, - T3: Deserializable -> (T0, T1, T2, T3): Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) -> (T0, T1, T2, T3) { - do d.read_tup(4) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)), - d.read_tup_elt(2, || deserialize(d)), - d.read_tup_elt(3, || deserialize(d)) - ) - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable, - T2: Serializable, - T3: Serializable, - T4: Serializable -> (T0, T1, T2, T3, T4): Serializable { - fn serialize<S: Serializer>(&self, s: &S) { - match *self { - (ref t0, ref t1, ref t2, ref t3, ref t4) => { - do s.emit_tup(5) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - s.emit_tup_elt(2, || t2.serialize(s)); - s.emit_tup_elt(3, || t3.serialize(s)); - s.emit_tup_elt(4, || t4.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable, - T2: Deserializable, - T3: Deserializable, - T4: Deserializable -> (T0, T1, T2, T3, T4): Deserializable { - static fn deserialize<D: Deserializer>(&self, d: &D) - -> (T0, T1, T2, T3, T4) { - do d.read_tup(5) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)), - d.read_tup_elt(2, || deserialize(d)), - d.read_tup_elt(3, || deserialize(d)), - d.read_tup_elt(4, || deserialize(d)) - ) - } - } -} - -// ___________________________________________________________________________ -// Helper routines -// -// In some cases, these should eventually be coded as traits. - -pub trait SerializerHelpers { - fn emit_from_vec<T>(&self, v: &[T], f: fn(&T)); -} - -pub impl<S: Serializer> S: SerializerHelpers { - fn emit_from_vec<T>(&self, v: &[T], f: fn(&T)) { - do self.emit_owned_vec(v.len()) { - for v.eachi |i, e| { - do self.emit_vec_elt(i) { - f(e) - } - } - } - } -} - -pub trait DeserializerHelpers { - fn read_to_vec<T>(&self, f: fn() -> T) -> ~[T]; -} - -pub impl<D: Deserializer> D: DeserializerHelpers { - fn read_to_vec<T>(&self, f: fn() -> T) -> ~[T] { - do self.read_owned_vec |len| { - do vec::from_fn(len) |i| { - self.read_vec_elt(i, || f()) - } - } - } -} diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 98f98fe7fce..946a3e1155d 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -899,7 +899,7 @@ mod test_qsort { do sort::quick_sort(names) |x, y| { int::le(*x, *y) }; - let immut_names = vec::from_mut(names); + let immut_names = vec::from_mut(move names); let pairs = vec::zip(expected, immut_names); for vec::each(pairs) |p| { diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 7fc3004bbcf..bbffde40948 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -8,7 +8,7 @@ not required in or otherwise suitable for the core library. */ #[link(name = "std", - vers = "0.4", + vers = "0.5", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; @@ -25,7 +25,7 @@ not required in or otherwise suitable for the core library. #[allow(deprecated_mode)]; #[forbid(deprecated_pattern)]; -extern mod core(vers = "0.4"); +extern mod core(vers = "0.5"); use core::*; // General io and system-services modules @@ -69,7 +69,6 @@ pub mod treemap; // And ... other stuff pub mod ebml; -pub mod ebml2; pub mod dbg; pub mod getopts; pub mod json; @@ -79,7 +78,6 @@ pub mod tempfile; pub mod term; pub mod time; pub mod prettyprint; -pub mod prettyprint2; pub mod arena; pub mod par; pub mod cmp; @@ -93,7 +91,6 @@ mod unicode; pub mod test; pub mod serialization; -pub mod serialization2; // Local Variables: // mode: rust; diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 908f3936f4e..73fc78a091a 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -25,7 +25,7 @@ struct Waitqueue { head: pipes::Port<SignalEnd>, fn new_waitqueue() -> Waitqueue { let (block_tail, block_head) = pipes::stream(); - Waitqueue { head: block_head, tail: block_tail } + Waitqueue { head: move block_head, tail: move block_tail } } // Signals one live task from the queue. @@ -71,7 +71,7 @@ enum Sem<Q: Send> = Exclusive<SemInner<Q>>; #[doc(hidden)] fn new_sem<Q: Send>(count: int, q: Q) -> Sem<Q> { Sem(exclusive(SemInner { - mut count: count, waiters: new_waitqueue(), blocked: q })) + mut count: count, waiters: new_waitqueue(), blocked: move q })) } #[doc(hidden)] fn new_sem_and_signal(count: int, num_condvars: uint) @@ -146,7 +146,7 @@ impl &Sem<~[mut Waitqueue]> { } } -// FIXME(#3136) should go inside of access() +// FIXME(#3588) should go inside of access() #[doc(hidden)] struct SemRelease { sem: &Sem<()>, @@ -577,7 +577,7 @@ impl &RWlock { } } -// FIXME(#3136) should go inside of read() +// FIXME(#3588) should go inside of read() #[doc(hidden)] struct RWlockReleaseRead { lock: &RWlock, @@ -606,7 +606,7 @@ fn RWlockReleaseRead(lock: &r/RWlock) -> RWlockReleaseRead/&r { } } -// FIXME(#3136) should go inside of downgrade() +// FIXME(#3588) should go inside of downgrade() #[doc(hidden)] struct RWlockReleaseDowngrade { lock: &RWlock, @@ -686,7 +686,7 @@ mod tests { fn test_sem_as_mutex() { let s = ~semaphore(1); let s2 = ~s.clone(); - do task::spawn { + do task::spawn |move s2| { do s2.access { for 5.times { task::yield(); } } @@ -701,7 +701,7 @@ mod tests { let (c,p) = pipes::stream(); let s = ~semaphore(0); let s2 = ~s.clone(); - do task::spawn { + do task::spawn |move s2, move c| { s2.acquire(); c.send(()); } @@ -713,7 +713,7 @@ mod tests { let (c,p) = pipes::stream(); let s = ~semaphore(0); let s2 = ~s.clone(); - do task::spawn { + do task::spawn |move s2, move p| { for 5.times { task::yield(); } s2.release(); let _ = p.recv(); @@ -729,7 +729,7 @@ mod tests { let s2 = ~s.clone(); let (c1,p1) = pipes::stream(); let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move s2, move c1, move p2| { do s2.access { let _ = p2.recv(); c1.send(()); @@ -748,10 +748,10 @@ mod tests { let s = ~semaphore(1); let s2 = ~s.clone(); let (c,p) = pipes::stream(); - let child_data = ~mut Some((s2,c)); + let child_data = ~mut Some((move s2, move c)); do s.access { let (s2,c) = option::swap_unwrap(child_data); - do task::spawn { + do task::spawn |move c, move s2| { c.send(()); do s2.access { } c.send(()); @@ -774,7 +774,7 @@ mod tests { let m2 = ~m.clone(); let mut sharedstate = ~0; let ptr = ptr::addr_of(&(*sharedstate)); - do task::spawn { + do task::spawn |move m2, move c| { let sharedstate: &mut int = unsafe { cast::reinterpret_cast(&ptr) }; access_shared(sharedstate, m2, 10); @@ -803,7 +803,7 @@ mod tests { // Child wakes up parent do m.lock_cond |cond| { let m2 = ~m.clone(); - do task::spawn { + do task::spawn |move m2| { do m2.lock_cond |cond| { let woken = cond.signal(); assert woken; @@ -814,7 +814,7 @@ mod tests { // Parent wakes up child let (chan,port) = pipes::stream(); let m3 = ~m.clone(); - do task::spawn { + do task::spawn |move chan, move m3| { do m3.lock_cond |cond| { chan.send(()); cond.wait(); @@ -836,8 +836,8 @@ mod tests { for num_waiters.times { let mi = ~m.clone(); let (chan, port) = pipes::stream(); - ports.push(port); - do task::spawn { + ports.push(move port); + do task::spawn |move chan, move mi| { do mi.lock_cond |cond| { chan.send(()); cond.wait(); @@ -867,7 +867,7 @@ mod tests { fn test_mutex_cond_no_waiter() { let m = ~Mutex(); let m2 = ~m.clone(); - do task::try { + do task::try |move m| { do m.lock_cond |_x| { } }; do m2.lock_cond |cond| { @@ -880,7 +880,7 @@ mod tests { let m = ~Mutex(); let m2 = ~m.clone(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move m2| { do m2.lock { fail; } @@ -896,9 +896,9 @@ mod tests { let m = ~Mutex(); let m2 = ~m.clone(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move m2| { let (c,p) = pipes::stream(); - do task::spawn { // linked + do task::spawn |move p| { // linked let _ = p.recv(); // wait for sibling to get in the mutex task::yield(); fail; @@ -921,19 +921,19 @@ mod tests { let m2 = ~m.clone(); let (c,p) = pipes::stream(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move c, move m2| { let mut sibling_convos = ~[]; for 2.times { let (c,p) = pipes::stream(); - let c = ~mut Some(c); - sibling_convos.push(p); + let c = ~mut Some(move c); + sibling_convos.push(move p); let mi = ~m2.clone(); // spawn sibling task - do task::spawn { // linked + do task::spawn |move mi, move c| { // linked do mi.lock_cond |cond| { let c = option::swap_unwrap(c); c.send(()); // tell sibling to go ahead - let _z = SendOnFailure(c); + let _z = SendOnFailure(move c); cond.wait(); // block forever } } @@ -942,7 +942,7 @@ mod tests { let _ = p.recv(); // wait for sibling to get in the mutex } do m2.lock { } - c.send(sibling_convos); // let parent wait on all children + c.send(move sibling_convos); // let parent wait on all children fail; }; assert result.is_err(); @@ -959,7 +959,7 @@ mod tests { fn SendOnFailure(c: pipes::Chan<()>) -> SendOnFailure { SendOnFailure { - c: c + c: move c } } } @@ -969,7 +969,7 @@ mod tests { let m = ~Mutex(); do m.lock_cond |cond| { let m2 = ~m.clone(); - do task::spawn { + do task::spawn |move m2| { do m2.lock_cond |cond| { cond.signal_on(0); } @@ -983,7 +983,7 @@ mod tests { let m = ~mutex_with_condvars(2); let m2 = ~m.clone(); let (c,p) = pipes::stream(); - do task::spawn { + do task::spawn |move m2, move c| { do m2.lock_cond |cond| { c.send(()); cond.wait_on(1); @@ -1032,7 +1032,7 @@ mod tests { }, DowngradeRead => do x.write_downgrade |mode| { - let mode = x.downgrade(mode); + let mode = x.downgrade(move mode); (&mode).read(blk); }, } @@ -1046,7 +1046,7 @@ mod tests { let x2 = ~x.clone(); let mut sharedstate = ~0; let ptr = ptr::addr_of(&(*sharedstate)); - do task::spawn { + do task::spawn |move c, move x2| { let sharedstate: &mut int = unsafe { cast::reinterpret_cast(&ptr) }; access_shared(sharedstate, x2, mode1, 10); @@ -1089,7 +1089,7 @@ mod tests { let x2 = ~x.clone(); let (c1,p1) = pipes::stream(); let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move c1, move x2, move p2| { if !make_mode2_go_first { let _ = p2.recv(); // parent sends to us once it locks, or ... } @@ -1126,10 +1126,10 @@ mod tests { // Tests that downgrade can unlock the lock in both modes let x = ~RWlock(); do lock_rwlock_in_mode(x, Downgrade) { } - test_rwlock_handshake(x, Read, Read, false); + test_rwlock_handshake(move x, Read, Read, false); let y = ~RWlock(); do lock_rwlock_in_mode(y, DowngradeRead) { } - test_rwlock_exclusion(y, Write, Write); + test_rwlock_exclusion(move y, Write, Write); } #[test] fn test_rwlock_read_recursive() { @@ -1144,7 +1144,7 @@ mod tests { // Child wakes up parent do x.write_cond |cond| { let x2 = ~x.clone(); - do task::spawn { + do task::spawn |move x2| { do x2.write_cond |cond| { let woken = cond.signal(); assert woken; @@ -1155,7 +1155,7 @@ mod tests { // Parent wakes up child let (chan,port) = pipes::stream(); let x3 = ~x.clone(); - do task::spawn { + do task::spawn |move x3, move chan| { do x3.write_cond |cond| { chan.send(()); cond.wait(); @@ -1190,8 +1190,8 @@ mod tests { for num_waiters.times { let xi = ~x.clone(); let (chan, port) = pipes::stream(); - ports.push(port); - do task::spawn { + ports.push(move port); + do task::spawn |move chan, move xi| { do lock_cond(xi, dg1) |cond| { chan.send(()); cond.wait(); @@ -1226,7 +1226,7 @@ mod tests { let x = ~RWlock(); let x2 = ~x.clone(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move x2| { do lock_rwlock_in_mode(x2, mode1) { fail; } @@ -1264,7 +1264,7 @@ mod tests { let x = ~RWlock(); let y = ~RWlock(); do x.write_downgrade |xwrite| { - let mut xopt = Some(xwrite); + let mut xopt = Some(move xwrite); do y.write_downgrade |_ywrite| { y.downgrade(option::swap_unwrap(&mut xopt)); error!("oops, y.downgrade(x) should have failed!"); diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 9790622332a..a10997d7c35 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -130,7 +130,7 @@ pub fn run_tests_console(opts: &TestOpts, st.failed += 1u; write_failed(st.out, st.use_color); st.out.write_line(~""); - st.failures.push(test); + st.failures.push(move test); } TrIgnored => { st.ignored += 1u; @@ -249,7 +249,7 @@ fn should_sort_failures_before_printing_them() { mut passed: 0u, mut failed: 0u, mut ignored: 0u, - mut failures: ~[test_b, test_a]}; + mut failures: ~[move test_b, move test_a]}; print_failures(st); }; @@ -534,9 +534,9 @@ mod tests { for vec::each(names) |name| { let test = {name: *name, testfn: copy testfn, ignore: false, should_fail: false}; - tests.push(test); + tests.push(move test); } - tests + move tests }; let filtered = filter_tests(&opts, tests); @@ -549,7 +549,7 @@ mod tests { ~"test::parse_ignored_flag", ~"test::sort_tests"]; - let pairs = vec::zip(expected, filtered); + let pairs = vec::zip(expected, move filtered); for vec::each(pairs) |p| { match *p { diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 65872a013ab..75909273392 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -595,8 +595,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> { fn strftime(format: &str, tm: Tm) -> ~str { fn parse_type(ch: char, tm: &Tm) -> ~str { //FIXME (#2350): Implement missing types. - let die = || #fmt("strftime: can't understand this format %c ", - ch); + let die = || fmt!("strftime: can't understand this format %c ", ch); match ch { 'A' => match tm.tm_wday as int { 0 => ~"Sunday", diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index c9c28c4e1f0..199fba45914 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -23,7 +23,7 @@ use comm = core::comm; * * ch - a channel of type T to send a `val` on * * val - a value of type T to send over the provided `ch` */ -pub fn delayed_send<T: Copy Send>(iotask: IoTask, +pub fn delayed_send<T: Send>(iotask: IoTask, msecs: uint, ch: comm::Chan<T>, val: T) { unsafe { let timer_done_po = core::comm::Port::<()>(); @@ -55,7 +55,7 @@ pub fn delayed_send<T: Copy Send>(iotask: IoTask, // delayed_send_cb has been processed by libuv core::comm::recv(timer_done_po); // notify the caller immediately - core::comm::send(ch, copy(val)); + core::comm::send(ch, move(val)); // uv_close for this timer has been processed core::comm::recv(timer_done_po); }; diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 8ab0dc7f2e7..e4b6c9b5b9a 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -11,28 +11,28 @@ use core::cmp::{Eq, Ord}; use core::option::{Some, None}; use Option = core::Option; -pub type TreeMap<K, V> = @mut TreeEdge<K, V>; +pub type TreeMap<K: Copy Eq Ord, V: Copy> = @mut TreeEdge<K, V>; -type TreeEdge<K, V> = Option<@TreeNode<K, V>>; +type TreeEdge<K: Copy Eq Ord, V: Copy> = Option<@TreeNode<K, V>>; -enum TreeNode<K, V> = { +struct TreeNode<K: Copy Eq Ord, V: Copy> { key: K, mut value: V, mut left: TreeEdge<K, V>, mut right: TreeEdge<K, V> -}; +} /// Create a treemap -pub fn TreeMap<K, V>() -> TreeMap<K, V> { @mut None } +pub fn TreeMap<K: Copy Eq Ord, V: Copy>() -> TreeMap<K, V> { @mut None } /// Insert a value into the map pub fn insert<K: Copy Eq Ord, V: Copy>(m: &mut TreeEdge<K, V>, k: K, v: V) { match copy *m { None => { - *m = Some(@TreeNode({key: k, - mut value: v, - mut left: None, - mut right: None})); + *m = Some(@TreeNode {key: k, + mut value: v, + mut left: None, + mut right: None}); return; } Some(node) => { @@ -67,7 +67,8 @@ pub fn find<K: Copy Eq Ord, V: Copy>(m: &const TreeEdge<K, V>, k: K) } /// Visit all pairs in the map in order. -pub fn traverse<K, V: Copy>(m: &const TreeEdge<K, V>, f: fn((&K), (&V))) { +pub fn traverse<K: Copy Eq Ord, V: Copy>(m: &const TreeEdge<K, V>, + f: fn((&K), (&V))) { match copy *m { None => (), Some(node) => { @@ -79,6 +80,19 @@ pub fn traverse<K, V: Copy>(m: &const TreeEdge<K, V>, f: fn((&K), (&V))) { } } +/// Compare two treemaps and return true iff +/// they contain same keys and values +pub fn equals<K: Copy Eq Ord, V: Copy Eq>(t1: &const TreeEdge<K, V>, + t2: &const TreeEdge<K, V>) + -> bool { + let mut v1 = ~[]; + let mut v2 = ~[]; + traverse(t1, |k,v| { v1.push((copy *k, copy *v)) }); + traverse(t2, |k,v| { v2.push((copy *k, copy *v)) }); + return v1 == v2; +} + + #[cfg(test)] mod tests { #[legacy_exports]; @@ -128,6 +142,28 @@ mod tests { } #[test] + fn equality() { + let m1 = TreeMap(); + insert(m1, 3, ()); + insert(m1, 0, ()); + insert(m1, 4, ()); + insert(m1, 2, ()); + insert(m1, 1, ()); + let m2 = TreeMap(); + insert(m2, 2, ()); + insert(m2, 1, ()); + insert(m2, 3, ()); + insert(m2, 0, ()); + insert(m2, 4, ()); + + assert equals(m1, m2); + + let m3 = TreeMap(); + assert !equals(m1,m3); + + } + + #[test] fn u8_map() { let m = TreeMap(); diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index f8c3882d15e..8bf4e9ed3af 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -590,6 +590,8 @@ extern mod rustrt { -> libc::c_int; fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: libc::size_t) -> libc::c_int; + fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint; + fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint; // FIXME ref #2064 fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, @@ -606,6 +608,10 @@ extern mod rustrt { // FIXME ref #2064 fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, ++addr: *sockaddr_in6) -> libc::c_int; + fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + ++name: *sockaddr_in) -> libc::c_int; + fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + ++name: *sockaddr_in6) ->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) @@ -736,6 +742,16 @@ pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr); } +pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in) -> libc::c_int { + return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name); +} + +pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in6) ->libc::c_int { + return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name); +} + pub unsafe fn listen<T>(stream: *T, backlog: libc::c_int, cb: *u8) -> libc::c_int { return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb); @@ -857,6 +873,12 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str { } } } +pub unsafe fn ip4_port(src: &sockaddr_in) -> uint { + rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint +} +pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint { + rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint +} pub unsafe fn timer_init(loop_ptr: *libc::c_void, timer_ptr: *uv_timer_t) -> libc::c_int { @@ -1048,7 +1070,7 @@ pub mod test { as *request_wrapper; let buf_base = get_base_from_buf(buf); let buf_len = get_len_from_buf(buf); - let bytes = vec::raw::from_buf(buf_base, buf_len as uint); + let bytes = vec::from_buf(buf_base, buf_len as uint); let read_chan = *((*client_data).read_chan); let msg_from_server = str::from_bytes(bytes); core::comm::send(read_chan, msg_from_server); @@ -1223,7 +1245,7 @@ pub mod test { buf_base as uint, buf_len as uint, nread)); - let bytes = vec::raw::from_buf(buf_base, buf_len); + let bytes = vec::from_buf(buf_base, buf_len); let request_str = str::from_bytes(bytes); let client_data = get_data_for_uv_handle( @@ -1462,7 +1484,7 @@ pub mod test { fn impl_uv_tcp_server_and_request() unsafe { let bind_ip = ~"0.0.0.0"; let request_ip = ~"127.0.0.1"; - let port = 8887; + let port = 8886; let kill_server_msg = ~"does a dog have buddha nature?"; let server_resp_msg = ~"mu!"; let client_port = core::comm::Port::<~str>(); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a50189cf598..a3d2fe96b5d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1,33 +1,14 @@ // The Rust abstract syntax tree. +use std::serialization::{Serializable, + Deserializable, + Serializer, + Deserializer}; use codemap::{span, filename}; -use std::serialization::{Serializer, - Deserializer, - serialize_Option, - deserialize_Option, - serialize_uint, - deserialize_uint, - serialize_int, - deserialize_int, - serialize_i64, - deserialize_i64, - serialize_u64, - deserialize_u64, - serialize_str, - deserialize_str, - serialize_bool, - deserialize_bool}; use parse::token; -/* Note #1972 -- spans are serialized but not deserialized */ -fn serialize_span<S>(_s: S, _v: span) { -} - -fn deserialize_span<D>(_d: D) -> span { - ast_util::dummy_sp() -} - #[auto_serialize] +#[auto_deserialize] type spanned<T> = {node: T, span: span}; @@ -42,25 +23,62 @@ macro_rules! interner_key ( // implemented. struct ident { repr: uint } -fn serialize_ident<S: Serializer>(s: S, i: ident) { - let intr = match unsafe{ - task::local_data::local_data_get(interner_key!()) - } { - None => fail ~"serialization: TLS interner not set up", - Some(intr) => intr - }; +#[cfg(stage0)] +impl ident: Serializable { + fn serialize<S: Serializer>(&self, s: &S) { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"serialization: TLS interner not set up", + Some(intr) => intr + }; + + s.emit_owned_str(*(*intr).get(*self)); + } +} + +#[cfg(stage0)] +impl ident: Deserializable { + static fn deserialize<D: Deserializer>(d: &D) -> ident { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"deserialization: TLS interner not set up", + Some(intr) => intr + }; - s.emit_str(*(*intr).get(i)); + (*intr).intern(@d.read_owned_str()) + } } -fn deserialize_ident<D: Deserializer>(d: D) -> ident { - let intr = match unsafe{ - task::local_data::local_data_get(interner_key!()) - } { - None => fail ~"deserialization: TLS interner not set up", - Some(intr) => intr - }; - (*intr).intern(@d.read_str()) +#[cfg(stage1)] +#[cfg(stage2)] +impl<S: Serializer> ident: Serializable<S> { + fn serialize(&self, s: &S) { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"serialization: TLS interner not set up", + Some(intr) => intr + }; + + s.emit_owned_str(*(*intr).get(*self)); + } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl<D: Deserializer> ident: Deserializable<D> { + static fn deserialize(d: &D) -> ident { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"deserialization: TLS interner not set up", + Some(intr) => intr + }; + + (*intr).intern(@d.read_owned_str()) + } } impl ident: cmp::Eq { @@ -75,23 +93,22 @@ impl ident: to_bytes::IterBytes { } // Functions may or may not have names. -#[auto_serialize] type fn_ident = Option<ident>; #[auto_serialize] +#[auto_deserialize] type path = {span: span, global: bool, idents: ~[ident], rp: Option<@region>, - types: ~[@ty]}; + types: ~[@Ty]}; -#[auto_serialize] type crate_num = int; -#[auto_serialize] type node_id = int; #[auto_serialize] +#[auto_deserialize] type def_id = {crate: crate_num, node: node_id}; impl def_id : cmp::Eq { @@ -105,21 +122,24 @@ const local_crate: crate_num = 0; const crate_node_id: node_id = 0; #[auto_serialize] -enum ty_param_bound { - bound_copy, - bound_send, - bound_const, - bound_owned, - bound_trait(@ty), -} +#[auto_deserialize] +// The AST represents all type param bounds as types. +// typeck::collect::compute_bounds matches these against +// the "special" built-in traits (see middle::lang_items) and +// detects Copy, Send, Owned, and Const. +enum ty_param_bound = @Ty; #[auto_serialize] +#[auto_deserialize] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_serialize] +#[auto_deserialize] enum def { def_fn(def_id, purity), - def_static_method(def_id, purity), + def_static_method(/* method */ def_id, + /* trait */ Option<def_id>, + purity), def_self(node_id), def_mod(def_id), def_foreign_mod(def_id), @@ -136,7 +156,7 @@ enum def { @def, // closed over def node_id, // expr node that creates the closure node_id), // id for the block/body of the closure expr - def_class(def_id, bool /* has constructor */), + def_class(def_id), def_typaram_binder(node_id), /* class, impl or trait that has ty params */ def_region(node_id), def_label(node_id) @@ -151,9 +171,10 @@ impl def : cmp::Eq { _ => false } } - def_static_method(e0a, e1a) => { + def_static_method(e0a, e1a, e2a) => { match (*other) { - def_static_method(e0b, e1b) => e0a == e0b && e1a == e1b, + def_static_method(e0b, e1b, e2b) => + e0a == e0b && e1a == e1b && e2a == e2b, _ => false } } @@ -236,9 +257,9 @@ impl def : cmp::Eq { _ => false } } - def_class(e0a, e1a) => { + def_class(e0a) => { match (*other) { - def_class(e0b, e1b) => e0a == e0b && e1a == e1b, + def_class(e0b) => e0a == e0b, _ => false } } @@ -293,20 +314,20 @@ enum crate_directive_ { type crate_directive = spanned<crate_directive_>; -#[auto_serialize] type meta_item = spanned<meta_item_>; #[auto_serialize] +#[auto_deserialize] enum meta_item_ { meta_word(~str), meta_list(~str, ~[@meta_item]), meta_name_value(~str, lit), } -#[auto_serialize] type blk = spanned<blk_>; #[auto_serialize] +#[auto_deserialize] type blk_ = {view_items: ~[@view_item], stmts: ~[@stmt], expr: Option<@expr>, @@ -314,12 +335,15 @@ type blk_ = {view_items: ~[@view_item], rules: blk_check_mode}; #[auto_serialize] +#[auto_deserialize] type pat = {id: node_id, node: pat_, span: span}; #[auto_serialize] +#[auto_deserialize] type field_pat = {ident: ident, pat: @pat}; #[auto_serialize] +#[auto_deserialize] enum binding_mode { bind_by_value, bind_by_move, @@ -376,6 +400,7 @@ impl binding_mode : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -399,6 +424,7 @@ enum pat_ { } #[auto_serialize] +#[auto_deserialize] enum mutability { m_mutbl, m_imm, m_const, } impl mutability : to_bytes::IterBytes { @@ -415,6 +441,7 @@ impl mutability : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum proto { proto_bare, // foreign fn proto_uniq, // fn~ @@ -430,18 +457,20 @@ impl proto : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum vstore { - // FIXME (#2112): Change uint to @expr (actually only constant exprs) - vstore_fixed(Option<uint>), // [1,2,3,4]/_ or 4 + // FIXME (#3469): Change uint to @expr (actually only constant exprs) + vstore_fixed(Option<uint>), // [1,2,3,4] vstore_uniq, // ~[1,2,3,4] vstore_box, // @[1,2,3,4] vstore_slice(@region) // &[1,2,3,4](foo)? } #[auto_serialize] +#[auto_deserialize] enum expr_vstore { - // FIXME (#2112): Change uint to @expr (actually only constant exprs) - expr_vstore_fixed(Option<uint>), // [1,2,3,4]/_ or 4 + // FIXME (#3469): Change uint to @expr (actually only constant exprs) + expr_vstore_fixed(Option<uint>), // [1,2,3,4] expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_box, // @[1,2,3,4] expr_vstore_slice // &[1,2,3,4] @@ -455,6 +484,7 @@ pure fn is_blockish(p: ast::proto) -> bool { } #[auto_serialize] +#[auto_deserialize] enum binop { add, subtract, @@ -484,6 +514,7 @@ impl binop : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum unop { box(mutability), uniq(mutability), @@ -535,6 +566,7 @@ impl unop : cmp::Eq { // Generally, after typeck you can get the inferred value // using ty::resolved_T(...). #[auto_serialize] +#[auto_deserialize] enum inferable<T> { expl(T), infer(node_id) @@ -574,6 +606,7 @@ impl<T:cmp::Eq> inferable<T> : cmp::Eq { // "resolved" mode: the real modes. #[auto_serialize] +#[auto_deserialize] enum rmode { by_ref, by_val, by_move, by_copy } impl rmode : to_bytes::IterBytes { @@ -591,13 +624,12 @@ impl rmode : cmp::Eq { } // inferable mode. -#[auto_serialize] type mode = inferable<rmode>; -#[auto_serialize] type stmt = spanned<stmt_>; #[auto_serialize] +#[auto_deserialize] enum stmt_ { stmt_decl(@decl, node_id), @@ -609,6 +641,7 @@ enum stmt_ { } #[auto_serialize] +#[auto_deserialize] enum init_op { init_assign, init_move, } impl init_op : cmp::Eq { @@ -632,33 +665,36 @@ impl init_op : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. #[auto_serialize] -type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, +#[auto_deserialize] +type local_ = {is_mutbl: bool, ty: @Ty, pat: @pat, init: Option<initializer>, id: node_id}; -#[auto_serialize] type local = spanned<local_>; -#[auto_serialize] type decl = spanned<decl_>; #[auto_serialize] +#[auto_deserialize] enum decl_ { decl_local(~[@local]), decl_item(@item), } #[auto_serialize] +#[auto_deserialize] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; #[auto_serialize] +#[auto_deserialize] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; -#[auto_serialize] type field = spanned<field_>; #[auto_serialize] +#[auto_deserialize] enum blk_check_mode { default_blk, unsafe_blk, } impl blk_check_mode : cmp::Eq { @@ -674,17 +710,17 @@ impl blk_check_mode : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary #[auto_serialize] +#[auto_deserialize] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other #[auto_serialize] -enum alt_mode { alt_check, alt_exhaustive, } - -#[auto_serialize] +#[auto_deserialize] enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -694,7 +730,7 @@ enum expr_ { expr_binary(binop, @expr, @expr), expr_unary(unop, @expr), expr_lit(@lit), - expr_cast(@expr, @ty), + expr_cast(@expr, @Ty), expr_if(@expr, blk, Option<@expr>), expr_while(@expr, blk), /* Conditionless loop (can be exited with break, cont, ret, or fail) @@ -718,7 +754,7 @@ enum expr_ { expr_assign(@expr, @expr), expr_swap(@expr, @expr), expr_assign_op(binop, @expr, @expr), - expr_field(@expr, ident, ~[@ty]), + expr_field(@expr, ident, ~[@Ty]), expr_index(@expr, @expr), expr_path(@path), expr_addr_of(mutability, @expr), @@ -741,14 +777,16 @@ enum expr_ { } #[auto_serialize] -type capture_item = @{ +#[auto_deserialize] +type capture_item_ = { id: int, is_move: bool, name: ident, // Currently, can only capture a local var. span: span }; -#[auto_serialize] +type capture_item = @capture_item_; + type capture_clause = @~[capture_item]; // @@ -768,12 +806,13 @@ type capture_clause = @~[capture_item]; // error. // #[auto_serialize] +#[auto_deserialize] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { - tt_tok(span, token::token), + tt_tok(span, token::Token), tt_delim(~[token_tree]), // These only make sense for right-hand-sides of MBE macros - tt_seq(span, ~[token_tree], Option<token::token>, bool), + tt_seq(span, ~[token_tree], Option<token::Token>, bool), tt_nonterminal(span, ident) } @@ -829,33 +868,32 @@ enum token_tree { // If you understand that, you have closed to loop and understand the whole // macro system. Congratulations. // -#[auto_serialize] type matcher = spanned<matcher_>; #[auto_serialize] +#[auto_deserialize] enum matcher_ { // match one token - match_tok(token::token), + match_tok(token::Token), // match repetitions of a sequence: body, separator, zero ok?, // lo, hi position-in-match-array used: - match_seq(~[matcher], Option<token::token>, bool, uint, uint), + match_seq(~[matcher], Option<token::Token>, bool, uint, uint), // parse a Rust NT: name to bind, name of NT, position in match array: match_nonterminal(ident, ident, uint) } -#[auto_serialize] type mac = spanned<mac_>; -#[auto_serialize] type mac_arg = Option<@expr>; #[auto_serialize] +#[auto_deserialize] type mac_body_ = {span: span}; -#[auto_serialize] type mac_body = Option<mac_body_>; #[auto_serialize] +#[auto_deserialize] enum mac_ { mac_invoc(@path, mac_arg, mac_body), // old macro-invocation mac_invoc_tt(@path,~[token_tree]), // new macro-invocation @@ -866,10 +904,10 @@ enum mac_ { mac_var(uint) } -#[auto_serialize] type lit = spanned<lit_>; #[auto_serialize] +#[auto_deserialize] enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -911,20 +949,23 @@ impl ast::lit_: cmp::Eq { // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. #[auto_serialize] -type mt = {ty: @ty, mutbl: mutability}; +#[auto_deserialize] +type mt = {ty: @Ty, mutbl: mutability}; #[auto_serialize] +#[auto_deserialize] type ty_field_ = {ident: ident, mt: mt}; -#[auto_serialize] type ty_field = spanned<ty_field_>; #[auto_serialize] +#[auto_deserialize] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; #[auto_serialize] +#[auto_deserialize] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -934,6 +975,7 @@ enum trait_method { } #[auto_serialize] +#[auto_deserialize] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl int_ty : to_bytes::IterBytes { @@ -963,6 +1005,7 @@ impl int_ty : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl uint_ty : to_bytes::IterBytes { @@ -990,6 +1033,7 @@ impl uint_ty : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum float_ty { ty_f, ty_f32, ty_f64, } impl float_ty : to_bytes::IterBytes { @@ -1008,10 +1052,12 @@ impl float_ty : cmp::Eq { } #[auto_serialize] -type ty = {id: node_id, node: ty_, span: span}; +#[auto_deserialize] +type Ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. #[auto_serialize] +#[auto_deserialize] enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -1059,9 +1105,11 @@ impl prim_ty : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] type region = {id: node_id, node: region_}; #[auto_serialize] +#[auto_deserialize] enum region_ { re_anon, re_static, @@ -1070,6 +1118,7 @@ enum region_ { } #[auto_serialize] +#[auto_deserialize] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1080,9 +1129,9 @@ enum ty_ { ty_rptr(@region, mt), ty_rec(~[ty_field]), ty_fn(proto, purity, @~[ty_param_bound], fn_decl), - ty_tup(~[@ty]), + ty_tup(~[@Ty]), ty_path(@path, node_id), - ty_fixed_length(@ty, Option<uint>), + ty_fixed_length(@Ty, Option<uint>), ty_mac(mac), // ty_infer means the type should be inferred instead of it having been // specified. This should only appear at the "top level" of a type and not @@ -1092,16 +1141,16 @@ enum ty_ { // Equality and byte-iter (hashing) can be quite approximate for AST types. // since we only care about this for normalizing them to "real" types. -impl ty : cmp::Eq { - pure fn eq(other: &ty) -> bool { +impl Ty : cmp::Eq { + pure fn eq(other: &Ty) -> bool { ptr::addr_of(&self) == ptr::addr_of(&(*other)) } - pure fn ne(other: &ty) -> bool { + pure fn ne(other: &Ty) -> bool { ptr::addr_of(&self) != ptr::addr_of(&(*other)) } } -impl ty : to_bytes::IterBytes { +impl Ty : to_bytes::IterBytes { pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f); } @@ -1109,15 +1158,18 @@ impl ty : to_bytes::IterBytes { #[auto_serialize] -type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; +#[auto_deserialize] +type arg = {mode: mode, ty: @Ty, ident: ident, id: node_id}; #[auto_serialize] +#[auto_deserialize] type fn_decl = {inputs: ~[arg], - output: @ty, + output: @Ty, cf: ret_style}; #[auto_serialize] +#[auto_deserialize] enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1139,6 +1191,7 @@ impl purity : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1164,6 +1217,7 @@ impl ret_style : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` @@ -1217,10 +1271,10 @@ impl self_ty_ : cmp::Eq { pure fn ne(other: &self_ty_) -> bool { !self.eq(other) } } -#[auto_serialize] type self_ty = spanned<self_ty_>; #[auto_serialize] +#[auto_deserialize] type method = {ident: ident, attrs: ~[attribute], tps: ~[ty_param], self_ty: self_ty, purity: purity, decl: fn_decl, body: blk, @@ -1228,9 +1282,11 @@ type method = {ident: ident, attrs: ~[attribute], vis: visibility}; #[auto_serialize] +#[auto_deserialize] type _mod = {view_items: ~[@view_item], items: ~[@item]}; #[auto_serialize] +#[auto_deserialize] enum foreign_abi { foreign_abi_rust_intrinsic, foreign_abi_cdecl, @@ -1239,6 +1295,7 @@ enum foreign_abi { // Foreign mods can be named or anonymous #[auto_serialize] +#[auto_deserialize] enum foreign_mod_sort { named, anonymous } impl foreign_mod_sort : cmp::Eq { @@ -1263,15 +1320,18 @@ impl foreign_abi : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] type foreign_mod = {sort: foreign_mod_sort, view_items: ~[@view_item], items: ~[@foreign_item]}; #[auto_serialize] -type variant_arg = {ty: @ty, id: node_id}; +#[auto_deserialize] +type variant_arg = {ty: @Ty, id: node_id}; #[auto_serialize] +#[auto_deserialize] enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), @@ -1279,22 +1339,28 @@ enum variant_kind { } #[auto_serialize] -enum enum_def = { variants: ~[variant], common: Option<@struct_def> }; +#[auto_deserialize] +type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; + +#[auto_serialize] +#[auto_deserialize] +enum enum_def = enum_def_; #[auto_serialize] +#[auto_deserialize] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: Option<@expr>, vis: visibility}; -#[auto_serialize] type variant = spanned<variant_>; #[auto_serialize] +#[auto_deserialize] type path_list_ident_ = {name: ident, id: node_id}; -#[auto_serialize] type path_list_ident = spanned<path_list_ident_>; #[auto_serialize] +#[auto_deserialize] enum namespace { module_ns, type_value_ns } impl namespace : cmp::Eq { @@ -1304,10 +1370,10 @@ impl namespace : cmp::Eq { pure fn ne(other: &namespace) -> bool { !self.eq(other) } } -#[auto_serialize] type view_path = spanned<view_path_>; #[auto_serialize] +#[auto_deserialize] enum view_path_ { // quux = foo::bar::baz @@ -1325,10 +1391,12 @@ enum view_path_ { } #[auto_serialize] +#[auto_deserialize] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; #[auto_serialize] +#[auto_deserialize] enum view_item_ { view_item_use(ident, ~[@meta_item], node_id), view_item_import(~[@view_path]), @@ -1336,13 +1404,13 @@ enum view_item_ { } // Meta-data associated with an item -#[auto_serialize] type attribute = spanned<attribute_>; // Distinguishes between attributes that decorate items and attributes that // are contained as statements within items. These two cases need to be // distinguished for pretty-printing. #[auto_serialize] +#[auto_deserialize] enum attr_style { attr_outer, attr_inner, } impl attr_style : cmp::Eq { @@ -1354,6 +1422,7 @@ impl attr_style : cmp::Eq { // doc-comments are promoted to attributes that have is_sugared_doc = true #[auto_serialize] +#[auto_deserialize] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; /* @@ -1366,9 +1435,11 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; trait) */ #[auto_serialize] +#[auto_deserialize] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; #[auto_serialize] +#[auto_deserialize] enum visibility { public, private, inherited } impl visibility : cmp::Eq { @@ -1386,29 +1457,29 @@ impl visibility : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] type struct_field_ = { kind: struct_field_kind, id: node_id, - ty: @ty + ty: @Ty }; -#[auto_serialize] type struct_field = spanned<struct_field_>; #[auto_serialize] +#[auto_deserialize] enum struct_field_kind { named_field(ident, class_mutability, visibility), unnamed_field // element of a tuple-like struct } #[auto_serialize] +#[auto_deserialize] type struct_def = { traits: ~[@trait_ref], /* traits this struct implements */ fields: ~[@struct_field], /* fields */ methods: ~[@method], /* methods */ /* (not including ctor or dtor) */ - /* ctor is optional, and will soon go away */ - ctor: Option<class_ctor>, /* dtor is optional */ dtor: Option<class_dtor> }; @@ -1418,28 +1489,31 @@ type struct_def = { we just use dummy names for anon items. */ #[auto_serialize] +#[auto_deserialize] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; #[auto_serialize] +#[auto_deserialize] enum item_ { - item_const(@ty, @expr), + item_const(@Ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), item_mod(_mod), item_foreign_mod(foreign_mod), - item_ty(@ty, ~[ty_param]), + item_ty(@Ty, ~[ty_param]), item_enum(enum_def, ~[ty_param]), item_class(@struct_def, ~[ty_param]), item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]), item_impl(~[ty_param], Option<@trait_ref>, /* (optional) trait this impl implements */ - @ty, /* self */ + @Ty, /* self */ ~[@method]), item_mac(mac), } #[auto_serialize] +#[auto_deserialize] enum class_mutability { class_mutable, class_immutable } impl class_mutability : to_bytes::IterBytes { @@ -1460,26 +1534,27 @@ impl class_mutability : cmp::Eq { pure fn ne(other: &class_mutability) -> bool { !self.eq(other) } } -#[auto_serialize] type class_ctor = spanned<class_ctor_>; #[auto_serialize] +#[auto_deserialize] type class_ctor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, dec: fn_decl, body: blk}; -#[auto_serialize] type class_dtor = spanned<class_dtor_>; #[auto_serialize] +#[auto_deserialize] type class_dtor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, body: blk}; #[auto_serialize] +#[auto_deserialize] type foreign_item = {ident: ident, attrs: ~[attribute], @@ -1489,20 +1564,21 @@ type foreign_item = vis: visibility}; #[auto_serialize] +#[auto_deserialize] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), - foreign_item_const(@ty) + foreign_item_const(@Ty) } // The data we save and restore about an inlined item or method. This is not // part of the AST that we parse from a file, but it becomes part of the tree // that we trans. #[auto_serialize] +#[auto_deserialize] enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), ii_foreign(@foreign_item), - ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */), ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */) } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index d05c6eadaf6..8555ceed2db 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -71,9 +71,6 @@ enum ast_node { // order they are introduced. node_arg(arg, uint), node_local(uint), - // Constructor for a class - // def_id is parent id - node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path), // Destructor for a class node_dtor(~[ty_param], @class_dtor, def_id, @path), node_block(blk), @@ -132,7 +129,7 @@ fn map_decoded_item(diag: span_handler, // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: match ii { - ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ } + ii_item(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic, @path)); @@ -155,18 +152,6 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, cx.local_id += 1u; } match fk { - visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => { - let ct = @{node: {id: id, - attrs: attrs, - self_id: self_id, - dec: /* FIXME (#2543) */ copy decl, - body: /* FIXME (#2543) */ copy body}, - span: sp}; - cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm, - /* FIXME (#2543) */ copy tps, - ct, parent_id, - @/* FIXME (#2543) */ copy cx.path)); - } visit::fk_dtor(tps, attrs, self_id, parent_id) => { let dt = @{node: {id: id, attrs: attrs, self_id: self_id, body: /* FIXME (#2543) */ copy body}, span: sp}; @@ -382,9 +367,6 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { Some(node_local(_)) => { // add more info here fmt!("local (id=%?)", id) } - Some(node_ctor(*)) => { // add more info here - fmt!("node_ctor (id=%?)", id) - } Some(node_dtor(*)) => { // add more info here fmt!("node_dtor (id=%?)", id) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index e8099de246c..6fd84c3317f 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -54,10 +54,10 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} { pure fn def_id_of_def(d: def) -> def_id { match d { - def_fn(id, _) | def_static_method(id, _) | def_mod(id) | + def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_class(id, _) => { + def_use(id) | def_class(id) => { id } def_arg(id, _) | def_local(id, _) | def_self(id) | @@ -233,7 +233,6 @@ fn is_exported(i: ident, m: _mod) -> bool { } } - // FIXME: glob-exports aren't supported yet. (#2006) _ => () } } @@ -339,7 +338,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => /* FIXME (#2543) */ copy i.ident, ii_foreign(i) => /* FIXME (#2543) */ copy i.ident, ii_method(_, m) => /* FIXME (#2543) */ copy m.ident, - ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm, ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm } } @@ -349,7 +347,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => i.id, ii_foreign(i) => i.id, ii_method(_, m) => m.id, - ii_ctor(ctor, _, _, _) => ctor.node.id, ii_dtor(dtor, _, _, _) => dtor.node.id } } @@ -359,9 +356,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => v.visit_item(i, e, v), ii_foreign(i) => v.visit_foreign_item(i, e, v), ii_method(_, m) => visit::visit_method_helper(m, e, v), - ii_ctor(ctor, nm, tps, parent_id) => { - visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v); - } ii_dtor(dtor, _, tps, parent_id) => { visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v); } @@ -407,6 +401,7 @@ fn dtor_dec() -> fn_decl { // Enumerating the IDs which appear in an AST #[auto_serialize] +#[auto_deserialize] type id_range = {min: node_id, max: node_id}; fn empty(range: id_range) -> bool { @@ -476,7 +471,7 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { visit_expr_post: fn@(_e: @expr) { }, - visit_ty: fn@(t: @ty) { + visit_ty: fn@(t: @Ty) { match t.node { ty_path(_, id) => vfn(id), _ => { /* fall through */ } @@ -494,12 +489,6 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { vfn(id); match fk { - visit::fk_ctor(_, _, tps, self_id, parent_id) => { - for vec::each(tps) |tp| { vfn(tp.id); } - vfn(id); - vfn(self_id); - vfn(parent_id.node); - } visit::fk_dtor(tps, _, self_id, parent_id) => { for vec::each(tps) |tp| { vfn(tp.id); } vfn(id); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 374300f07c7..8c19814350c 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -90,9 +90,7 @@ fn attr_meta(attr: ast::attribute) -> @ast::meta_item { @attr.node.value } // Get the meta_items from inside a vector of attributes fn attr_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] { - let mut mitems = ~[]; - for attrs.each |a| { mitems.push(attr_meta(*a)); } - return mitems; + do attrs.map |a| { attr_meta(*a) } } fn desugar_doc_attr(attr: &ast::attribute) -> ast::attribute { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index e07985119ec..69a80d0bac1 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -1,4 +1,8 @@ use dvec::DVec; +use std::serialization::{Serializable, + Deserializable, + Serializer, + Deserializer}; export filename; export filemap; @@ -7,7 +11,7 @@ export file_substr; export fss_none; export fss_internal; export fss_external; -export codemap; +export CodeMap; export expn_info; export expn_info_; export expanded_from; @@ -55,11 +59,11 @@ type filemap = @{name: filename, substr: file_substr, src: @~str, start_pos: file_pos, mut lines: ~[file_pos]}; -type codemap = @{files: DVec<filemap>}; +type CodeMap = @{files: DVec<filemap>}; type loc = {file: filemap, line: uint, col: uint}; -fn new_codemap() -> codemap { @{files: DVec()} } +fn new_codemap() -> CodeMap { @{files: DVec()} } fn new_filemap_w_substr(+filename: filename, +substr: file_substr, src: @~str, @@ -77,7 +81,7 @@ fn new_filemap(+filename: filename, src: @~str, start_pos_ch, start_pos_byte); } -fn mk_substr_filename(cm: codemap, sp: span) -> ~str +fn mk_substr_filename(cm: CodeMap, sp: span) -> ~str { let pos = lookup_char_pos(cm, sp.lo); return fmt!("<%s:%u:%u>", pos.file.name, pos.line, pos.col); @@ -89,7 +93,7 @@ fn next_line(file: filemap, chpos: uint, byte_pos: uint) { type lookup_fn = pure fn(file_pos) -> uint; -fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn) +fn lookup_line(map: CodeMap, pos: uint, lookup: lookup_fn) -> {fm: filemap, line: uint} { let len = map.files.len(); @@ -112,22 +116,22 @@ fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn) return {fm: f, line: a}; } -fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc { +fn lookup_pos(map: CodeMap, pos: uint, lookup: lookup_fn) -> loc { let {fm: f, line: a} = lookup_line(map, pos, lookup); return {file: f, line: a + 1u, col: pos - lookup(f.lines[a])}; } -fn lookup_char_pos(map: codemap, pos: uint) -> loc { +fn lookup_char_pos(map: CodeMap, pos: uint) -> loc { pure fn lookup(pos: file_pos) -> uint { return pos.ch; } return lookup_pos(map, pos, lookup); } -fn lookup_byte_pos(map: codemap, pos: uint) -> loc { +fn lookup_byte_pos(map: CodeMap, pos: uint) -> loc { pure fn lookup(pos: file_pos) -> uint { return pos.byte; } return lookup_pos(map, pos, lookup); } -fn lookup_char_pos_adj(map: codemap, pos: uint) +fn lookup_char_pos_adj(map: CodeMap, pos: uint) -> {filename: ~str, line: uint, col: uint, file: Option<filemap>} { let loc = lookup_char_pos(map, pos); @@ -150,7 +154,7 @@ fn lookup_char_pos_adj(map: codemap, pos: uint) } } -fn adjust_span(map: codemap, sp: span) -> span { +fn adjust_span(map: CodeMap, sp: span) -> span { pure fn lookup(pos: file_pos) -> uint { return pos.ch; } let line = lookup_line(map, sp.lo, lookup); match (line.fm.substr) { @@ -178,14 +182,42 @@ impl span : cmp::Eq { pure fn ne(other: &span) -> bool { !self.eq(other) } } -fn span_to_str_no_adj(sp: span, cm: codemap) -> ~str { +#[cfg(stage0)] +impl span: Serializable { + /* Note #1972 -- spans are serialized but not deserialized */ + fn serialize<S: Serializer>(&self, _s: &S) { } +} + +#[cfg(stage0)] +impl span: Deserializable { + static fn deserialize<D: Deserializer>(_d: &D) -> span { + ast_util::dummy_sp() + } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl<S: Serializer> span: Serializable<S> { + /* Note #1972 -- spans are serialized but not deserialized */ + fn serialize(&self, _s: &S) { } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl<D: Deserializer> span: Deserializable<D> { + static fn deserialize(_d: &D) -> span { + ast_util::dummy_sp() + } +} + +fn span_to_str_no_adj(sp: span, cm: CodeMap) -> ~str { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); return fmt!("%s:%u:%u: %u:%u", lo.file.name, lo.line, lo.col, hi.line, hi.col) } -fn span_to_str(sp: span, cm: codemap) -> ~str { +fn span_to_str(sp: span, cm: CodeMap) -> ~str { let lo = lookup_char_pos_adj(cm, sp.lo); let hi = lookup_char_pos_adj(cm, sp.hi); return fmt!("%s:%u:%u: %u:%u", lo.filename, @@ -194,12 +226,12 @@ fn span_to_str(sp: span, cm: codemap) -> ~str { type file_lines = {file: filemap, lines: ~[uint]}; -fn span_to_filename(sp: span, cm: codemap::codemap) -> filename { +fn span_to_filename(sp: span, cm: codemap::CodeMap) -> filename { let lo = lookup_char_pos(cm, sp.lo); return /* FIXME (#2543) */ copy lo.file.name; } -fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines { +fn span_to_lines(sp: span, cm: codemap::CodeMap) -> @file_lines { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); let mut lines = ~[]; @@ -218,7 +250,7 @@ fn get_line(fm: filemap, line: int) -> ~str unsafe { str::slice(*fm.src, begin, end) } -fn lookup_byte_offset(cm: codemap::codemap, chpos: uint) +fn lookup_byte_offset(cm: codemap::CodeMap, chpos: uint) -> {fm: filemap, pos: uint} { pure fn lookup(pos: file_pos) -> uint { return pos.ch; } let {fm, line} = lookup_line(cm, chpos, lookup); @@ -228,20 +260,20 @@ fn lookup_byte_offset(cm: codemap::codemap, chpos: uint) {fm: fm, pos: line_offset + col_offset} } -fn span_to_snippet(sp: span, cm: codemap::codemap) -> ~str { +fn span_to_snippet(sp: span, cm: codemap::CodeMap) -> ~str { let begin = lookup_byte_offset(cm, sp.lo); let end = lookup_byte_offset(cm, sp.hi); assert begin.fm.start_pos == end.fm.start_pos; return str::slice(*begin.fm.src, begin.pos, end.pos); } -fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> ~str +fn get_snippet(cm: codemap::CodeMap, fidx: uint, lo: uint, hi: uint) -> ~str { let fm = cm.files[fidx]; return str::slice(*fm.src, lo, hi) } -fn get_filemap(cm: codemap, filename: ~str) -> filemap { +fn get_filemap(cm: CodeMap, filename: ~str) -> filemap { for cm.files.each |fm| { if fm.name == filename { return *fm; } } //XXjdm the following triggers a mismatched type bug // (or expected function, found _|_) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 7f208a3a710..855b0ca3ef5 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -9,7 +9,7 @@ export codemap_span_handler, codemap_handler; export ice_msg; export expect; -type emitter = fn@(cmsp: Option<(codemap::codemap, span)>, +type emitter = fn@(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level); @@ -33,7 +33,7 @@ trait handler { fn note(msg: &str); fn bug(msg: &str) -> !; fn unimpl(msg: &str) -> !; - fn emit(cmsp: Option<(codemap::codemap, span)>, msg: &str, lvl: level); + fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level); } type handler_t = @{ @@ -43,7 +43,7 @@ type handler_t = @{ type codemap_t = @{ handler: handler, - cm: codemap::codemap + cm: codemap::CodeMap }; impl codemap_t: span_handler { @@ -107,7 +107,7 @@ impl handler_t: handler { self.fatal(ice_msg(msg)); } fn unimpl(msg: &str) -> ! { self.bug(~"unimplemented " + msg); } - fn emit(cmsp: Option<(codemap::codemap, span)>, msg: &str, lvl: level) { + fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level) { self.emit(cmsp, msg, lvl); } } @@ -116,7 +116,7 @@ fn ice_msg(msg: &str) -> ~str { fmt!("internal compiler error: %s", msg) } -fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler { +fn mk_span_handler(handler: handler, cm: codemap::CodeMap) -> span_handler { @{ handler: handler, cm: cm } as span_handler } @@ -125,7 +125,7 @@ fn mk_handler(emitter: Option<emitter>) -> handler { let emit = match emitter { Some(e) => e, None => { - let f = fn@(cmsp: Option<(codemap::codemap, span)>, + let f = fn@(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, t: level) { emit(cmsp, msg, t); }; @@ -189,8 +189,7 @@ fn print_diagnostic(topic: ~str, lvl: level, msg: &str) { io::stderr().write_str(fmt!(" %s\n", msg)); } -fn emit(cmsp: Option<(codemap::codemap, span)>, - msg: &str, lvl: level) { +fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level) { match cmsp { Some((cm, sp)) => { let sp = codemap::adjust_span(cm,sp); @@ -206,7 +205,7 @@ fn emit(cmsp: Option<(codemap::codemap, span)>, } } -fn highlight_lines(cm: codemap::codemap, sp: span, +fn highlight_lines(cm: codemap::CodeMap, sp: span, lines: @codemap::file_lines) { let fm = lines.file; @@ -261,12 +260,12 @@ fn highlight_lines(cm: codemap::codemap, sp: span, } } -fn print_macro_backtrace(cm: codemap::codemap, sp: span) { +fn print_macro_backtrace(cm: codemap::CodeMap, sp: span) { do option::iter(&sp.expn_info) |ei| { let ss = option::map_default(&ei.callie.span, @~"", |span| @codemap::span_to_str(*span, cm)); print_diagnostic(*ss, note, - fmt!("in expansion of #%s", ei.callie.name)); + fmt!("in expansion of %s!", ei.callie.name)); let ss = codemap::span_to_str(ei.call_site, cm); print_diagnostic(ss, note, ~"expansion site"); print_macro_backtrace(cm, ei.call_site); diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 64915c60742..47e61c26f38 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -1,62 +1,70 @@ /* -The compiler code necessary to implement the #[auto_serialize] -extension. The idea here is that type-defining items may be tagged -with #[auto_serialize], which will cause us to generate a little -companion module with the same name as the item. +The compiler code necessary to implement the #[auto_serialize] and +#[auto_deserialize] extension. The idea here is that type-defining items may +be tagged with #[auto_serialize] and #[auto_deserialize], which will cause +us to generate a little companion module with the same name as the item. For example, a type like: - type node_id = uint; + #[auto_serialize] + #[auto_deserialize] + struct Node {id: uint} -would generate two functions like: +would generate two implementations like: - fn serialize_node_id<S: serializer>(s: S, v: node_id) { - s.emit_uint(v); + impl<S: Serializer> node_id: Serializable<S> { + fn serialize(s: &S) { + do s.emit_struct("Node") { + s.emit_field("id", 0, || s.emit_uint(self)) + } + } } - fn deserialize_node_id<D: deserializer>(d: D) -> node_id { - d.read_uint() + + impl<D: Deserializer> node_id: Deserializable { + static fn deserialize(d: &D) -> Node { + do d.read_struct("Node") { + Node { + id: d.read_field(~"x", 0, || deserialize(d)) + } + } + } } Other interesting scenarios are whe the item has type parameters or references other non-built-in types. A type definition like: + #[auto_serialize] + #[auto_deserialize] type spanned<T> = {node: T, span: span}; would yield functions like: - fn serialize_spanned<S: serializer,T>(s: S, v: spanned<T>, t: fn(T)) { - s.emit_rec(2u) {|| - s.emit_rec_field("node", 0u) {|| - t(s.node); - }; - s.emit_rec_field("span", 1u) {|| - serialize_span(s, s.span); - }; - } - } - fn deserialize_spanned<D: deserializer>(d: D, t: fn() -> T) -> node_id { - d.read_rec(2u) {|| - {node: d.read_rec_field("node", 0u, t), - span: d.read_rec_field("span", 1u) {||deserialize_span(d)}} - } + impl< + S: Serializer, + T: Serializable<S> + > spanned<T>: Serializable<S> { + fn serialize<S: Serializer>(s: &S) { + do s.emit_rec { + s.emit_field("node", 0, || self.node.serialize(s)); + s.emit_field("span", 1, || self.span.serialize(s)); + } + } } -In general, the code to serialize an instance `v` of a non-built-in -type a::b::c<T0,...,Tn> looks like: - - a::b::serialize_c(s, {|v| c_T0}, ..., {|v| c_Tn}, v) - -where `c_Ti` is the code to serialize an instance `v` of the type -`Ti`. - -Similarly, the code to deserialize an instance of a non-built-in type -`a::b::c<T0,...,Tn>` using the deserializer `d` looks like: - - a::b::deserialize_c(d, {|| c_T0}, ..., {|| c_Tn}) - -where `c_Ti` is the code to deserialize an instance of `Ti` using the -deserializer `d`. + impl< + D: Deserializer, + T: Deserializable<D> + > spanned<T>: Deserializable<D> { + static fn deserialize(d: &D) -> spanned<T> { + do d.read_rec { + { + node: d.read_field(~"node", 0, || deserialize(d)), + span: d.read_field(~"span", 1, || deserialize(d)), + } + } + } + } FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the standard library. @@ -69,137 +77,167 @@ into the tree. This is intended to prevent us from inserting the same node twice. */ + use base::*; use codemap::span; use std::map; use std::map::HashMap; -export expand; +export expand_auto_serialize; +export expand_auto_deserialize; // Transitional reexports so qquote can find the paths it is looking for mod syntax { - #[legacy_exports]; pub use ext; pub use parse; } -type ser_tps_map = map::HashMap<ast::ident, fn@(@ast::expr) -> ~[@ast::stmt]>; -type deser_tps_map = map::HashMap<ast::ident, fn@() -> @ast::expr>; - -fn expand(cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item]) -> ~[@ast::item] { - fn not_auto_serialize(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) != ~"auto_serialize" +fn expand_auto_serialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_serialize(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_serialize" } fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, not_auto_serialize), + @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize(a)), .. *item} } - do vec::flat_map(in_items) |in_item| { - match in_item.node { - ast::item_ty(ty, tps) => { - vec::append(~[filter_attrs(*in_item)], - ty_fns(cx, in_item.ident, ty, tps)) - } - - ast::item_enum(enum_definition, tps) => { - vec::append(~[filter_attrs(*in_item)], - enum_fns(cx, in_item.ident, - in_item.span, enum_definition.variants, tps)) - } - - _ => { - cx.span_err(span, ~"#[auto_serialize] can only be \ - applied to type and enum \ - definitions"); - ~[*in_item] - } + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_serialize) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let ser_impl = mk_rec_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let ser_impl = mk_struct_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_enum(enum_def, tps) => { + let ser_impl = mk_enum_ser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_serialize] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] } } } -trait ext_ctxt_helpers { - fn helper_path(base_path: @ast::path, helper_name: ~str) -> @ast::path; - fn path(span: span, strs: ~[ast::ident]) -> @ast::path; - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path; - fn ty_path(span: span, strs: ~[ast::ident], tps: ~[@ast::ty]) -> @ast::ty; - fn ty_fn(span: span, - -input_tys: ~[@ast::ty], - -output: @ast::ty) -> @ast::ty; - fn ty_nil(span: span) -> @ast::ty; - fn expr(span: span, node: ast::expr_) -> @ast::expr; - fn var_ref(span: span, name: ast::ident) -> @ast::expr; - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk; - fn expr_blk(expr: @ast::expr) -> ast::blk; - fn binder_pat(span: span, nm: ast::ident) -> @ast::pat; - fn stmt(expr: @ast::expr) -> @ast::stmt; - fn alt_stmt(arms: ~[ast::arm], span: span, -v: @ast::expr) -> @ast::stmt; - fn lit_str(span: span, s: @~str) -> @ast::expr; - fn lit_uint(span: span, i: uint) -> @ast::expr; - fn lambda(blk: ast::blk) -> @ast::expr; - fn clone_folder() -> fold::ast_fold; - fn clone(v: @ast::expr) -> @ast::expr; - fn clone_ty(v: @ast::ty) -> @ast::ty; - fn clone_ty_param(v: ast::ty_param) -> ast::ty_param; - fn at(span: span, expr: @ast::expr) -> @ast::expr; -} - -impl ext_ctxt: ext_ctxt_helpers { - fn helper_path(base_path: @ast::path, - helper_name: ~str) -> @ast::path { - let head = vec::init(base_path.idents); - let tail = vec::last(base_path.idents); - self.path(base_path.span, - vec::append(head, - ~[self.parse_sess().interner. - intern(@(helper_name + ~"_" + - *self.parse_sess().interner.get( - tail)))])) +fn expand_auto_deserialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_deserialize(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_deserialize" } - fn path(span: span, strs: ~[ast::ident]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: ~[]} - } - - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: tps} + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize(a)), + .. *item} } - fn ty_path(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::ty { - @{id: self.next_id(), - node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), - span: span} + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_deserialize) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let deser_impl = mk_rec_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let deser_impl = mk_struct_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_enum(enum_def, tps) => { + let deser_impl = mk_enum_deser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_deserialize] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } } +} - fn ty_fn(span: span, - -input_tys: ~[@ast::ty], - -output: @ast::ty) -> @ast::ty { - let args = do vec::map(input_tys) |ty| { - {mode: ast::expl(ast::by_ref), - ty: *ty, - ident: parse::token::special_idents::invalid, - id: self.next_id()} - }; - - @{id: self.next_id(), - node: ast::ty_fn(ast::proto_block, - ast::impure_fn, - @~[], - {inputs: args, - output: output, - cf: ast::return_val}), - span: span} - } +priv impl ext_ctxt { + fn bind_path( + span: span, + ident: ast::ident, + path: @ast::path, + bounds: @~[ast::ty_param_bound] + ) -> ast::ty_param { + let bound = ast::ty_param_bound(@{ + id: self.next_id(), + node: ast::ty_path(path, self.next_id()), + span: span, + }); - fn ty_nil(span: span) -> @ast::ty { - @{id: self.next_id(), node: ast::ty_nil, span: span} + { + ident: ident, + id: self.next_id(), + bounds: @vec::append(~[bound], *bounds) + } } fn expr(span: span, node: ast::expr_) -> @ast::expr { @@ -207,26 +245,20 @@ impl ext_ctxt: ext_ctxt_helpers { node: node, span: span} } - fn var_ref(span: span, name: ast::ident) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, ~[name]))) + fn path(span: span, strs: ~[ast::ident]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: ~[]} } - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { - {node: {view_items: ~[], - stmts: stmts, - expr: None, - id: self.next_id(), - rules: ast::default_blk}, - span: span} + fn path_tps(span: span, strs: ~[ast::ident], + tps: ~[@ast::Ty]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: tps} } - fn expr_blk(expr: @ast::expr) -> ast::blk { - {node: {view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: self.next_id(), - rules: ast::default_blk}, - span: expr.span} + fn ty_path(span: span, strs: ~[ast::ident], + tps: ~[@ast::Ty]) -> @ast::Ty { + @{id: self.next_id(), + node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), + span: span} } fn binder_pat(span: span, nm: ast::ident) -> @ast::pat { @@ -244,14 +276,6 @@ impl ext_ctxt: ext_ctxt_helpers { span: expr.span} } - fn alt_stmt(arms: ~[ast::arm], - span: span, -v: @ast::expr) -> @ast::stmt { - self.stmt( - self.expr( - span, - ast::expr_match(v, arms))) - } - fn lit_str(span: span, s: @~str) -> @ast::expr { self.expr( span, @@ -278,686 +302,835 @@ impl ext_ctxt: ext_ctxt_helpers { #ast{ || $(blk_e) } } - fn clone_folder() -> fold::ast_fold { - fold::make_fold(@{ - new_id: |_id| self.next_id(), - .. *fold::default_ast_fold() - }) + fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { + {node: {view_items: ~[], + stmts: stmts, + expr: None, + id: self.next_id(), + rules: ast::default_blk}, + span: span} } - fn clone(v: @ast::expr) -> @ast::expr { - let fld = self.clone_folder(); - fld.fold_expr(v) + fn expr_blk(expr: @ast::expr) -> ast::blk { + {node: {view_items: ~[], + stmts: ~[], + expr: Some(expr), + id: self.next_id(), + rules: ast::default_blk}, + span: expr.span} } - fn clone_ty(v: @ast::ty) -> @ast::ty { - let fld = self.clone_folder(); - fld.fold_ty(v) + fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { + self.expr(span, ast::expr_path(self.path(span, strs))) } - fn clone_ty_param(v: ast::ty_param) -> ast::ty_param { - let fld = self.clone_folder(); - fold::fold_ty_param(v, fld) + fn expr_var(span: span, var: ~str) -> @ast::expr { + self.expr_path(span, ~[self.ident_of(var)]) } - fn at(span: span, expr: @ast::expr) -> @ast::expr { - fn repl_sp(old_span: span, repl_span: span, with_span: span) -> span { - if old_span == repl_span { - with_span - } else { - old_span - } - } - - let fld = fold::make_fold(@{ - new_span: |a| repl_sp(a, ast_util::dummy_sp(), span), - .. *fold::default_ast_fold() - }); + fn expr_field( + span: span, + expr: @ast::expr, + ident: ast::ident + ) -> @ast::expr { + self.expr(span, ast::expr_field(expr, ident, ~[])) + } - fld.fold_expr(expr) + fn expr_call( + span: span, + expr: @ast::expr, + args: ~[@ast::expr] + ) -> @ast::expr { + self.expr(span, ast::expr_call(expr, args, false)) } -} -fn ser_path(cx: ext_ctxt, tps: ser_tps_map, path: @ast::path, - -s: @ast::expr, -v: @ast::expr) - -> ~[@ast::stmt] { - let ext_cx = cx; // required for #ast{} - - // We want to take a path like a::b::c<...> and generate a call - // like a::b::c::serialize(s, ...), as described above. - - let callee = - cx.expr( - path.span, - ast::expr_path( - cx.helper_path(path, ~"serialize"))); - - let ty_args = do vec::map(path.types) |ty| { - let sv_stmts = ser_ty(cx, tps, *ty, cx.clone(s), #ast{ __v }); - let sv = cx.expr(path.span, - ast::expr_block(cx.blk(path.span, sv_stmts))); - cx.at(ty.span, #ast{ |__v| $(sv) }) - }; + fn lambda_expr(expr: @ast::expr) -> @ast::expr { + self.lambda(self.expr_blk(expr)) + } - ~[cx.stmt( - cx.expr( - path.span, - ast::expr_call(callee, vec::append(~[s, v], ty_args), false)))] + fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr { + self.lambda(self.blk(span, stmts)) + } } -fn ser_variant(cx: ext_ctxt, - tps: ser_tps_map, - tys: ~[@ast::ty], - span: span, - -s: @ast::expr, - pfn: fn(~[@ast::pat]) -> ast::pat_, - bodyfn: fn(-v: @ast::expr, ast::blk) -> @ast::expr, - argfn: fn(-v: @ast::expr, uint, ast::blk) -> @ast::expr) - -> ast::arm { - let vnames = do vec::from_fn(vec::len(tys)) |i| { - cx.parse_sess().interner.intern(@fmt!("__v%u", i)) - }; - let pats = do vec::from_fn(vec::len(tys)) |i| { - cx.binder_pat(tys[i].span, vnames[i]) - }; - let pat: @ast::pat = @{id: cx.next_id(), node: pfn(pats), span: span}; - let stmts = do vec::from_fn(vec::len(tys)) |i| { - let v = cx.var_ref(span, vnames[i]); - let arg_blk = - cx.blk( - span, - ser_ty(cx, tps, tys[i], cx.clone(s), move v)); - cx.stmt(argfn(cx.clone(s), i, arg_blk)) - }; - - let body_blk = cx.blk(span, stmts); - let body = cx.blk(span, ~[cx.stmt(bodyfn(move s, body_blk))]); +fn mk_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + ty_param: ast::ty_param, + path: @ast::path, + tps: ~[ast::ty_param], + f: fn(@ast::Ty) -> @ast::method +) -> @ast::item { + // All the type parameters need to bound to the trait. + let mut trait_tps = vec::append( + ~[ty_param], + do tps.map |tp| { + let t_bound = ast::ty_param_bound(@{ + id: cx.next_id(), + node: ast::ty_path(path, cx.next_id()), + span: span, + }); - {pats: ~[pat], guard: None, body: body} + { + ident: tp.ident, + id: cx.next_id(), + bounds: @vec::append(~[t_bound], *tp.bounds) + } + } + ); + + let opt_trait = Some(@{ + path: path, + ref_id: cx.next_id(), + impl_id: cx.next_id(), + }); + + let ty = cx.ty_path( + span, + ~[ident], + tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) + ); + + @{ + // This is a new-style impl declaration. + // XXX: clownshoes + ident: ast::token::special_idents::clownshoes_extensions, + attrs: ~[], + id: cx.next_id(), + node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), + vis: ast::public, + span: span, + } } -fn ser_lambda(cx: ext_ctxt, tps: ser_tps_map, ty: @ast::ty, - -s: @ast::expr, -v: @ast::expr) -> @ast::expr { - cx.lambda(cx.blk(ty.span, ser_ty(cx, tps, ty, move s, move v))) +fn mk_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization::Serializable typaram. + let ty_param = cx.bind_path( + span, + cx.ident_of(~"__S"), + cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializer"), + ] + ), + @~[] + ); + + // Make a path to the std::serialization::Serializable trait. + let path = cx.path_tps( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializable"), + ], + ~[cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[])] + ); + + mk_impl( + cx, + span, + ident, + ty_param, + path, + tps, + |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) + ) } -fn is_vec_or_str(ty: @ast::ty) -> bool { - match ty.node { - ast::ty_vec(_) => true, - // This may be wrong if the user has shadowed (!) str - ast::ty_path(@{span: _, global: _, idents: ids, - rp: None, types: _}, _) - if ids == ~[parse::token::special_idents::str] => true, - _ => false - } +fn mk_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization::Deserializable typaram. + let ty_param = cx.bind_path( + span, + cx.ident_of(~"__D"), + cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializer"), + ] + ), + @~[] + ); + + // Make a path to the std::serialization::Deserializable trait. + let path = cx.path_tps( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializable"), + ], + ~[cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[])] + ); + + mk_impl( + cx, + span, + ident, + ty_param, + path, + tps, + |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) + ) } -fn ser_ty(cx: ext_ctxt, tps: ser_tps_map, - ty: @ast::ty, -s: @ast::expr, -v: @ast::expr) - -> ~[@ast::stmt] { - - let ext_cx = cx; // required for #ast{} - - match ty.node { - ast::ty_nil => { - ~[#ast[stmt]{$(s).emit_nil()}] - } - - ast::ty_bot => { - cx.span_err( - ty.span, fmt!("Cannot serialize bottom type")); - ~[] - } - - ast::ty_box(mt) => { - let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) }); - ~[#ast[stmt]{$(s).emit_box($(l));}] - } - - // For unique evecs/estrs, just pass through to underlying vec or str - ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => { - ser_ty(cx, tps, mt.ty, move s, move v) - } - - ast::ty_uniq(mt) => { - let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) }); - ~[#ast[stmt]{$(s).emit_uniq($(l));}] - } - - ast::ty_ptr(_) | ast::ty_rptr(_, _) => { - cx.span_err(ty.span, ~"cannot serialize pointer types"); - ~[] - } - - ast::ty_rec(flds) => { - let fld_stmts = do vec::from_fn(vec::len(flds)) |fidx| { - let fld = flds[fidx]; - let vf = cx.expr(fld.span, - ast::expr_field(cx.clone(v), - fld.node.ident, - ~[])); - let s = cx.clone(s); - let f = cx.lit_str(fld.span, cx.parse_sess().interner.get( - fld.node.ident)); - let i = cx.lit_uint(fld.span, fidx); - let l = ser_lambda(cx, tps, fld.node.mt.ty, cx.clone(s), move vf); - #ast[stmt]{$(s).emit_rec_field($(f), $(i), $(l));} - }; - let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts)); - ~[#ast[stmt]{$(s).emit_rec($(fld_lambda));}] - } - - ast::ty_fn(*) => { - cx.span_err(ty.span, ~"cannot serialize function types"); - ~[] - } - - ast::ty_tup(tys) => { - // Generate code like - // - // match v { - // (v1, v2, v3) { - // .. serialize v1, v2, v3 .. - // } - // }; - - let arms = ~[ - ser_variant( - - cx, tps, tys, ty.span, move s, - - // Generate pattern (v1, v2, v3) - |pats| ast::pat_tup(pats), - - // Generate body s.emit_tup(3, {|| blk }) - |-s, blk| { - let sz = cx.lit_uint(ty.span, vec::len(tys)); - let body = cx.lambda(blk); - #ast{ $(s).emit_tup($(sz), $(body)) } - }, - - // Generate s.emit_tup_elt(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(ty.span, i); - let body = cx.lambda(blk); - #ast{ $(s).emit_tup_elt($(idx), $(body)) } - }) - ]; - ~[cx.alt_stmt(arms, ty.span, move v)] - } - - ast::ty_path(path, _) => { - if path.idents.len() == 1 && path.types.is_empty() { - let ident = path.idents[0]; - - match tps.find(ident) { - Some(f) => f(v), - None => ser_path(cx, tps, path, move s, move v) +fn mk_ser_method( + cx: ext_ctxt, + span: span, + ser_body: ast::blk +) -> @ast::method { + let ty_s = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), + mutbl: ast::m_imm } - } else { - ser_path(cx, tps, path, move s, move v) - } - } + ), + span: span, + }; - ast::ty_mac(_) => { - cx.span_err(ty.span, ~"cannot serialize macro types"); - ~[] - } + let ser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_s, + ident: cx.ident_of(~"__s"), + id: cx.next_id(), + }]; + + let ser_output = @{ + id: cx.next_id(), + node: ast::ty_nil, + span: span, + }; - ast::ty_infer => { - cx.span_err(ty.span, ~"cannot serialize inferred types"); - ~[] - } + let ser_decl = { + inputs: ser_inputs, + output: ser_output, + cf: ast::return_val, + }; - ast::ty_vec(mt) => { - let ser_e = - cx.expr( - ty.span, - ast::expr_block( - cx.blk( - ty.span, - ser_ty( - cx, tps, mt.ty, - cx.clone(s), - cx.at(ty.span, #ast{ __e }))))); - - ~[#ast[stmt]{ - std::serialization::emit_from_vec($(s), $(v), |__e| $(ser_e)) - }] - } - - ast::ty_fixed_length(_, _) => { - cx.span_unimpl(ty.span, ~"serialization for fixed length types"); - } + @{ + ident: cx.ident_of(~"serialize"), + attrs: ~[], + tps: ~[], + self_ty: { node: ast::sty_region(ast::m_imm), span: span }, + purity: ast::impure_fn, + decl: ser_decl, + body: ser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, } } -fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident, - tps: ~[ast::ty_param], - f: fn(ext_ctxt, ser_tps_map, - -v: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt]) - -> @ast::item { - let ext_cx = cx; // required for #ast - - let tp_types = vec::map(tps, |tp| cx.ty_path(span, ~[tp.ident], ~[])); - let v_ty = cx.ty_path(span, ~[name], tp_types); - - let tp_inputs = - vec::map(tps, |tp| - {mode: ast::expl(ast::by_ref), - ty: cx.ty_fn(span, - ~[cx.ty_path(span, ~[tp.ident], ~[])], - cx.ty_nil(span)), - ident: cx.ident_of(~"__s" + cx.str_of(tp.ident)), - id: cx.next_id()}); - - debug!("tp_inputs = %?", tp_inputs); - - - let ser_inputs: ~[ast::arg] = - vec::append(~[{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - ident: cx.ident_of(~"__s"), - id: cx.next_id()}, - {mode: ast::expl(ast::by_ref), - ty: v_ty, - ident: cx.ident_of(~"__v"), - id: cx.next_id()}], - tp_inputs); - - let tps_map = map::HashMap(); - for vec::each2(tps, tp_inputs) |tp, arg| { - let arg_ident = arg.ident; - tps_map.insert( - tp.ident, - fn@(v: @ast::expr) -> ~[@ast::stmt] { - let f = cx.var_ref(span, arg_ident); - debug!("serializing type arg %s", cx.str_of(arg_ident)); - ~[#ast[stmt]{$(f)($(v));}] - }); - } +fn mk_deser_method( + cx: ext_ctxt, + span: span, + ty: @ast::Ty, + deser_body: ast::blk +) -> @ast::method { + let ty_d = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; - let ser_bnds = @~[ - ast::bound_trait(cx.ty_path(span, - ~[cx.ident_of(~"std"), - cx.ident_of(~"serialization"), - cx.ident_of(~"Serializer")], - ~[]))]; - - let ser_tps: ~[ast::ty_param] = - vec::append(~[{ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: ser_bnds}], - vec::map(tps, |tp| cx.clone_ty_param(*tp))); - - let ser_output: @ast::ty = @{id: cx.next_id(), - node: ast::ty_nil, - span: span}; - - let ser_blk = cx.blk(span, - f(cx, tps_map, #ast{ __s }, #ast{ __v })); - - @{ident: cx.ident_of(~"serialize_" + cx.str_of(name)), - attrs: ~[], - id: cx.next_id(), - node: ast::item_fn({inputs: ser_inputs, - output: ser_output, - cf: ast::return_val}, - ast::impure_fn, - ser_tps, - ser_blk), - vis: ast::public, - span: span} + let deser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_d, + ident: cx.ident_of(~"__d"), + id: cx.next_id(), + }]; + + let deser_decl = { + inputs: deser_inputs, + output: ty, + cf: ast::return_val, + }; + + @{ + ident: cx.ident_of(~"deserialize"), + attrs: ~[], + tps: ~[], + self_ty: { node: ast::sty_static, span: span }, + purity: ast::impure_fn, + decl: deser_decl, + body: deser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, + } } -// ______________________________________________________________________ +fn mk_rec_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `__s.emit_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_rec") + ), + ~[cx.lambda_stmts(span, fields)] + ); -fn deser_path(cx: ext_ctxt, tps: deser_tps_map, path: @ast::path, - -d: @ast::expr) -> @ast::expr { - // We want to take a path like a::b::c<...> and generate a call - // like a::b::c::deserialize(d, ...), as described above. + mk_ser_impl(cx, span, ident, tps, body) +} - let callee = - cx.expr( - path.span, - ast::expr_path( - cx.helper_path(path, ~"deserialize"))); +fn mk_rec_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `read_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_rec") + ), + ~[ + cx.lambda_expr( + cx.expr( + span, + ast::expr_rec(fields, None) + ) + ) + ] + ); - let ty_args = do vec::map(path.types) |ty| { - let dv_expr = deser_ty(cx, tps, *ty, cx.clone(d)); - cx.lambda(cx.expr_blk(dv_expr)) - }; + mk_deser_impl(cx, span, ident, tps, body) +} - cx.expr(path.span, ast::expr_call(callee, vec::append(~[d], ty_args), - false)) +fn mk_struct_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `__s.emit_struct($(name), || $(fields))` + let ser_body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_stmts(span, fields), + ] + ); + + mk_ser_impl(cx, span, ident, tps, ser_body) } -fn deser_lambda(cx: ext_ctxt, tps: deser_tps_map, ty: @ast::ty, - -d: @ast::expr) -> @ast::expr { - cx.lambda(cx.expr_blk(deser_ty(cx, tps, ty, move d))) +fn mk_struct_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `read_struct($(name), || $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_expr( + cx.expr( + span, + ast::expr_struct( + cx.path(span, ~[ident]), + fields, + None + ) + ) + ), + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) } -fn deser_ty(cx: ext_ctxt, tps: deser_tps_map, - ty: @ast::ty, -d: @ast::expr) -> @ast::expr { - - let ext_cx = cx; // required for #ast{} - - match ty.node { - ast::ty_nil => { - #ast{ $(d).read_nil() } - } - - ast::ty_bot => { - #ast{ fail } - } - - ast::ty_box(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ @$(d).read_box($(l)) } - } - - // For unique evecs/estrs, just pass through to underlying vec or str - ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => { - deser_ty(cx, tps, mt.ty, move d) - } - - ast::ty_uniq(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ ~$(d).read_uniq($(l)) } - } - - ast::ty_ptr(_) | ast::ty_rptr(_, _) => { - #ast{ fail } - } - - ast::ty_rec(flds) => { - let fields = do vec::from_fn(vec::len(flds)) |fidx| { - let fld = flds[fidx]; - let d = cx.clone(d); - let f = cx.lit_str(fld.span, @cx.str_of(fld.node.ident)); - let i = cx.lit_uint(fld.span, fidx); - let l = deser_lambda(cx, tps, fld.node.mt.ty, cx.clone(d)); - {node: {mutbl: fld.node.mt.mutbl, - ident: fld.node.ident, - expr: #ast{ $(d).read_rec_field($(f), $(i), $(l))} }, - span: fld.span} - }; - let fld_expr = cx.expr(ty.span, ast::expr_rec(fields, None)); - let fld_lambda = cx.lambda(cx.expr_blk(fld_expr)); - #ast{ $(d).read_rec($(fld_lambda)) } - } - - ast::ty_fn(*) => { - #ast{ fail } - } - - ast::ty_tup(tys) => { - // Generate code like - // - // d.read_tup(3u) {|| - // (d.read_tup_elt(0u, {||...}), - // d.read_tup_elt(1u, {||...}), - // d.read_tup_elt(2u, {||...})) - // } - - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(ty.span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_tup_elt($(idx), $(body)) } - }; - let body = - cx.lambda(cx.expr_blk( - cx.expr(ty.span, ast::expr_tup(arg_exprs)))); - let sz = cx.lit_uint(ty.span, vec::len(tys)); - #ast{ $(d).read_tup($(sz), $(body)) } - } - - ast::ty_path(path, _) => { - if vec::len(path.idents) == 1u && - vec::is_empty(path.types) { - let ident = path.idents[0]; - - match tps.find(ident) { - Some(f) => f(), - None => deser_path(cx, tps, path, move d) - } - } else { - deser_path(cx, tps, path, move d) +// Records and structs don't have the same fields types, but they share enough +// that if we extract the right subfields out we can share the serialization +// generator code. +type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; + +fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { + do fields.map |field| { + { + span: field.span, + ident: field.node.ident, + mutbl: field.node.mt.mutbl, } - } - - ast::ty_mac(_) => { - #ast{ fail } - } - - ast::ty_infer => { - #ast{ fail } - } + } +} - ast::ty_vec(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ std::serialization::read_to_vec($(d), $(l)) } - } +fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { + do fields.map |field| { + let (ident, mutbl) = match field.node.kind { + ast::named_field(ident, mutbl, _) => (ident, mutbl), + _ => fail ~"[auto_serialize] does not support \ + unnamed fields", + }; - ast::ty_fixed_length(_, _) => { - cx.span_unimpl(ty.span, ~"deserialization for fixed length types"); - } + { + span: field.span, + ident: ident, + mutbl: match mutbl { + ast::class_mutable => ast::m_mutbl, + ast::class_immutable => ast::m_imm, + }, + } } } -fn mk_deser_fn(cx: ext_ctxt, span: span, - name: ast::ident, tps: ~[ast::ty_param], - f: fn(ext_ctxt, deser_tps_map, -v: @ast::expr) -> @ast::expr) - -> @ast::item { - let ext_cx = cx; // required for #ast - - let tp_types = vec::map(tps, |tp| cx.ty_path(span, ~[tp.ident], ~[])); - let v_ty = cx.ty_path(span, ~[name], tp_types); - - let tp_inputs = - vec::map(tps, |tp| - {mode: ast::expl(ast::by_ref), - ty: cx.ty_fn(span, - ~[], - cx.ty_path(span, ~[tp.ident], ~[])), - ident: cx.ident_of(~"__d" + cx.str_of(tp.ident)), - id: cx.next_id()}); - - debug!("tp_inputs = %?", tp_inputs); - - let deser_inputs: ~[ast::arg] = - vec::append(~[{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - ident: cx.ident_of(~"__d"), - id: cx.next_id()}], - tp_inputs); - - let tps_map = map::HashMap(); - for vec::each2(tps, tp_inputs) |tp, arg| { - let arg_ident = arg.ident; - tps_map.insert( - tp.ident, - fn@() -> @ast::expr { - let f = cx.var_ref(span, arg_ident); - #ast{ $(f)() } - }); +fn mk_ser_fields( + cx: ext_ctxt, + span: span, + fields: ~[field] +) -> ~[@ast::stmt] { + do fields.mapi |idx, field| { + // ast for `|| self.$(name).serialize(__s)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"self"), + field.ident + ), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` + cx.stmt( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ) + ) } +} - let deser_bnds = @~[ - ast::bound_trait(cx.ty_path( +fn mk_deser_fields( + cx: ext_ctxt, + span: span, + fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] +) -> ~[ast::field] { + do fields.mapi |idx, field| { + // ast for `|| std::serialization::deserialize(__d)` + let expr_lambda = cx.lambda( + cx.expr_blk( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ) + ); + + // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` + let expr: @ast::expr = cx.expr_call( span, - ~[cx.ident_of(~"std"), cx.ident_of(~"serialization"), - cx.ident_of(~"Deserializer")], - ~[]))]; - - let deser_tps: ~[ast::ty_param] = - vec::append(~[{ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: deser_bnds}], - vec::map(tps, |tp| { - let cloned = cx.clone_ty_param(*tp); - {bounds: @(vec::append(*cloned.bounds, - ~[ast::bound_copy])), - .. cloned} - })); - - let deser_blk = cx.expr_blk(f(cx, tps_map, #ast[expr]{__d})); - - @{ident: cx.ident_of(~"deserialize_" + cx.str_of(name)), - attrs: ~[], - id: cx.next_id(), - node: ast::item_fn({inputs: deser_inputs, - output: v_ty, - cf: ast::return_val}, - ast::impure_fn, - deser_tps, - deser_blk), - vis: ast::public, - span: span} + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ); + + { + node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, + span: span, + } + } } -fn ty_fns(cx: ext_ctxt, name: ast::ident, - ty: @ast::ty, tps: ~[ast::ty_param]) - -> ~[@ast::item] { +fn mk_enum_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_ser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_ser_impl(cx, span, ident, tps, body) +} - let span = ty.span; - ~[ - mk_ser_fn(cx, span, name, tps, |a,b,c,d| ser_ty(a, b, ty, move c, - move d)), - mk_deser_fn(cx, span, name, tps, |a,b,c| deser_ty(a, b, ty, move c)) - ] +fn mk_enum_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_deser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_deser_impl(cx, span, ident, tps, body) } -fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident, - e_span: span, variants: ~[ast::variant], - -s: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt] { - let ext_cx = cx; - let arms = do vec::from_fn(vec::len(variants)) |vidx| { - let variant = variants[vidx]; - let v_span = variant.span; - let v_name = variant.node.name; +fn ser_variant( + cx: ext_ctxt, + span: span, + v_name: ast::ident, + v_idx: uint, + args: ~[ast::variant_arg] +) -> ast::arm { + // Name the variant arguments. + let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); + + // Bind the names to the variant argument type. + let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); + + let pat_node = if pats.is_empty() { + ast::pat_ident( + ast::bind_by_implicit_ref, + cx.path(span, ~[v_name]), + None + ) + } else { + ast::pat_enum( + cx.path(span, ~[v_name]), + Some(pats) + ) + }; - match variant.node.kind { - ast::tuple_variant_kind(args) => { - let variant_tys = vec::map(args, |a| a.ty); - - ser_variant( - cx, tps, variant_tys, v_span, cx.clone(s), - - // Generate pattern var(v1, v2, v3) - |pats| { - if vec::is_empty(pats) { - ast::pat_ident(ast::bind_by_implicit_ref, - cx.path(v_span, ~[v_name]), - None) - } else { - ast::pat_enum(cx.path(v_span, ~[v_name]), - Some(pats)) - } - }, + let pat = @{ + id: cx.next_id(), + node: pat_node, + span: span, + }; - // Generate body s.emit_enum_variant("foo", 0u, - // 3u, {|| blk }) - |-s, blk| { - let v_name = cx.lit_str(v_span, @cx.str_of(v_name)); - let v_id = cx.lit_uint(v_span, vidx); - let sz = cx.lit_uint(v_span, vec::len(variant_tys)); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant($(v_name), $(v_id), - $(sz), $(body)) - } - }, + let stmts = do args.mapi |a_idx, _arg| { + // ast for `__s.emit_enum_variant_arg` + let expr_emit = cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant_arg") + ); - // Generate s.emit_enum_variant_arg(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(v_span, i); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant_arg($(idx), $(body)) - } - }) - } - _ => - fail ~"struct variants unimplemented for auto serialize" - } + // ast for `|| $(v).serialize(__s)` + let expr_serialize = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_path(span, ~[names[a_idx]]), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` + cx.stmt( + cx.expr_call( + span, + expr_emit, + ~[cx.lit_uint(span, a_idx), expr_serialize] + ) + ) }; - let lam = cx.lambda(cx.blk(e_span, ~[cx.alt_stmt(arms, e_span, move v)])); - let e_name = cx.lit_str(e_span, @cx.str_of(e_name)); - ~[#ast[stmt]{ $(s).emit_enum($(e_name), $(lam)) }] -} -fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident, - e_span: span, variants: ~[ast::variant], - -d: @ast::expr) -> @ast::expr { - let ext_cx = cx; - let mut arms: ~[ast::arm] = do vec::from_fn(vec::len(variants)) |vidx| { - let variant = variants[vidx]; - let v_span = variant.span; - let v_name = variant.node.name; + // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant") + ), + ~[ + cx.lit_str(span, @cx.str_of(v_name)), + cx.lit_uint(span, v_idx), + cx.lit_uint(span, stmts.len()), + cx.lambda_stmts(span, stmts), + ] + ); + + { pats: ~[pat], guard: None, body: cx.expr_blk(body) } +} - let body; +fn mk_enum_ser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let arms = do variants.mapi |v_idx, variant| { match variant.node.kind { - ast::tuple_variant_kind(args) => { - let tys = vec::map(args, |a| a.ty); - - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(v_span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_enum_variant_arg($(idx), $(body)) } - }; - - body = { - if vec::is_empty(tys) { - // for a nullary variant v, do "v" - cx.var_ref(v_span, v_name) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - cx.expr(v_span, ast::expr_call( - cx.var_ref(v_span, v_name), arg_exprs, false)) - } - }; - } + ast::tuple_variant_kind(args) => + ser_variant(cx, span, variant.node.name, v_idx, args), ast::struct_variant_kind(*) => fail ~"struct variants unimplemented", ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented" + fail ~"enum variants unimplemented", } + }; - {pats: ~[@{id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(v_span, vidx)), - span: v_span}], - guard: None, - body: cx.expr_blk(body)} + // ast for `match *self { $(arms) }` + let match_expr = cx.expr( + span, + ast::expr_match( + cx.expr( + span, + ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) + ), + arms + ) + ); + + // ast for `__s.emit_enum($(name), || $(match_expr))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + cx.lambda_expr(match_expr), + ] + ) +} + +fn mk_enum_deser_variant_nary( + cx: ext_ctxt, + span: span, + name: ast::ident, + args: ~[ast::variant_arg] +) -> @ast::expr { + let args = do args.mapi |idx, _arg| { + // ast for `|| std::serialization::deserialize(__d)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ); + + // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant_arg") + ), + ~[cx.lit_uint(span, idx), expr_lambda] + ) }; - let impossible_case = {pats: ~[@{id: cx.next_id(), - node: ast::pat_wild, - span: e_span}], - guard: None, - // FIXME #3198: proper error message - body: cx.expr_blk(cx.expr(e_span, - ast::expr_fail(None)))}; - arms += ~[impossible_case]; - - // Generate code like: - let e_name = cx.lit_str(e_span, @cx.str_of(e_name)); - let alt_expr = cx.expr(e_span, - ast::expr_match(#ast{__i}, arms)); - let var_lambda = #ast{ |__i| $(alt_expr) }; - let read_var = #ast{ $(cx.clone(d)).read_enum_variant($(var_lambda)) }; - let read_lambda = cx.lambda(cx.expr_blk(read_var)); - #ast{ $(d).read_enum($(e_name), $(read_lambda)) } + // ast for `$(name)($(args))` + cx.expr_call(span, cx.expr_path(span, ~[name]), args) } -fn enum_fns(cx: ext_ctxt, e_name: ast::ident, e_span: span, - variants: ~[ast::variant], tps: ~[ast::ty_param]) - -> ~[@ast::item] { - ~[ - mk_ser_fn(cx, e_span, e_name, tps, - |a,b,c,d| ser_enum(a, b, e_name, e_span, variants, move c, - move d)), - mk_deser_fn(cx, e_span, e_name, tps, - |a,b,c| deser_enum(a, b, e_name, e_span, variants, move c)) - ] +fn mk_enum_deser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let mut arms = do variants.mapi |v_idx, variant| { + let body = match variant.node.kind { + ast::tuple_variant_kind(args) => { + if args.is_empty() { + // for a nullary variant v, do "v" + cx.expr_path(span, ~[variant.node.name]) + } else { + // for an n-ary variant v, do "v(a_1, ..., a_n)" + mk_enum_deser_variant_nary( + cx, + span, + variant.node.name, + args + ) + } + }, + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + }; + + let pat = @{ + id: cx.next_id(), + node: ast::pat_lit(cx.lit_uint(span, v_idx)), + span: span, + }; + + { + pats: ~[pat], + guard: None, + body: cx.expr_blk(body), + } + }; + + let impossible_case = { + pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], + guard: None, + + // FIXME(#3198): proper error message + body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), + }; + + arms.push(impossible_case); + + // ast for `|i| { match i { $(arms) } }` + let expr_lambda = cx.expr( + span, + ast::expr_fn_block( + { + inputs: ~[{ + mode: ast::infer(cx.next_id()), + ty: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span + }, + ident: cx.ident_of(~"i"), + id: cx.next_id(), + }], + output: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span, + }, + cf: ast::return_val, + }, + cx.expr_blk( + cx.expr( + span, + ast::expr_match(cx.expr_var(span, ~"i"), arms) + ) + ), + @~[] + ) + ); + + // ast for `__d.read_enum_variant($(expr_lambda))` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant") + ), + ~[expr_lambda] + ) + ); + + // ast for `__d.read_enum($(e_name), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + expr_lambda + ] + ) } diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs deleted file mode 100644 index 99f837a4c84..00000000000 --- a/src/libsyntax/ext/auto_serialize2.rs +++ /dev/null @@ -1,1025 +0,0 @@ -/* - -The compiler code necessary to implement the #[auto_serialize2] and -#[auto_deserialize2] extension. The idea here is that type-defining items may -be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause -us to generate a little companion module with the same name as the item. - -For example, a type like: - - #[auto_serialize2] - #[auto_deserialize2] - struct Node {id: uint} - -would generate two implementations like: - - impl Node: Serializable { - fn serialize<S: Serializer>(s: &S) { - do s.emit_struct("Node") { - s.emit_field("id", 0, || s.emit_uint(self)) - } - } - } - - impl node_id: Deserializable { - static fn deserialize<D: Deserializer>(d: &D) -> Node { - do d.read_struct("Node") { - Node { - id: d.read_field(~"x", 0, || deserialize(d)) - } - } - } - } - -Other interesting scenarios are whe the item has type parameters or -references other non-built-in types. A type definition like: - - #[auto_serialize2] - #[auto_deserialize2] - type spanned<T> = {node: T, span: span}; - -would yield functions like: - - impl<T: Serializable> spanned<T>: Serializable { - fn serialize<S: Serializer>(s: &S) { - do s.emit_rec { - s.emit_field("node", 0, || self.node.serialize(s)); - s.emit_field("span", 1, || self.span.serialize(s)); - } - } - } - - impl<T: Deserializable> spanned<T>: Deserializable { - static fn deserialize<D: Deserializer>(d: &D) -> spanned<T> { - do d.read_rec { - { - node: d.read_field(~"node", 0, || deserialize(d)), - span: d.read_field(~"span", 1, || deserialize(d)), - } - } - } - } - -FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the -standard library. - -Misc notes: ------------ - -I use move mode arguments for ast nodes that will get inserted as is -into the tree. This is intended to prevent us from inserting the same -node twice. - -*/ - -use base::*; -use codemap::span; -use std::map; -use std::map::HashMap; - -export expand_auto_serialize; -export expand_auto_deserialize; - -// Transitional reexports so qquote can find the paths it is looking for -mod syntax { - pub use ext; - pub use parse; -} - -fn expand_auto_serialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_serialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_serialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_serialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let ser_impl = mk_rec_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let ser_impl = mk_struct_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_enum(enum_def, tps) => { - let ser_impl = mk_enum_ser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_serialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -fn expand_auto_deserialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_deserialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_deserialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_deserialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let deser_impl = mk_rec_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let deser_impl = mk_struct_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_enum(enum_def, tps) => { - let deser_impl = mk_enum_deser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_deserialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -priv impl ext_ctxt { - fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, strs))) - } - - fn expr_var(span: span, var: ~str) -> @ast::expr { - self.expr_path(span, ~[self.ident_of(var)]) - } - - fn expr_field( - span: span, - expr: @ast::expr, - ident: ast::ident - ) -> @ast::expr { - self.expr(span, ast::expr_field(expr, ident, ~[])) - } - - fn expr_call( - span: span, - expr: @ast::expr, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, ast::expr_call(expr, args, false)) - } - - fn lambda_expr(expr: @ast::expr) -> @ast::expr { - self.lambda(self.expr_blk(expr)) - } - - fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr { - self.lambda(self.blk(span, stmts)) - } -} - -fn mk_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - path: @ast::path, - tps: ~[ast::ty_param], - f: fn(@ast::ty) -> @ast::method -) -> @ast::item { - // All the type parameters need to bound to the trait. - let trait_tps = do tps.map |tp| { - let t_bound = ast::bound_trait(@{ - id: cx.next_id(), - node: ast::ty_path(path, cx.next_id()), - span: span, - }); - - { - ident: tp.ident, - id: cx.next_id(), - bounds: @vec::append(~[t_bound], *tp.bounds) - } - }; - - let opt_trait = Some(@{ - path: path, - ref_id: cx.next_id(), - impl_id: cx.next_id(), - }); - - let ty = cx.ty_path( - span, - ~[ident], - tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) - ); - - @{ - // This is a new-style impl declaration. - // XXX: clownshoes - ident: ast::token::special_idents::clownshoes_extensions, - attrs: ~[], - id: cx.next_id(), - node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), - vis: ast::public, - span: span, - } -} - -fn mk_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Serializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) - ) -} - -fn mk_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Deserializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) - ) -} - -fn mk_ser_method( - cx: ext_ctxt, - span: span, - ser_body: ast::blk -) -> @ast::method { - let ser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializer"), - ], - ~[] - ); - - let ser_tps = ~[{ - ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(ser_bound)], - }]; - - let ty_s = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let ser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_s, - ident: cx.ident_of(~"__s"), - id: cx.next_id(), - }]; - - let ser_output = @{ - id: cx.next_id(), - node: ast::ty_nil, - span: span, - }; - - let ser_decl = { - inputs: ser_inputs, - output: ser_output, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"serialize"), - attrs: ~[], - tps: ser_tps, - self_ty: { node: ast::sty_region(ast::m_imm), span: span }, - purity: ast::impure_fn, - decl: ser_decl, - body: ser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_deser_method( - cx: ext_ctxt, - span: span, - ty: @ast::ty, - deser_body: ast::blk -) -> @ast::method { - let deser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializer"), - ], - ~[] - ); - - let deser_tps = ~[{ - ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(deser_bound)], - }]; - - let ty_d = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let deser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_d, - ident: cx.ident_of(~"__d"), - id: cx.next_id(), - }]; - - let deser_decl = { - inputs: deser_inputs, - output: ty, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"deserialize"), - attrs: ~[], - tps: deser_tps, - self_ty: { node: ast::sty_static, span: span }, - purity: ast::impure_fn, - decl: deser_decl, - body: deser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_rec_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `__s.emit_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_rec") - ), - ~[cx.lambda_stmts(span, fields)] - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_rec_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `read_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_rec") - ), - ~[ - cx.lambda_expr( - cx.expr( - span, - ast::expr_rec(fields, None) - ) - ) - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn mk_struct_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `__s.emit_struct($(name), || $(fields))` - let ser_body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_stmts(span, fields), - ] - ); - - mk_ser_impl(cx, span, ident, tps, ser_body) -} - -fn mk_struct_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `read_struct($(name), || $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_expr( - cx.expr( - span, - ast::expr_struct( - cx.path(span, ~[ident]), - fields, - None - ) - ) - ), - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -// Records and structs don't have the same fields types, but they share enough -// that if we extract the right subfields out we can share the serialization -// generator code. -type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; - -fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { - do fields.map |field| { - { - span: field.span, - ident: field.node.ident, - mutbl: field.node.mt.mutbl, - } - } -} - -fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { - do fields.map |field| { - let (ident, mutbl) = match field.node.kind { - ast::named_field(ident, mutbl, _) => (ident, mutbl), - _ => fail ~"[auto_serialize2] does not support \ - unnamed fields", - }; - - { - span: field.span, - ident: ident, - mutbl: match mutbl { - ast::class_mutable => ast::m_mutbl, - ast::class_immutable => ast::m_imm, - }, - } - } -} - -fn mk_ser_fields( - cx: ext_ctxt, - span: span, - fields: ~[field] -) -> ~[@ast::stmt] { - do fields.mapi |idx, field| { - // ast for `|| self.$(name).serialize(__s)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"self"), - field.ident - ), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` - cx.stmt( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ) - ) - } -} - -fn mk_deser_fields( - cx: ext_ctxt, - span: span, - fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] -) -> ~[ast::field] { - do fields.mapi |idx, field| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda( - cx.expr_blk( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ) - ); - - // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` - let expr: @ast::expr = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ); - - { - node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, - span: span, - } - } -} - -fn mk_enum_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_ser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_enum_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_deser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn ser_variant( - cx: ext_ctxt, - span: span, - v_name: ast::ident, - v_idx: uint, - args: ~[ast::variant_arg] -) -> ast::arm { - // Name the variant arguments. - let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); - - // Bind the names to the variant argument type. - let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); - - let pat_node = if pats.is_empty() { - ast::pat_ident( - ast::bind_by_implicit_ref, - cx.path(span, ~[v_name]), - None - ) - } else { - ast::pat_enum( - cx.path(span, ~[v_name]), - Some(pats) - ) - }; - - let pat = @{ - id: cx.next_id(), - node: pat_node, - span: span, - }; - - let stmts = do args.mapi |a_idx, _arg| { - // ast for `__s.emit_enum_variant_arg` - let expr_emit = cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant_arg") - ); - - // ast for `|| $(v).serialize(__s)` - let expr_serialize = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_path(span, ~[names[a_idx]]), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` - cx.stmt( - cx.expr_call( - span, - expr_emit, - ~[cx.lit_uint(span, a_idx), expr_serialize] - ) - ) - }; - - // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant") - ), - ~[ - cx.lit_str(span, @cx.str_of(v_name)), - cx.lit_uint(span, v_idx), - cx.lit_uint(span, stmts.len()), - cx.lambda_stmts(span, stmts), - ] - ); - - { pats: ~[pat], guard: None, body: cx.expr_blk(body) } -} - -fn mk_enum_ser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let arms = do variants.mapi |v_idx, variant| { - match variant.node.kind { - ast::tuple_variant_kind(args) => - ser_variant(cx, span, variant.node.name, v_idx, args), - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - } - }; - - // ast for `match *self { $(arms) }` - let match_expr = cx.expr( - span, - ast::expr_match( - cx.expr( - span, - ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) - ), - arms - ) - ); - - // ast for `__s.emit_enum($(name), || $(match_expr))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - cx.lambda_expr(match_expr), - ] - ) -} - -fn mk_enum_deser_variant_nary( - cx: ext_ctxt, - span: span, - name: ast::ident, - args: ~[ast::variant_arg] -) -> @ast::expr { - let args = do args.mapi |idx, _arg| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ); - - // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant_arg") - ), - ~[cx.lit_uint(span, idx), expr_lambda] - ) - }; - - // ast for `$(name)($(args))` - cx.expr_call(span, cx.expr_path(span, ~[name]), args) -} - -fn mk_enum_deser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let mut arms = do variants.mapi |v_idx, variant| { - let body = match variant.node.kind { - ast::tuple_variant_kind(args) => { - if args.is_empty() { - // for a nullary variant v, do "v" - cx.expr_path(span, ~[variant.node.name]) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - mk_enum_deser_variant_nary( - cx, - span, - variant.node.name, - args - ) - } - }, - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - }; - - let pat = @{ - id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(span, v_idx)), - span: span, - }; - - { - pats: ~[pat], - guard: None, - body: cx.expr_blk(body), - } - }; - - let impossible_case = { - pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], - guard: None, - - // FIXME(#3198): proper error message - body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), - }; - - arms.push(impossible_case); - - // ast for `|i| { match i { $(arms) } }` - let expr_lambda = cx.expr( - span, - ast::expr_fn_block( - { - inputs: ~[{ - mode: ast::infer(cx.next_id()), - ty: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span - }, - ident: cx.ident_of(~"i"), - id: cx.next_id(), - }], - output: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span, - }, - cf: ast::return_val, - }, - cx.expr_blk( - cx.expr( - span, - ast::expr_match(cx.expr_var(span, ~"i"), arms) - ) - ), - @~[] - ) - ); - - // ast for `__d.read_enum_variant($(expr_lambda))` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant") - ), - ~[expr_lambda] - ) - ); - - // ast for `__d.read_enum($(e_name), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - expr_lambda - ] - ) -} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9a31cc1d8f6..5b4cc23ce09 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,7 +1,7 @@ use std::map::HashMap; use parse::parser; use diagnostic::span_handler; -use codemap::{codemap, span, expn_info, expanded_from}; +use codemap::{CodeMap, span, expn_info, expanded_from}; // obsolete old-style #macro code: // @@ -80,14 +80,12 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { builtin_item_tt( ext::tt::macro_rules::add_new_extension)); syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); - syntax_expanders.insert(~"auto_serialize", - item_decorator(ext::auto_serialize::expand)); syntax_expanders.insert( - ~"auto_serialize2", - item_decorator(ext::auto_serialize2::expand_auto_serialize)); + ~"auto_serialize", + item_decorator(ext::auto_serialize::expand_auto_serialize)); syntax_expanders.insert( - ~"auto_deserialize2", - item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + ~"auto_deserialize", + item_decorator(ext::auto_serialize::expand_auto_deserialize)); syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); syntax_expanders.insert(~"concat_idents", builtin(ext::concat_idents::expand_syntax_ext)); @@ -122,12 +120,11 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { return syntax_expanders; } - // One of these is made during expansion and incrementally updated as we go; // when a macro expansion occurs, the resulting nodes have the backtrace() // -> expn_info of their expansion context stored into their span. trait ext_ctxt { - fn codemap() -> codemap; + fn codemap() -> CodeMap; fn parse_sess() -> parse::parse_sess; fn cfg() -> ast::crate_cfg; fn print_backtrace(); @@ -159,7 +156,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess, mut mod_path: ~[ast::ident], mut trace_mac: bool}; impl ctxt_repr: ext_ctxt { - fn codemap() -> codemap { self.parse_sess.cm } + fn codemap() -> CodeMap { self.parse_sess.cm } fn parse_sess() -> parse::parse_sess { self.parse_sess } fn cfg() -> ast::crate_cfg { self.cfg } fn print_backtrace() { } @@ -234,7 +231,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess, mut mod_path: ~[], mut trace_mac: false }; - move (imp as ext_ctxt) + move ((move imp) as ext_ctxt) } fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: ~str) -> ~str { @@ -272,21 +269,21 @@ fn get_mac_args(cx: ext_ctxt, sp: span, arg: ast::mac_arg, match max { Some(max) if ! (min <= elts_len && elts_len <= max) => { cx.span_fatal(sp, - fmt!("#%s takes between %u and %u arguments.", + fmt!("%s! takes between %u and %u arguments.", name, min, max)); } None if ! (min <= elts_len) => { - cx.span_fatal(sp, fmt!("#%s needs at least %u arguments.", + cx.span_fatal(sp, fmt!("%s! needs at least %u arguments.", name, min)); } _ => return elts /* we are good */ } } _ => { - cx.span_fatal(sp, fmt!("#%s: malformed invocation", name)) + cx.span_fatal(sp, fmt!("%s!: malformed invocation", name)) } }, - None => cx.span_fatal(sp, fmt!("#%s: missing arguments", name)) + None => cx.span_fatal(sp, fmt!("%s!: missing arguments", name)) } } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 8cecceb2e55..37fb0f05cbd 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -1,6 +1,6 @@ /* - * The compiler code necessary to support the #env extension. Eventually this + * The compiler code necessary to support the env! extension. Eventually this * should all get sucked into either the compiler syntax extension plugin * interface. */ @@ -15,7 +15,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg, // FIXME (#2248): if this was more thorough it would manufacture an // Option<str> rather than just an maybe-empty string. - let var = expr_to_str(cx, args[0], ~"#env requires a string"); + let var = expr_to_str(cx, args[0], ~"env! requires a string"); match os::getenv(var) { option::None => return mk_uniq_str(cx, sp, ~""), option::Some(s) => return mk_uniq_str(cx, sp, s) diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index ea493eab561..e24575f6cd3 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -1,7 +1,7 @@ /* - * The compiler code necessary to support the #fmt extension. Eventually this + * The compiler code necessary to support the fmt! extension. Eventually this * should all get sucked into either the standard library extfmt module or the * compiler syntax extension plugin interface. */ @@ -16,7 +16,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg, let args = get_mac_args_no_max(cx, sp, arg, 1u, ~"fmt"); let fmt = expr_to_str(cx, args[0], - ~"first argument to #fmt must be a string literal."); + ~"first argument to fmt! must be a string literal."); let fmtspan = args[0].span; debug!("Format string:"); log(debug, fmt); @@ -76,7 +76,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, let count_is_args = ~[count_lit]; return mk_call(cx, sp, count_is_path, count_is_args); } - _ => cx.span_unimpl(sp, ~"unimplemented #fmt conversion") + _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion") } } fn make_ty(cx: ext_ctxt, sp: span, t: Ty) -> @ast::expr { @@ -133,7 +133,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, _ => return false } } - let unsupported = ~"conversion not supported in #fmt string"; + let unsupported = ~"conversion not supported in fmt! string"; match cnv.param { option::None => (), _ => cx.span_unimpl(sp, unsupported) @@ -145,14 +145,14 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, if !is_signed_type(cnv) { cx.span_fatal(sp, ~"+ flag only valid in " + - ~"signed #fmt conversion"); + ~"signed fmt! conversion"); } } FlagSpaceForSign => { if !is_signed_type(cnv) { cx.span_fatal(sp, ~"space flag only valid in " + - ~"signed #fmt conversions"); + ~"signed fmt! conversions"); } } FlagLeftZeroPad => (), @@ -252,7 +252,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, n += 1u; if n >= nargs { cx.span_fatal(sp, - ~"not enough arguments to #fmt " + + ~"not enough arguments to fmt! " + ~"for the given format string"); } debug!("Building conversion:"); @@ -267,7 +267,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, if expected_nargs < nargs { cx.span_fatal - (sp, fmt!("too many arguments to #fmt. found %u, expected %u", + (sp, fmt!("too many arguments to fmt!. found %u, expected %u", nargs, expected_nargs)); } diff --git a/src/libsyntax/ext/pipes.rs b/src/libsyntax/ext/pipes.rs index ad4984c5558..4d04552bfa1 100644 --- a/src/libsyntax/ext/pipes.rs +++ b/src/libsyntax/ext/pipes.rs @@ -37,7 +37,7 @@ use codemap::span; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use parse::common::parser_common; use pipes::parse_proto::proto_parser; @@ -52,7 +52,7 @@ fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, cx.parse_sess().interner, None, tt); let rdr = tt_rdr as reader; - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let proto = rust_parser.parse_proto(cx.str_of(id)); diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 4da9992b0dd..f10cbc2a589 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -28,17 +28,17 @@ fn empty_span() -> span { } trait append_types { - fn add_ty(ty: @ast::ty) -> @ast::path; - fn add_tys(+tys: ~[@ast::ty]) -> @ast::path; + fn add_ty(ty: @ast::Ty) -> @ast::path; + fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path; } impl @ast::path: append_types { - fn add_ty(ty: @ast::ty) -> @ast::path { + fn add_ty(ty: @ast::Ty) -> @ast::path { @{types: vec::append_one(self.types, ty), .. *self} } - fn add_tys(+tys: ~[@ast::ty]) -> @ast::path { + fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path { @{types: vec::append(self.types, tys), .. *self} } @@ -47,18 +47,18 @@ impl @ast::path: append_types { trait ext_ctxt_ast_builder { fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound]) -> ast::ty_param; - fn arg(name: ident, ty: @ast::ty) -> ast::arg; + fn arg(name: ident, ty: @ast::Ty) -> ast::arg; fn expr_block(e: @ast::expr) -> ast::blk; - fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl; + fn fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; fn item(name: ident, span: span, +node: ast::item_) -> @ast::item; fn item_fn_poly(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +ty_params: ~[ast::ty_param], +body: ast::blk) -> @ast::item; fn item_fn(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +body: ast::blk) -> @ast::item; fn item_enum_poly(name: ident, span: span, @@ -66,17 +66,17 @@ trait ext_ctxt_ast_builder { +ty_params: ~[ast::ty_param]) -> @ast::item; fn item_enum(name: ident, span: span, +enum_definition: ast::enum_def) -> @ast::item; - fn variant(name: ident, span: span, +tys: ~[@ast::ty]) -> ast::variant; + fn variant(name: ident, span: span, +tys: ~[@ast::Ty]) -> ast::variant; fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item; - fn ty_path_ast_builder(path: @ast::path) -> @ast::ty; + fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty; fn item_ty_poly(name: ident, span: span, - ty: @ast::ty, + ty: @ast::Ty, +params: ~[ast::ty_param]) -> @ast::item; - fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item; - fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty]; - fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field; - fn ty_rec(+v: ~[ast::ty_field]) -> @ast::ty; + fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item; + fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty]; + fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field; + fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty; fn field_imm(name: ident, e: @ast::expr) -> ast::field; fn rec(+v: ~[ast::field]) -> @ast::expr; fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; @@ -84,11 +84,11 @@ trait ext_ctxt_ast_builder { fn stmt_expr(e: @ast::expr) -> @ast::stmt; fn block_expr(b: ast::blk) -> @ast::expr; fn empty_span() -> span; - fn ty_option(ty: @ast::ty) -> @ast::ty; + fn ty_option(ty: @ast::Ty) -> @ast::Ty; } impl ext_ctxt: ext_ctxt_ast_builder { - fn ty_option(ty: @ast::ty) -> @ast::ty { + fn ty_option(ty: @ast::Ty) -> @ast::Ty { self.ty_path_ast_builder(path(~[self.ident_of(~"Option")], self.empty_span()) .add_ty(ty)) @@ -146,18 +146,18 @@ impl ext_ctxt: ext_ctxt_ast_builder { span: self.empty_span()} } - fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field { + fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field { {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } }, span: self.empty_span()} } - fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::ty { + fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_rec(fields), span: self.empty_span()} } - fn ty_infer() -> @ast::ty { + fn ty_infer() -> @ast::Ty { @{id: self.next_id(), node: ast::ty_infer, span: self.empty_span()} @@ -169,7 +169,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { {ident: id, id: self.next_id(), bounds: @bounds} } - fn arg(name: ident, ty: @ast::ty) -> ast::arg { + fn arg(name: ident, ty: @ast::Ty) -> ast::arg { {mode: ast::infer(self.next_id()), ty: ty, ident: name, @@ -192,7 +192,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { } fn fn_decl(+inputs: ~[ast::arg], - output: @ast::ty) -> ast::fn_decl { + output: @ast::Ty) -> ast::fn_decl { {inputs: inputs, output: output, cf: ast::return_val} @@ -224,7 +224,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_fn_poly(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +ty_params: ~[ast::ty_param], +body: ast::blk) -> @ast::item { self.item(name, @@ -237,7 +237,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_fn(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +body: ast::blk) -> @ast::item { self.item_fn_poly(name, inputs, output, ~[], body) } @@ -256,7 +256,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn variant(name: ident, span: span, - +tys: ~[@ast::ty]) -> ast::variant { + +tys: ~[@ast::Ty]) -> ast::variant { let args = tys.map(|ty| {ty: *ty, id: self.next_id()}); {node: {name: name, @@ -278,13 +278,13 @@ impl ext_ctxt: ext_ctxt_ast_builder { items: items})) } - fn ty_path_ast_builder(path: @ast::path) -> @ast::ty { + fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: path.span} } - fn ty_nil_ast_builder() -> @ast::ty { + fn ty_nil_ast_builder() -> @ast::Ty { @{id: self.next_id(), node: ast::ty_nil, span: self.empty_span()} @@ -292,16 +292,16 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_ty_poly(name: ident, span: span, - ty: @ast::ty, + ty: @ast::Ty, +params: ~[ast::ty_param]) -> @ast::item { self.item(name, span, ast::item_ty(ty, params)) } - fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item { + fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item { self.item_ty_poly(name, span, ty, ~[]) } - fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] { + fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty] { ty_params.map(|p| self.ty_path_ast_builder( path(~[p.ident], self.empty_span()))) } diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs index 5fcc00ef012..fcc0c84a4ff 100644 --- a/src/libsyntax/ext/pipes/check.rs +++ b/src/libsyntax/ext/pipes/check.rs @@ -38,7 +38,7 @@ impl ext_ctxt: proto::visitor<(), (), ()> { } } - fn visit_message(name: ~str, _span: span, _tys: &[@ast::ty], + fn visit_message(name: ~str, _span: span, _tys: &[@ast::Ty], this: state, next: next_state) { match next { Some({state: next, tys: next_tys}) => { @@ -68,4 +68,4 @@ impl ext_ctxt: proto::visitor<(), (), ()> { None => () } } -} \ No newline at end of file +} diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs index 5c15b616b4a..8f2b92a720c 100644 --- a/src/libsyntax/ext/pipes/parse_proto.rs +++ b/src/libsyntax/ext/pipes/parse_proto.rs @@ -10,7 +10,7 @@ trait proto_parser { fn parse_state(proto: protocol); } -impl parser: proto_parser { +impl parser::Parser: proto_parser { fn parse_proto(id: ~str) -> protocol { let proto = protocol(id, self.span); diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 874ea01e9b0..7e1cbe9ad0d 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -181,7 +181,7 @@ impl message: gen_send { } } - fn to_ty(cx: ext_ctxt) -> @ast::ty { + fn to_ty(cx: ext_ctxt) -> @ast::Ty { cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span()) .add_tys(cx.ty_vars(self.get_params()))) } @@ -360,7 +360,7 @@ impl protocol: gen_init { }} } - fn buffer_ty_path(cx: ext_ctxt) -> @ast::ty { + fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty { let mut params: ~[ast::ty_param] = ~[]; for (copy self.states).each |s| { for s.ty_params.each |tp| { @@ -444,13 +444,13 @@ impl ~[@ast::item]: to_source { } } -impl @ast::ty: to_source { +impl @ast::Ty: to_source { fn to_source(cx: ext_ctxt) -> ~str { ty_to_str(self, cx.parse_sess().interner) } } -impl ~[@ast::ty]: to_source { +impl ~[@ast::Ty]: to_source { fn to_source(cx: ext_ctxt) -> ~str { str::connect(self.map(|i| i.to_source(cx)), ~", ") } diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index 6d58d209fcf..229e55fdfcc 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -18,7 +18,7 @@ impl direction : cmp::Eq { } impl direction: ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { match self { send => ~"Send", recv => ~"Recv" @@ -35,11 +35,11 @@ impl direction { } } -type next_state = Option<{state: ~str, tys: ~[@ast::ty]}>; +type next_state = Option<{state: ~str, tys: ~[@ast::Ty]}>; enum message { // name, span, data, current state, next state - message(~str, span, ~[@ast::ty], state, next_state) + message(~str, span, ~[@ast::Ty], state, next_state) } impl message { @@ -78,7 +78,7 @@ enum state { impl state { fn add_message(name: ~str, span: span, - +data: ~[@ast::ty], next: next_state) { + +data: ~[@ast::Ty], next: next_state) { self.messages.push(message(name, span, data, self, next)); } @@ -92,7 +92,7 @@ impl state { } /// Returns the type that is used for the messages. - fn to_ty(cx: ext_ctxt) -> @ast::ty { + fn to_ty(cx: ext_ctxt) -> @ast::Ty { cx.ty_path_ast_builder (path(~[cx.ident_of(self.name)],self.span).add_tys( cx.ty_vars(self.ty_params))) @@ -200,7 +200,7 @@ impl protocol { trait visitor<Tproto, Tstate, Tmessage> { fn visit_proto(proto: protocol, st: &[Tstate]) -> Tproto; fn visit_state(state: state, m: &[Tmessage]) -> Tstate; - fn visit_message(name: ~str, spane: span, tys: &[@ast::ty], + fn visit_message(name: ~str, spane: span, tys: &[@ast::Ty], this: state, next: next_state) -> Tmessage; } diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs index 342743d8c46..af7ffaa73f5 100644 --- a/src/libsyntax/ext/qquote.rs +++ b/src/libsyntax/ext/qquote.rs @@ -1,7 +1,7 @@ use ast::{crate, expr_, mac_invoc, mac_aq, mac_var}; use parse::parser; -use parse::parser::parse_from_source_str; +use parse::parser::{Parser, parse_from_source_str}; use dvec::DVec; use parse::token::ident_interner; @@ -24,7 +24,7 @@ struct gather_item { type aq_ctxt = @{lo: uint, gather: DVec<gather_item>}; enum fragment { from_expr(@ast::expr), - from_ty(@ast::ty) + from_ty(@ast::Ty) } fn ids_ext(cx: ext_ctxt, strs: ~[~str]) -> ~[ast::ident] { @@ -68,7 +68,7 @@ impl @ast::expr: qq_helper { } fn get_fold_fn() -> ~str {~"fold_expr"} } -impl @ast::ty: qq_helper { +impl @ast::Ty: qq_helper { fn span() -> span {self.span} fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_ty(self, cx, v);} fn extract_mac() -> Option<ast::mac_> { @@ -186,13 +186,13 @@ fn expand_ast(ecx: ext_ctxt, _sp: span, }; } -fn parse_crate(p: parser) -> @ast::crate { p.parse_crate_mod(~[]) } -fn parse_ty(p: parser) -> @ast::ty { p.parse_ty(false) } -fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) } -fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() } -fn parse_pat(p: parser) -> @ast::pat { p.parse_pat(true) } +fn parse_crate(p: Parser) -> @ast::crate { p.parse_crate_mod(~[]) } +fn parse_ty(p: Parser) -> @ast::Ty { p.parse_ty(false) } +fn parse_stmt(p: Parser) -> @ast::stmt { p.parse_stmt(~[]) } +fn parse_expr(p: Parser) -> @ast::expr { p.parse_expr() } +fn parse_pat(p: Parser) -> @ast::pat { p.parse_pat(true) } -fn parse_item(p: parser) -> @ast::item { +fn parse_item(p: Parser) -> @ast::item { match p.parse_item(~[]) { Some(item) => item, None => fail ~"parse_item: parsing an item failed" @@ -200,7 +200,7 @@ fn parse_item(p: parser) -> @ast::item { } fn finish<T: qq_helper> - (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: parser) -> T) + (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: Parser) -> T) -> @ast::expr { let cm = ecx.codemap(); @@ -309,7 +309,7 @@ fn fold_crate(f: ast_fold, &&n: @ast::crate) -> @ast::crate { @f.fold_crate(*n) } fn fold_expr(f: ast_fold, &&n: @ast::expr) -> @ast::expr {f.fold_expr(n)} -fn fold_ty(f: ast_fold, &&n: @ast::ty) -> @ast::ty {f.fold_ty(n)} +fn fold_ty(f: ast_fold, &&n: @ast::Ty) -> @ast::Ty {f.fold_ty(n)} fn fold_item(f: ast_fold, &&n: @ast::item) -> @ast::item { f.fold_item(n).get() //HACK: we know we don't drop items } diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs index e16e1c55349..bec29c9a835 100644 --- a/src/libsyntax/ext/simplext.rs +++ b/src/libsyntax/ext/simplext.rs @@ -6,7 +6,7 @@ use base::*; use fold::*; use ast_util::respan; -use ast::{ident, path, ty, blk_, expr, expr_path, +use ast::{ident, path, Ty, blk_, expr, expr_path, expr_vec, expr_mac, mac_invoc, node_id, expr_index}; export add_new_extension; @@ -29,7 +29,7 @@ enum matchable { match_expr(@expr), match_path(@path), match_ident(ast::spanned<ident>), - match_ty(@ty), + match_ty(@Ty), match_block(ast::blk), match_exact, /* don't bind anything, just verify the AST traversal */ } diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index c2d4de1b423..0c7d408db7c 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -2,7 +2,7 @@ use codemap::span; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use parse::common::parser_common; fn expand_trace_macros(cx: ext_ctxt, sp: span, @@ -13,7 +13,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, cx.parse_sess().interner, None, tt); let rdr = tt_rdr as reader; - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let arg = cx.str_of(rust_parser.parse_ident()); match arg { @@ -21,7 +21,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, ~"false" => cx.set_trace_macros(false), _ => cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`") } - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let result = rust_parser.parse_expr(); base::mr_expr(result) } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 16e3454ca2c..17122b85fb3 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -1,9 +1,9 @@ // Earley-like parser for macros. use parse::token; -use parse::token::{token, EOF, to_str, nonterminal}; +use parse::token::{Token, EOF, to_str, nonterminal}; use parse::lexer::*; //resolve bug? //import parse::lexer::{reader, tt_reader, tt_reader_as_reader}; -use parse::parser::{parser,SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; //import parse::common::parser_common; use parse::common::*; //resolve bug? use parse::parse_sess; @@ -97,7 +97,7 @@ fn is_some(&&mpu: matcher_pos_up) -> bool { type matcher_pos = ~{ elts: ~[ast::matcher], // maybe should be /&? Need to understand regions. - sep: Option<token>, + sep: Option<Token>, mut idx: uint, mut up: matcher_pos_up, // mutable for swapping only matches: ~[DVec<@named_match>], @@ -122,7 +122,7 @@ fn count_names(ms: &[matcher]) -> uint { } #[allow(non_implicitly_copyable_typarams)] -fn initial_matcher_pos(ms: ~[matcher], sep: Option<token>, lo: uint) +fn initial_matcher_pos(ms: ~[matcher], sep: Option<Token>, lo: uint) -> matcher_pos { let mut match_idx_hi = 0u; for ms.each() |elt| { @@ -345,7 +345,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) built-in NTs %s or %u other options.", nts, next_eis.len())); } else if (bb_eis.len() == 0u && next_eis.len() == 0u) { - return failure(sp, ~"No rules expected the token " + return failure(sp, ~"No rules expected the token: " + to_str(rdr.interner(), tok)); } else if (next_eis.len() > 0u) { /* Now process the next token */ @@ -354,7 +354,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) } rdr.next_token(); } else /* bb_eis.len() == 1 */ { - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let ei = bb_eis.pop(); match ei.elts[ei.idx].node { @@ -381,7 +381,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) } } -fn parse_nt(p: parser, name: ~str) -> nonterminal { +fn parse_nt(p: Parser, name: ~str) -> nonterminal { match name { ~"item" => match p.parse_item(~[]) { Some(i) => token::nt_item(i), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 52369ad7207..31bc375a76d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -4,7 +4,7 @@ use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq, tt_delim}; use parse::lexer::{new_tt_reader, reader}; use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use macro_parser::{parse, parse_or_else, success, failure, named_match, matched_seq, matched_nonterminal, error}; use std::map::HashMap; @@ -86,7 +86,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(s_d, itr, Some(named_matches), ~[rhs]); - let p = parser(cx.parse_sess(), cx.cfg(), + let p = Parser(cx.parse_sess(), cx.cfg(), trncbr as reader, SOURCE_FILE); let e = p.parse_expr(); return mr_expr(e); @@ -111,4 +111,4 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, name: *cx.parse_sess().interner.get(name), ext: expr_tt({expander: exp, span: Some(sp)}) }); -} \ No newline at end of file +} diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index a8a41cca6cb..238f9db6ac5 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -2,8 +2,7 @@ use diagnostic::span_handler; use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident}; use macro_parser::{named_match, matched_seq, matched_nonterminal}; use codemap::span; -use parse::token::{EOF, INTERPOLATED, IDENT, token, nt_ident, - ident_interner}; +use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; use std::map::HashMap; export tt_reader, new_tt_reader, dup_tt_reader, tt_next_token; @@ -19,7 +18,7 @@ type tt_frame = @{ readme: ~[ast::token_tree], mut idx: uint, dotdotdoted: bool, - sep: Option<token>, + sep: Option<Token>, up: tt_frame_up, }; @@ -32,7 +31,7 @@ type tt_reader = @{ mut repeat_idx: ~[uint], mut repeat_len: ~[uint], /* cached: */ - mut cur_tok: token, + mut cur_tok: Token, mut cur_span: span }; @@ -134,7 +133,7 @@ fn lockstep_iter_size(t: token_tree, r: tt_reader) -> lis { } -fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} { +fn tt_next_token(&&r: tt_reader) -> {tok: Token, sp: span} { let ret_val = { tok: r.cur_tok, sp: r.cur_span }; while r.cur.idx >= r.cur.readme.len() { /* done with this set; pop or repeat? */ diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 088df01985e..311928dd4e0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -33,7 +33,7 @@ trait ast_fold { fn fold_pat(&&v: @pat) -> @pat; fn fold_decl(&&v: @decl) -> @decl; fn fold_expr(&&v: @expr) -> @expr; - fn fold_ty(&&v: @ty) -> @ty; + fn fold_ty(&&v: @Ty) -> @Ty; fn fold_mod(_mod) -> _mod; fn fold_foreign_mod(foreign_mod) -> foreign_mod; fn fold_variant(variant) -> variant; @@ -131,10 +131,7 @@ fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl { } fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound { - match tpb { - bound_copy | bound_send | bound_const | bound_owned => tpb, - bound_trait(ty) => bound_trait(fld.fold_ty(ty)) - } + ty_param_bound(fld.fold_ty(*tpb)) } fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param { @@ -271,23 +268,6 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) -> @ast::struct_def { - let resulting_optional_constructor; - match struct_def.ctor { - None => { - resulting_optional_constructor = None; - } - Some(constructor) => { - resulting_optional_constructor = Some({ - node: { - body: fld.fold_block(constructor.node.body), - dec: fold_fn_decl(constructor.node.dec, fld), - id: fld.new_id(constructor.node.id), - .. constructor.node - }, - .. constructor - }); - } - } let dtor = do option::map(&struct_def.dtor) |dtor| { let dtor_body = fld.fold_block(dtor.node.body); let dtor_id = fld.new_id(dtor.node.id); @@ -298,7 +278,6 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)), fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), - ctor: resulting_optional_constructor, dtor: dtor }; } @@ -585,7 +564,6 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { |f| fld.fold_struct_field(*f)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), - ctor: None, dtor: dtor }) } @@ -747,7 +725,7 @@ impl ast_fold_precursor: ast_fold { node: n, span: self.new_span(s)}; } - fn fold_ty(&&x: @ty) -> @ty { + fn fold_ty(&&x: @Ty) -> @Ty { let (n, s) = self.fold_ty(x.node, x.span, self as ast_fold); return @{id: self.new_id(x.id), node: n, span: self.new_span(s)}; } diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs index 2c04b2a1419..e38ee7ff037 100644 --- a/src/libsyntax/parse.rs +++ b/src/libsyntax/parse.rs @@ -12,7 +12,7 @@ export parse_expr_from_source_str, parse_item_from_source_str; export parse_stmt_from_source_str; export parse_from_source_str; -use parser::parser; +use parser::Parser; use attr::parser_attr; use common::parser_common; use ast::node_id; @@ -22,7 +22,7 @@ use lexer::{reader, string_reader}; use parse::token::{ident_interner, mk_ident_interner}; type parse_sess = @{ - cm: codemap::codemap, + cm: codemap::CodeMap, mut next_id: node_id, span_diagnostic: span_handler, interner: @ident_interner, @@ -40,7 +40,7 @@ fn new_parse_sess(demitter: Option<emitter>) -> parse_sess { mut chpos: 0u, mut byte_pos: 0u}; } -fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::codemap) +fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::CodeMap) -> parse_sess { return @{cm: cm, mut next_id: 1, @@ -142,7 +142,7 @@ fn parse_stmt_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg, return r; } -fn parse_from_source_str<T>(f: fn (p: parser) -> T, +fn parse_from_source_str<T>(f: fn (p: Parser) -> T, name: ~str, ss: codemap::file_substr, source: @~str, cfg: ast::crate_cfg, sess: parse_sess) @@ -170,19 +170,19 @@ fn next_node_id(sess: parse_sess) -> node_id { fn new_parser_etc_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, +name: ~str, +ss: codemap::file_substr, - source: @~str) -> (parser, string_reader) { + source: @~str) -> (Parser, string_reader) { let ftype = parser::SOURCE_FILE; let filemap = codemap::new_filemap_w_substr (name, ss, source, sess.chpos, sess.byte_pos); sess.cm.files.push(filemap); let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, sess.interner); - return (parser(sess, cfg, srdr as reader, ftype), srdr); + return (Parser(sess, cfg, srdr as reader, ftype), srdr); } fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, +name: ~str, +ss: codemap::file_substr, - source: @~str) -> parser { + source: @~str) -> Parser { let (p, _) = new_parser_etc_from_source_str(sess, cfg, name, ss, source); move p } @@ -190,7 +190,7 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path, ftype: parser::file_type) -> - (parser, string_reader) { + (Parser, string_reader) { let res = io::read_whole_file_str(path); match res { result::Ok(_) => { /* Continue. */ } @@ -202,18 +202,18 @@ fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg, sess.cm.files.push(filemap); let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, sess.interner); - return (parser(sess, cfg, srdr as reader, ftype), srdr); + return (Parser(sess, cfg, srdr as reader, ftype), srdr); } fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path, - ftype: parser::file_type) -> parser { + ftype: parser::file_type) -> Parser { let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype); move p } fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg, - tt: ~[ast::token_tree]) -> parser { + tt: ~[ast::token_tree]) -> Parser { let trdr = lexer::new_tt_reader(sess.span_diagnostic, sess.interner, None, tt); - return parser(sess, cfg, trdr as reader, parser::SOURCE_FILE) + return Parser(sess, cfg, trdr as reader, parser::SOURCE_FILE) } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 9be4909814b..42101a431d6 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -23,7 +23,7 @@ trait parser_attr { fn parse_optional_meta() -> ~[@ast::meta_item]; } -impl parser: parser_attr { +impl Parser: parser_attr { fn parse_outer_attrs_or_ext(first_item_attrs: ~[ast::attribute]) -> attr_or_ext diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index c8c30ee7fa9..50c22c08f4f 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -1,63 +1,63 @@ use std::map::{HashMap}; use ast_util::spanned; -use parser::parser; +use parser::Parser; use lexer::reader; type seq_sep = { - sep: Option<token::token>, + sep: Option<token::Token>, trailing_sep_allowed: bool }; -fn seq_sep_trailing_disallowed(t: token::token) -> seq_sep { +fn seq_sep_trailing_disallowed(t: token::Token) -> seq_sep { return {sep: option::Some(t), trailing_sep_allowed: false}; } -fn seq_sep_trailing_allowed(t: token::token) -> seq_sep { +fn seq_sep_trailing_allowed(t: token::Token) -> seq_sep { return {sep: option::Some(t), trailing_sep_allowed: true}; } fn seq_sep_none() -> seq_sep { return {sep: option::None, trailing_sep_allowed: false}; } -fn token_to_str(reader: reader, ++token: token::token) -> ~str { +fn token_to_str(reader: reader, ++token: token::Token) -> ~str { token::to_str(reader.interner(), token) } trait parser_common { - fn unexpected_last(t: token::token) -> !; + fn unexpected_last(t: token::Token) -> !; fn unexpected() -> !; - fn expect(t: token::token); + fn expect(t: token::Token); fn parse_ident() -> ast::ident; fn parse_path_list_ident() -> ast::path_list_ident; fn parse_value_ident() -> ast::ident; - fn eat(tok: token::token) -> bool; + fn eat(tok: token::Token) -> bool; // A sanity check that the word we are asking for is a known keyword fn require_keyword(word: ~str); - fn token_is_keyword(word: ~str, ++tok: token::token) -> bool; + fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool; fn is_keyword(word: ~str) -> bool; - fn is_any_keyword(tok: token::token) -> bool; + fn is_any_keyword(tok: token::Token) -> bool; fn eat_keyword(word: ~str) -> bool; fn expect_keyword(word: ~str); fn expect_gt(); - fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::token>, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq_to_gt<T: Copy>(sep: Option<token::token>, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq_lt_gt<T: Copy>(sep: Option<token::token>, - f: fn(parser) -> T) -> spanned<~[T]>; - fn parse_seq_to_end<T: Copy>(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq_to_before_end<T: Copy>(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T]; - fn parse_unspanned_seq<T: Copy>(bra: token::token, - ket: token::token, + fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::Token>, + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq_to_gt<T: Copy>(sep: Option<token::Token>, + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq_lt_gt<T: Copy>(sep: Option<token::Token>, + f: fn(Parser) -> T) -> spanned<~[T]>; + fn parse_seq_to_end<T: Copy>(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq_to_before_end<T: Copy>(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T]; + fn parse_unspanned_seq<T: Copy>(bra: token::Token, + ket: token::Token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq<T: Copy>(bra: token::token, ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> spanned<~[T]>; + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq<T: Copy>(bra: token::Token, ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> spanned<~[T]>; } -impl parser: parser_common { - fn unexpected_last(t: token::token) -> ! { +impl Parser: parser_common { + fn unexpected_last(t: token::Token) -> ! { self.span_fatal( copy self.last_span, ~"unexpected token: `" + token_to_str(self.reader, t) + ~"`"); @@ -68,7 +68,7 @@ impl parser: parser_common { + token_to_str(self.reader, self.token) + ~"`"); } - fn expect(t: token::token) { + fn expect(t: token::Token) { if self.token == t { self.bump(); } else { @@ -104,7 +104,7 @@ impl parser: parser_common { return self.parse_ident(); } - fn eat(tok: token::token) -> bool { + fn eat(tok: token::Token) -> bool { return if self.token == tok { self.bump(); true } else { false }; } @@ -117,14 +117,14 @@ impl parser: parser_common { } } - fn token_is_word(word: ~str, ++tok: token::token) -> bool { + fn token_is_word(word: ~str, ++tok: token::Token) -> bool { match tok { token::IDENT(sid, false) => { *self.id_to_str(sid) == word } _ => { false } } } - fn token_is_keyword(word: ~str, ++tok: token::token) -> bool { + fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool { self.require_keyword(word); self.token_is_word(word, tok) } @@ -133,7 +133,7 @@ impl parser: parser_common { self.token_is_keyword(word, self.token) } - fn is_any_keyword(tok: token::token) -> bool { + fn is_any_keyword(tok: token::Token) -> bool { match tok { token::IDENT(sid, false) => { self.keywords.contains_key_ref(self.id_to_str(sid)) @@ -216,8 +216,8 @@ impl parser: parser_common { } } - fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::token>, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::Token>, + f: fn(Parser) -> T) -> ~[T] { let mut first = true; let mut v = ~[]; while self.token != token::GT @@ -235,16 +235,16 @@ impl parser: parser_common { return v; } - fn parse_seq_to_gt<T: Copy>(sep: Option<token::token>, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_gt<T: Copy>(sep: Option<token::Token>, + f: fn(Parser) -> T) -> ~[T] { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } - fn parse_seq_lt_gt<T: Copy>(sep: Option<token::token>, - f: fn(parser) -> T) -> spanned<~[T]> { + fn parse_seq_lt_gt<T: Copy>(sep: Option<token::Token>, + f: fn(Parser) -> T) -> spanned<~[T]> { let lo = self.span.lo; self.expect(token::LT); let result = self.parse_seq_to_before_gt::<T>(sep, f); @@ -253,16 +253,16 @@ impl parser: parser_common { return spanned(lo, hi, result); } - fn parse_seq_to_end<T: Copy>(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_end<T: Copy>(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T] { let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); return val; } - fn parse_seq_to_before_end<T: Copy>(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_before_end<T: Copy>(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T] { let mut first: bool = true; let mut v: ~[T] = ~[]; while self.token != ket { @@ -279,10 +279,10 @@ impl parser: parser_common { return v; } - fn parse_unspanned_seq<T: Copy>(bra: token::token, - ket: token::token, + fn parse_unspanned_seq<T: Copy>(bra: token::Token, + ket: token::Token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T] { + f: fn(Parser) -> T) -> ~[T] { self.expect(bra); let result = self.parse_seq_to_before_end::<T>(ket, sep, f); self.bump(); @@ -291,8 +291,8 @@ impl parser: parser_common { // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. - fn parse_seq<T: Copy>(bra: token::token, ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> spanned<~[T]> { + fn parse_seq<T: Copy>(bra: token::Token, ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> spanned<~[T]> { let lo = self.span.lo; self.expect(bra); let result = self.parse_seq_to_before_end::<T>(ket, sep, f); diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs index c9106028491..56c9d4de9f3 100644 --- a/src/libsyntax/parse/eval.rs +++ b/src/libsyntax/parse/eval.rs @@ -1,4 +1,4 @@ -use parser::{parser, SOURCE_FILE}; +use parser::{Parser, SOURCE_FILE}; use attr::parser_attr; export eval_crate_directives_to_mod; diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 06fcc1cf958..8f57d733eb5 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -10,11 +10,11 @@ export string_reader_as_reader, tt_reader_as_reader; trait reader { fn is_eof() -> bool; - fn next_token() -> {tok: token::token, sp: span}; + fn next_token() -> {tok: token::Token, sp: span}; fn fatal(~str) -> !; fn span_diag() -> span_handler; pure fn interner() -> @token::ident_interner; - fn peek() -> {tok: token::token, sp: span}; + fn peek() -> {tok: token::Token, sp: span}; fn dup() -> reader; } @@ -28,7 +28,7 @@ type string_reader = @{ filemap: codemap::filemap, interner: @token::ident_interner, /* cached: */ - mut peek_tok: token::token, + mut peek_tok: token::Token, mut peek_span: span }; @@ -69,7 +69,7 @@ fn dup_string_reader(&&r: string_reader) -> string_reader { impl string_reader: reader { fn is_eof() -> bool { is_eof(self) } - fn next_token() -> {tok: token::token, sp: span} { + fn next_token() -> {tok: token::Token, sp: span} { let ret_val = {tok: self.peek_tok, sp: self.peek_span}; string_advance_token(self); return ret_val; @@ -79,7 +79,7 @@ impl string_reader: reader { } fn span_diag() -> span_handler { self.span_diagnostic } pure fn interner() -> @token::ident_interner { self.interner } - fn peek() -> {tok: token::token, sp: span} { + fn peek() -> {tok: token::Token, sp: span} { {tok: self.peek_tok, sp: self.peek_span} } fn dup() -> reader { dup_string_reader(self) as reader } @@ -87,7 +87,7 @@ impl string_reader: reader { impl tt_reader: reader { fn is_eof() -> bool { self.cur_tok == token::EOF } - fn next_token() -> {tok: token::token, sp: span} { + fn next_token() -> {tok: token::Token, sp: span} { /* weird resolve bug: if the following `if`, or any of its statements are removed, we get resolution errors */ if false { @@ -101,7 +101,7 @@ impl tt_reader: reader { } fn span_diag() -> span_handler { self.sp_diag } pure fn interner() -> @token::ident_interner { self.interner } - fn peek() -> {tok: token::token, sp: span} { + fn peek() -> {tok: token::Token, sp: span} { { tok: self.cur_tok, sp: self.cur_span } } fn dup() -> reader { dup_tt_reader(self) as reader } @@ -196,14 +196,14 @@ fn is_bin_digit(c: char) -> bool { return c == '0' || c == '1'; } // might return a sugared-doc-attr fn consume_whitespace_and_comments(rdr: string_reader) - -> Option<{tok: token::token, sp: span}> { + -> Option<{tok: token::Token, sp: span}> { while is_whitespace(rdr.curr) { bump(rdr); } return consume_any_line_comment(rdr); } // might return a sugared-doc-attr fn consume_any_line_comment(rdr: string_reader) - -> Option<{tok: token::token, sp: span}> { + -> Option<{tok: token::Token, sp: span}> { if rdr.curr == '/' { match nextch(rdr) { '/' => { @@ -246,7 +246,7 @@ fn consume_any_line_comment(rdr: string_reader) // might return a sugared-doc-attr fn consume_block_comment(rdr: string_reader) - -> Option<{tok: token::token, sp: span}> { + -> Option<{tok: token::Token, sp: span}> { // block comments starting with "/**" or "/*!" are doc-comments if rdr.curr == '*' || rdr.curr == '!' { @@ -317,7 +317,7 @@ fn scan_digits(rdr: string_reader, radix: uint) -> ~str { }; } -fn scan_number(c: char, rdr: string_reader) -> token::token { +fn scan_number(c: char, rdr: string_reader) -> token::Token { let mut num_str, base = 10u, c = c, n = nextch(rdr); if c == '0' && n == 'x' { bump(rdr); @@ -435,7 +435,7 @@ fn scan_numeric_escape(rdr: string_reader, n_hex_digits: uint) -> char { return accum_int as char; } -fn next_token_inner(rdr: string_reader) -> token::token { +fn next_token_inner(rdr: string_reader) -> token::Token { let mut accum_str = ~""; let mut c = rdr.curr; if (c >= 'a' && c <= 'z') @@ -460,7 +460,7 @@ fn next_token_inner(rdr: string_reader) -> token::token { if is_dec_digit(c) { return scan_number(c, rdr); } - fn binop(rdr: string_reader, op: token::binop) -> token::token { + fn binop(rdr: string_reader, op: token::binop) -> token::Token { bump(rdr); if rdr.curr == '=' { bump(rdr); diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 828d498ca3c..1f607d849d9 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -10,7 +10,7 @@ removed. use codemap::span; use ast::{expr, expr_lit, lit_nil}; use ast_util::{respan}; -use token::token; +use token::Token; /// The specific types of unsupported syntax pub enum ObsoleteSyntax { @@ -23,7 +23,8 @@ pub enum ObsoleteSyntax { ObsoleteClassTraits, ObsoletePrivSection, ObsoleteModeInFnType, - ObsoleteByMutRefMode + ObsoleteByMutRefMode, + ObsoleteFixedLengthVec, } impl ObsoleteSyntax : cmp::Eq { @@ -47,7 +48,7 @@ pub trait ObsoleteReporter { fn obsolete_expr(sp: span, kind: ObsoleteSyntax) -> @expr; } -impl parser : ObsoleteReporter { +impl Parser : ObsoleteReporter { /// Reports an obsolete syntax non-fatal error. fn obsolete(sp: span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { @@ -99,6 +100,11 @@ impl parser : ObsoleteReporter { "by-mutable-reference mode", "Declare an argument of type &mut T instead" ), + ObsoleteFixedLengthVec => ( + "fixed-length vector", + "Fixed-length types are now written `[T * N]`, and instances \ + are type-inferred" + ) }; self.report(sp, kind, kind_str, desc); @@ -121,7 +127,7 @@ impl parser : ObsoleteReporter { } } - fn token_is_obsolete_ident(ident: &str, token: token) -> bool { + fn token_is_obsolete_ident(ident: &str, token: Token) -> bool { match token { token::IDENT(copy sid, _) => { str::eq_slice(*self.id_to_str(sid), ident) @@ -183,5 +189,66 @@ impl parser : ObsoleteReporter { false } } + + fn try_parse_obsolete_fixed_vstore() -> Option<Option<uint>> { + if self.token == token::BINOP(token::SLASH) { + self.bump(); + match copy self.token { + token::UNDERSCORE => { + self.obsolete(copy self.last_span, + ObsoleteFixedLengthVec); + self.bump(); Some(None) + } + token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { + self.obsolete(copy self.last_span, + ObsoleteFixedLengthVec); + self.bump(); Some(Some(i as uint)) + } + _ => None + } + } else { + None + } + } + + fn try_convert_ty_to_obsolete_fixed_length_vstore(sp: span, t: ast::ty_) + -> ast::ty_ { + match self.try_parse_obsolete_fixed_vstore() { + // Consider a fixed length vstore suffix (/N or /_) + None => t, + Some(v) => { + ast::ty_fixed_length( + @{id: self.get_id(), node: t, span: sp}, v) + } + } + } + + fn try_convert_expr_to_obsolete_fixed_length_vstore( + lo: uint, hi: uint, ex: ast::expr_ + ) -> (uint, ast::expr_) { + + let mut hi = hi; + let mut ex = ex; + + // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...) + // only. + match ex { + ast::expr_lit(@{node: ast::lit_str(_), span: _}) | + ast::expr_vec(_, _) => { + match self.try_parse_obsolete_fixed_vstore() { + None => (), + Some(v) => { + hi = self.span.hi; + ex = ast::expr_vstore(self.mk_expr(lo, hi, ex), + ast::expr_vstore_fixed(v)); + } + } + } + _ => () + } + + return (hi, ex); + } + } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 22c25186c91..925da063ca6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6,7 +6,7 @@ use std::map::HashMap; use token::{can_begin_expr, is_ident, is_ident_or_path, is_plain_ident, INTERPOLATED, special_idents}; use codemap::{span,fss_none}; -use util::interner::interner; +use util::interner::Interner; use ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec}; use lexer::reader; use prec::{as_prec, token_to_binop}; @@ -22,10 +22,9 @@ use obsolete::{ ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits, ObsoleteModeInFnType, ObsoleteByMutRefMode }; -use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, +use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move, - bitand, bitor, bitxor, blk, blk_check_mode, bound_const, - bound_copy, bound_send, bound_trait, bound_owned, box, by_copy, + bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy, by_move, by_ref, by_val, capture_clause, capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item, class_immutable, class_mutable, @@ -58,7 +57,7 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, stmt_semi, struct_def, struct_field, struct_variant_kind, subtract, sty_box, sty_by_ref, sty_region, sty_static, sty_uniq, sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq, - tt_tok, tt_nonterminal, tuple_variant_kind, ty, ty_, ty_bot, + tt_tok, tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, type_value_ns, @@ -71,11 +70,11 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, expr_vstore_uniq}; export file_type; -export parser; +export Parser; export CRATE_FILE; export SOURCE_FILE; -// FIXME (#1893): #ast expects to find this here but it's actually +// FIXME (#3726): #ast expects to find this here but it's actually // defined in `parse` Fixing this will be easier when we have export // decls on individual items -- then parse can export this publicly, and // everything else crate-visibly. @@ -115,8 +114,7 @@ enum class_member { So that we can distinguish a class ctor or dtor from other class members */ -enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span), - dtor_decl(blk, ~[attribute], codemap::span), +enum class_contents { dtor_decl(blk, ~[attribute], codemap::span), members(~[@class_member]) } type arg_or_capture_item = Either<arg, capture_item>; @@ -125,12 +123,13 @@ type item_info = (ident, item_, Option<~[attribute]>); enum item_or_view_item { iovi_none, iovi_item(@item), + iovi_foreign_item(@foreign_item), iovi_view_item(@view_item) } enum view_item_parse_mode { VIEW_ITEMS_AND_ITEMS_ALLOWED, - VIEW_ITEMS_ALLOWED, + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED, IMPORTS_AND_ITEMS_ALLOWED } @@ -191,14 +190,14 @@ pure fn maybe_append(+lhs: ~[attribute], rhs: Option<~[attribute]>) /* ident is handled by common.rs */ -fn parser(sess: parse_sess, cfg: ast::crate_cfg, - +rdr: reader, ftype: file_type) -> parser { +fn Parser(sess: parse_sess, cfg: ast::crate_cfg, + +rdr: reader, ftype: file_type) -> Parser { let tok0 = rdr.next_token(); let span0 = tok0.sp; let interner = rdr.interner(); - parser { + Parser { reader: move rdr, interner: move interner, sess: sess, @@ -207,12 +206,7 @@ fn parser(sess: parse_sess, cfg: ast::crate_cfg, token: tok0.tok, span: span0, last_span: span0, - buffer: [mut - {tok: tok0.tok, sp: span0}, - {tok: tok0.tok, sp: span0}, - {tok: tok0.tok, sp: span0}, - {tok: tok0.tok, sp: span0} - ]/4, + buffer: [mut {tok: tok0.tok, sp: span0}, ..4], buffer_start: 0, buffer_end: 0, restriction: UNRESTRICTED, @@ -224,14 +218,14 @@ fn parser(sess: parse_sess, cfg: ast::crate_cfg, } } -struct parser { +struct Parser { sess: parse_sess, cfg: crate_cfg, file_type: file_type, - mut token: token::token, + mut token: token::Token, mut span: span, mut last_span: span, - mut buffer: [mut {tok: token::token, sp: span}]/4, + mut buffer: [mut {tok: token::Token, sp: span} * 4], mut buffer_start: int, mut buffer_end: int, mut restriction: restriction, @@ -248,7 +242,7 @@ struct parser { drop {} /* do not copy the parser; its state is tied to outside state */ } -impl parser { +impl Parser { fn bump() { self.last_span = self.span; let next = if self.buffer_start == self.buffer_end { @@ -261,7 +255,7 @@ impl parser { self.token = next.tok; self.span = next.sp; } - fn swap(next: token::token, lo: uint, hi: uint) { + fn swap(next: token::Token, lo: uint, hi: uint) { self.token = next; self.span = mk_sp(lo, hi); } @@ -271,7 +265,7 @@ impl parser { } return (4 - self.buffer_start) + self.buffer_end; } - fn look_ahead(distance: uint) -> token::token { + fn look_ahead(distance: uint) -> token::Token { let dist = distance as int; while self.buffer_length() < dist { self.buffer[self.buffer_end] = self.reader.next_token(); @@ -412,7 +406,7 @@ impl parser { }); } - fn parse_ret_ty() -> (ret_style, @ty) { + fn parse_ret_ty() -> (ret_style, @Ty) { return if self.eat(token::RARROW) { let lo = self.span.lo; if self.eat(token::NOT) { @@ -473,7 +467,7 @@ impl parser { self.region_from_name(name) } - fn parse_ty(colons_before_params: bool) -> @ty { + fn parse_ty(colons_before_params: bool) -> @Ty { maybe_whole!(self, nt_ty); let lo = self.span.lo; @@ -558,14 +552,13 @@ impl parser { } else { self.fatal(~"expected type"); }; let sp = mk_sp(lo, self.last_span.hi); - return @{id: self.get_id(), - node: match self.maybe_parse_fixed_vstore() { - // Consider a fixed vstore suffix (/N or /_) - None => t, - Some(v) => { - ty_fixed_length(@{id: self.get_id(), node:t, span: sp}, v) - } }, + return { + let node = + self.try_convert_ty_to_obsolete_fixed_length_vstore(sp, t); + @{id: self.get_id(), + node: node, span: sp} + }; } fn parse_arg_mode() -> mode { @@ -610,10 +603,10 @@ impl parser { } } - fn parse_capture_item_or(parse_arg_fn: fn(parser) -> arg_or_capture_item) + fn parse_capture_item_or(parse_arg_fn: fn(Parser) -> arg_or_capture_item) -> arg_or_capture_item { - fn parse_capture_item(p:parser, is_move: bool) -> capture_item { + fn parse_capture_item(p:Parser, is_move: bool) -> capture_item { let sp = mk_sp(p.span.lo, p.span.hi); let ident = p.parse_ident(); @{id: p.get_id(), is_move: is_move, name: ident, span: sp} @@ -696,23 +689,6 @@ impl parser { } } - fn maybe_parse_fixed_vstore() -> Option<Option<uint>> { - if self.token == token::BINOP(token::SLASH) { - self.bump(); - match copy self.token { - token::UNDERSCORE => { - self.bump(); Some(None) - } - token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { - self.bump(); Some(Some(i as uint)) - } - _ => None - } - } else { - None - } - } - fn maybe_parse_fixed_vstore_with_star() -> Option<Option<uint>> { if self.eat(token::BINOP(token::STAR)) { match copy self.token { @@ -729,7 +705,7 @@ impl parser { } } - fn lit_from_token(tok: token::token) -> lit_ { + fn lit_from_token(tok: token::Token) -> lit_ { match tok { token::LIT_INT(i, it) => lit_int(i, it), token::LIT_UINT(u, ut) => lit_uint(u, ut), @@ -761,8 +737,8 @@ impl parser { } fn parse_path_without_tps_( - parse_ident: fn(parser) -> ident, - parse_last_ident: fn(parser) -> ident) -> @path { + parse_ident: fn(Parser) -> ident, + parse_last_ident: fn(Parser) -> ident) -> @path { maybe_whole!(self, nt_path); let lo = self.span.lo; @@ -843,7 +819,7 @@ impl parser { } } - fn parse_field(sep: token::token) -> field { + fn parse_field(sep: token::Token) -> field { let lo = self.span.lo; let m = self.parse_mutability(); let i = self.parse_ident(); @@ -1088,20 +1064,8 @@ impl parser { ex = expr_lit(@lit); } - // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...) - // only. - match ex { - expr_lit(@{node: lit_str(_), span: _}) | - expr_vec(_, _) => match self.maybe_parse_fixed_vstore() { - None => (), - Some(v) => { - hi = self.span.hi; - ex = expr_vstore(self.mk_expr(lo, hi, ex), - expr_vstore_fixed(v)); - } - }, - _ => () - } + let (hi, ex) = + self.try_convert_expr_to_obsolete_fixed_length_vstore(lo, hi, ex); return self.mk_pexpr(lo, hi, ex); } @@ -1221,7 +1185,7 @@ impl parser { return e; } - fn parse_sep_and_zerok() -> (Option<token::token>, bool) { + fn parse_sep_and_zerok() -> (Option<token::Token>, bool) { if self.token == token::BINOP(token::STAR) || self.token == token::BINOP(token::PLUS) { let zerok = self.token == token::BINOP(token::STAR); @@ -1244,7 +1208,7 @@ impl parser { fn parse_token_tree() -> token_tree { maybe_whole!(deref self, nt_tt); - fn parse_tt_tok(p: parser, delim_ok: bool) -> token_tree { + fn parse_tt_tok(p: Parser, delim_ok: bool) -> token_tree { match p.token { token::RPAREN | token::RBRACE | token::RBRACKET if !delim_ok => { @@ -1311,8 +1275,8 @@ impl parser { // This goofy function is necessary to correctly match parens in matchers. // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be // invalid. It's similar to common::parse_seq. - fn parse_matcher_subseq(name_idx: @mut uint, bra: token::token, - ket: token::token) -> ~[matcher] { + fn parse_matcher_subseq(name_idx: @mut uint, bra: token::Token, + ket: token::Token) -> ~[matcher] { let mut ret_val = ~[]; let mut lparens = 0u; @@ -2159,7 +2123,7 @@ impl parser { fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt { maybe_whole!(self, nt_stmt); - fn check_expected_item(p: parser, current_attrs: ~[attribute]) { + fn check_expected_item(p: Parser, current_attrs: ~[attribute]) { // If we have attributes then we should have an item if vec::is_not_empty(current_attrs) { p.fatal(~"expected item"); @@ -2185,7 +2149,7 @@ impl parser { let item_attrs = vec::append(first_item_attrs, item_attrs); - match self.parse_item_or_view_item(item_attrs, true) { + match self.parse_item_or_view_item(item_attrs, true, false) { iovi_item(i) => { let mut hi = i.span.hi; let decl = @spanned(lo, hi, decl_item(i)); @@ -2195,6 +2159,9 @@ impl parser { self.span_fatal(vi.span, ~"view items must be declared at \ the top of the block"); } + iovi_foreign_item(_) => { + self.fatal(~"foreign items are not allowed here"); + } iovi_none() => { /* fallthrough */ } } @@ -2222,7 +2189,7 @@ impl parser { maybe_whole!(pair_empty self, nt_block); - fn maybe_parse_inner_attrs_and_next(p: parser, parse_attrs: bool) -> + fn maybe_parse_inner_attrs_and_next(p: Parser, parse_attrs: bool) -> {inner: ~[attribute], next: ~[attribute]} { if parse_attrs { p.parse_inner_attrs_and_next() @@ -2260,7 +2227,7 @@ impl parser { let mut stmts = ~[]; let mut expr = None; - let {attrs_remaining, view_items, items: items} = + let {attrs_remaining, view_items, items: items, _} = self.parse_items_and_view_items(first_item_attrs, IMPORTS_AND_ITEMS_ALLOWED); @@ -2327,19 +2294,20 @@ impl parser { return spanned(lo, hi, bloc); } + fn mk_ty_path(i: ident) -> @Ty { + @{id: self.get_id(), node: ty_path( + ident_to_path(copy self.last_span, i), + self.get_id()), span: self.last_span} + } + fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] { let mut bounds = ~[]; if self.eat(token::COLON) { while is_ident(self.token) { if is_ident(self.token) { - // XXX: temporary until kinds become traits let maybe_bound = match self.token { token::IDENT(copy sid, _) => { match *self.id_to_str(sid) { - ~"Send" => Some(bound_send), - ~"Copy" => Some(bound_copy), - ~"Const" => Some(bound_const), - ~"Owned" => Some(bound_owned), ~"send" | ~"copy" @@ -2349,7 +2317,7 @@ impl parser { ObsoleteLowerCaseKindBounds); // Bogus value, but doesn't matter, since // is an error - Some(bound_send) + Some(ty_param_bound(self.mk_ty_path(sid))) } _ => None @@ -2364,11 +2332,11 @@ impl parser { bounds.push(bound); } None => { - bounds.push(bound_trait(self.parse_ty(false))); + bounds.push(ty_param_bound(self.parse_ty(false))); } } } else { - bounds.push(bound_trait(self.parse_ty(false))); + bounds.push(ty_param_bound(self.parse_ty(false))); } } } @@ -2387,7 +2355,7 @@ impl parser { } else { ~[] } } - fn parse_fn_decl(parse_arg_fn: fn(parser) -> arg_or_capture_item) + fn parse_fn_decl(parse_arg_fn: fn(Parser) -> arg_or_capture_item) -> (fn_decl, capture_clause) { let args_or_capture_items: ~[arg_or_capture_item] = @@ -2414,18 +2382,18 @@ impl parser { fn expect_self_ident() { if !self.is_self_ident() { - self.fatal(#fmt("expected `self` but found `%s`", + self.fatal(fmt!("expected `self` but found `%s`", token_to_str(self.reader, self.token))); } self.bump(); } fn parse_fn_decl_with_self(parse_arg_fn: - fn(parser) -> arg_or_capture_item) + fn(Parser) -> arg_or_capture_item) -> (self_ty, fn_decl, capture_clause) { fn maybe_parse_self_ty(cnstr: fn(+v: mutability) -> ast::self_ty_, - p: parser) -> ast::self_ty_ { + p: Parser) -> ast::self_ty_ { // We need to make sure it isn't a mode or a type if p.token_is_keyword(~"self", p.look_ahead(1)) || ((p.token_is_keyword(~"const", p.look_ahead(1)) || @@ -2605,7 +2573,7 @@ impl parser { // Parses four variants (with the region/type params always optional): // impl<T> ~[T] : to_str { ... } fn parse_item_impl() -> item_info { - fn wrap_path(p: parser, pt: @path) -> @ty { + fn wrap_path(p: Parser, pt: @path) -> @Ty { @{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span} } @@ -2665,7 +2633,7 @@ impl parser { ref_id: self.get_id(), impl_id: self.get_id()} } - fn parse_trait_ref_list(ket: token::token) -> ~[@trait_ref] { + fn parse_trait_ref_list(ket: token::Token) -> ~[@trait_ref] { self.parse_seq_to_before_end( ket, seq_sep_trailing_disallowed(token::COMMA), |p| p.parse_trait_ref()) @@ -2683,34 +2651,17 @@ impl parser { let mut fields: ~[@struct_field]; let mut methods: ~[@method] = ~[]; - let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)> - = None; let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None; - let ctor_id = self.get_id(); if self.eat(token::LBRACE) { // It's a record-like struct. fields = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { - ctor_decl(a_fn_decl, attrs, blk, s) => { - match the_ctor { - Some((_, _, _, s_first)) => { - self.span_note(s, #fmt("Duplicate constructor \ - declaration for class %s", - *self.interner.get(class_name))); - self.span_fatal(copy s_first, ~"First constructor \ - declared here"); - } - None => { - the_ctor = Some((a_fn_decl, attrs, blk, s)); - } - } - } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { - self.span_note(s, #fmt("Duplicate destructor \ + self.span_note(s, fmt!("Duplicate destructor \ declaration for class %s", *self.interner.get(class_name))); self.span_fatal(copy s_first, ~"First destructor \ @@ -2764,39 +2715,17 @@ impl parser { self_id: self.get_id(), body: d_body}, span: d_s}}; - match the_ctor { - Some((ct_d, ct_attrs, ct_b, ct_s)) => { - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - ctor: Some({ - node: {id: ctor_id, - attrs: ct_attrs, - self_id: self.get_id(), - dec: ct_d, - body: ct_b}, - span: ct_s}), - dtor: actual_dtor - }, ty_params), - None) - } - None => { - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - ctor: None, - dtor: actual_dtor - }, ty_params), - None) - } - } + (class_name, + item_class(@{ + traits: traits, + fields: move fields, + methods: move methods, + dtor: actual_dtor + }, ty_params), + None) } - fn token_is_pound_or_doc_comment(++tok: token::token) -> bool { + fn token_is_pound_or_doc_comment(++tok: token::Token) -> bool { match tok { token::POUND | token::DOC_COMMENT(_) => true, _ => false @@ -2881,10 +2810,10 @@ impl parser { self.eat_keyword(~"static") } - fn parse_mod_items(term: token::token, + fn parse_mod_items(term: token::Token, +first_item_attrs: ~[attribute]) -> _mod { // Shouldn't be any view items since we've already parsed an item attr - let {attrs_remaining, view_items, items: starting_items} = + let {attrs_remaining, view_items, items: starting_items, _} = self.parse_items_and_view_items(first_item_attrs, VIEW_ITEMS_AND_ITEMS_ALLOWED); let mut items: ~[@item] = move starting_items; @@ -2898,7 +2827,7 @@ impl parser { } debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)", attrs); - match self.parse_item_or_view_item(attrs, true) { + match self.parse_item_or_view_item(attrs, true, false) { iovi_item(item) => items.push(item), iovi_view_item(view_item) => { self.span_fatal(view_item.span, ~"view items must be \ @@ -2998,11 +2927,11 @@ impl parser { +first_item_attrs: ~[attribute]) -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr - let {attrs_remaining, view_items, items: _} = + let {attrs_remaining, view_items, items: _, foreign_items} = self.parse_items_and_view_items(first_item_attrs, - VIEW_ITEMS_ALLOWED); + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED); - let mut items: ~[@foreign_item] = ~[]; + let mut items: ~[@foreign_item] = move foreign_items; let mut initial_attrs = attrs_remaining; while self.token != token::RBRACE { let attrs = vec::append(initial_attrs, @@ -3011,7 +2940,7 @@ impl parser { items.push(self.parse_foreign_item(attrs)); } return {sort: sort, view_items: view_items, - items: items}; + items: items}; } fn parse_item_foreign_mod(lo: uint, @@ -3097,12 +3026,6 @@ impl parser { let mut methods: ~[@method] = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { - ctor_decl(*) => { - self.span_fatal(copy self.span, - ~"deprecated explicit \ - constructors are not allowed \ - here"); - } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -3143,7 +3066,6 @@ impl parser { traits: ~[], fields: move fields, methods: move methods, - ctor: None, dtor: actual_dtor }; } @@ -3269,15 +3191,18 @@ impl parser { } } - fn fn_expr_lookahead(tok: token::token) -> bool { + fn fn_expr_lookahead(tok: token::Token) -> bool { match tok { token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true, _ => false } } - fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool) + fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool, + foreign_items_allowed: bool) -> item_or_view_item { + assert items_allowed != foreign_items_allowed; + maybe_whole!(iovi self,nt_item); let lo = self.span.lo; @@ -3295,6 +3220,9 @@ impl parser { return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); + } else if foreign_items_allowed && self.is_keyword(~"const") { + let item = self.parse_item_foreign_const(visibility, attrs); + return iovi_foreign_item(item); } else if items_allowed && self.is_keyword(~"fn") && !self.fn_expr_lookahead(self.look_ahead(1u)) { @@ -3309,6 +3237,10 @@ impl parser { return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); + } else if foreign_items_allowed && + (self.is_keyword(~"fn") || self.is_keyword(~"pure")) { + let item = self.parse_item_foreign_fn(visibility, attrs); + return iovi_foreign_item(item); } else if items_allowed && self.is_keyword(~"unsafe") && self.look_ahead(1u) != token::LBRACE { self.bump(); @@ -3395,16 +3327,24 @@ impl parser { return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_, visibility, attrs)); } else { + if visibility != inherited { + let mut s = ~"unmatched visibility `"; + s += if visibility == public { ~"pub" } else { ~"priv" }; + s += ~"`"; + self.span_fatal(copy self.last_span, s); + } return iovi_none; }; } fn parse_item(+attrs: ~[attribute]) -> Option<@ast::item> { - match self.parse_item_or_view_item(attrs, true) { + match self.parse_item_or_view_item(attrs, true, false) { iovi_none => None, iovi_view_item(_) => self.fatal(~"view items are not allowed here"), + iovi_foreign_item(_) => + self.fatal(~"foreign items are not allowed here"), iovi_item(item) => Some(item) } @@ -3539,28 +3479,35 @@ impl parser { mode: view_item_parse_mode) -> {attrs_remaining: ~[attribute], view_items: ~[@view_item], - items: ~[@item]} { + items: ~[@item], + foreign_items: ~[@foreign_item]} { let mut attrs = vec::append(first_item_attrs, self.parse_outer_attributes()); - let items_allowed; - match mode { - VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => - items_allowed = true, - VIEW_ITEMS_ALLOWED => - items_allowed = false - } + let items_allowed = match mode { + VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true, + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false + }; - let (view_items, items) = (DVec(), DVec()); + let restricted_to_imports = match mode { + IMPORTS_AND_ITEMS_ALLOWED => true, + VIEW_ITEMS_AND_ITEMS_ALLOWED | + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false + }; + + let foreign_items_allowed = match mode { + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => true, + VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false + }; + + let (view_items, items, foreign_items) = (DVec(), DVec(), DVec()); loop { - match self.parse_item_or_view_item(attrs, items_allowed) { + match self.parse_item_or_view_item(attrs, items_allowed, + foreign_items_allowed) { iovi_none => break, iovi_view_item(view_item) => { - match mode { - VIEW_ITEMS_AND_ITEMS_ALLOWED | - VIEW_ITEMS_ALLOWED => {} - IMPORTS_AND_ITEMS_ALLOWED => + if restricted_to_imports { match view_item.node { view_item_import(_) => {} view_item_export(_) | view_item_use(*) => @@ -3575,13 +3522,18 @@ impl parser { assert items_allowed; items.push(item) } + iovi_foreign_item(foreign_item) => { + assert foreign_items_allowed; + foreign_items.push(foreign_item); + } } attrs = self.parse_outer_attributes(); } {attrs_remaining: attrs, view_items: dvec::unwrap(move view_items), - items: dvec::unwrap(move items)} + items: dvec::unwrap(move items), + foreign_items: dvec::unwrap(move foreign_items)} } // Parses a source module as a crate @@ -3655,7 +3607,7 @@ impl parser { return self.fatal(~"expected crate directive"); } - fn parse_crate_directives(term: token::token, + fn parse_crate_directives(term: token::Token, first_outer_attr: ~[attribute]) -> ~[@crate_directive] { diff --git a/src/libsyntax/parse/prec.rs b/src/libsyntax/parse/prec.rs index 668301db620..3fd905cb8ec 100644 --- a/src/libsyntax/parse/prec.rs +++ b/src/libsyntax/parse/prec.rs @@ -3,7 +3,7 @@ export unop_prec; export token_to_binop; use token::*; -use token::token; +use token::Token; use ast::*; /// Unary operators have higher precedence than binary @@ -19,7 +19,7 @@ const as_prec: uint = 11u; * Maps a token to a record specifying the corresponding binary * operator and its precedence */ -fn token_to_binop(tok: token) -> Option<ast::binop> { +fn token_to_binop(tok: Token) -> Option<ast::binop> { match tok { BINOP(STAR) => Some(mul), BINOP(SLASH) => Some(div), diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 99b789cf63f..5151fd1bac8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -1,18 +1,9 @@ use util::interner; -use util::interner::interner; +use util::interner::Interner; use std::map::HashMap; -use std::serialization::{Serializer, - Deserializer, - serialize_uint, - deserialize_uint, - serialize_i64, - deserialize_i64, - serialize_u64, - deserialize_u64, - serialize_bool, - deserialize_bool}; #[auto_serialize] +#[auto_deserialize] enum binop { PLUS, MINUS, @@ -27,7 +18,8 @@ enum binop { } #[auto_serialize] -enum token { +#[auto_deserialize] +enum Token { /* Expression-operator symbols. */ EQ, LT, @@ -84,6 +76,7 @@ enum token { } #[auto_serialize] +#[auto_deserialize] /// For interpolation during macro expansion. enum nonterminal { nt_item(@ast::item), @@ -91,7 +84,7 @@ enum nonterminal { nt_stmt(@ast::stmt), nt_pat( @ast::pat), nt_expr(@ast::expr), - nt_ty( @ast::ty), + nt_ty( @ast::Ty), nt_ident(ast::ident, bool), nt_path(@ast::path), nt_tt( @ast::token_tree), //needs @ed to break a circularity @@ -113,7 +106,7 @@ fn binop_to_str(o: binop) -> ~str { } } -fn to_str(in: @ident_interner, t: token) -> ~str { +fn to_str(in: @ident_interner, t: Token) -> ~str { match t { EQ => ~"=", LT => ~"<", @@ -199,7 +192,7 @@ fn to_str(in: @ident_interner, t: token) -> ~str { } } -pure fn can_begin_expr(t: token) -> bool { +pure fn can_begin_expr(t: Token) -> bool { match t { LPAREN => true, LBRACE => true, @@ -230,7 +223,7 @@ pure fn can_begin_expr(t: token) -> bool { } /// what's the opposite delimiter? -fn flip_delimiter(t: token::token) -> token::token { +fn flip_delimiter(t: token::Token) -> token::Token { match t { token::LPAREN => token::RPAREN, token::LBRACE => token::RBRACE, @@ -244,7 +237,7 @@ fn flip_delimiter(t: token::token) -> token::token { -fn is_lit(t: token) -> bool { +fn is_lit(t: Token) -> bool { match t { LIT_INT(_, _) => true, LIT_UINT(_, _) => true, @@ -255,22 +248,22 @@ fn is_lit(t: token) -> bool { } } -pure fn is_ident(t: token) -> bool { +pure fn is_ident(t: Token) -> bool { match t { IDENT(_, _) => true, _ => false } } -pure fn is_ident_or_path(t: token) -> bool { +pure fn is_ident_or_path(t: Token) -> bool { match t { IDENT(_, _) | INTERPOLATED(nt_path(*)) => true, _ => false } } -pure fn is_plain_ident(t: token) -> bool { +pure fn is_plain_ident(t: Token) -> bool { match t { IDENT(_, false) => true, _ => false } } -pure fn is_bar(t: token) -> bool { +pure fn is_bar(t: Token) -> bool { match t { BINOP(OR) | OROR => true, _ => false } } @@ -321,7 +314,7 @@ mod special_idents { } struct ident_interner { - priv interner: util::interner::interner<@~str>, + priv interner: util::interner::Interner<@~str>, } impl ident_interner { @@ -350,28 +343,33 @@ macro_rules! interner_key ( ) fn mk_ident_interner() -> @ident_interner { - /* the indices here must correspond to the numbers in special_idents */ - let init_vec = ~[@~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!", - @~"[]", @~"unary-", @~"__extensions__", @~"self", - @~"item", @~"block", @~"stmt", @~"pat", @~"expr", - @~"ty", @~"ident", @~"path", @~"tt", @~"matchers", - @~"str", @~"TyVisitor", @~"arg", @~"descrim", - @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc", - @~"dtor", @~"main", @~"<opaque>", @~"blk", @~"static", - @~"intrinsic", @~"__foreign_mod__"]; - - let rv = @ident_interner { - interner: interner::mk_prefill::<@~str>(init_vec) - }; - - /* having multiple interners will just confuse the serializer */ unsafe { - assert task::local_data::local_data_get(interner_key!()).is_none() - }; - unsafe { - task::local_data::local_data_set(interner_key!(), @rv) - }; - rv + match task::local_data::local_data_get(interner_key!()) { + Some(interner) => *interner, + None => { + // the indices here must correspond to the numbers in + // special_idents. + let init_vec = ~[ + @~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!", + @~"[]", @~"unary-", @~"__extensions__", @~"self", + @~"item", @~"block", @~"stmt", @~"pat", @~"expr", + @~"ty", @~"ident", @~"path", @~"tt", @~"matchers", + @~"str", @~"TyVisitor", @~"arg", @~"descrim", + @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc", + @~"dtor", @~"main", @~"<opaque>", @~"blk", @~"static", + @~"intrinsic", @~"__foreign_mod__" + ]; + + let rv = @ident_interner { + interner: interner::mk_prefill(init_vec) + }; + + task::local_data::local_data_set(interner_key!(), @rv); + + rv + } + } + } } /* for when we don't care about the contents; doesn't interact with TLD or @@ -459,8 +457,8 @@ impl binop : cmp::Eq { pure fn ne(other: &binop) -> bool { !self.eq(other) } } -impl token : cmp::Eq { - pure fn eq(other: &token) -> bool { +impl Token : cmp::Eq { + pure fn eq(other: &Token) -> bool { match self { EQ => { match (*other) { @@ -722,7 +720,7 @@ impl token : cmp::Eq { } } } - pure fn ne(other: &token) -> bool { !self.eq(other) } + pure fn ne(other: &Token) -> bool { !self.eq(other) } } // Local Variables: diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index bff356e5cb7..33915c8c0c9 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1,5 +1,5 @@ use parse::{comments, lexer, token}; -use codemap::codemap; +use codemap::CodeMap; use pp::{break_offset, word, printer, space, zerobreak, hardbreak, breaks}; use pp::{consistent, inconsistent, eof}; use ast::{required, provided}; @@ -24,7 +24,7 @@ fn no_ann() -> pp_ann { type ps = @{s: pp::printer, - cm: Option<codemap>, + cm: Option<CodeMap>, intr: @token::ident_interner, comments: Option<~[comments::cmnt]>, literals: Option<~[comments::lit]>, @@ -45,7 +45,7 @@ fn end(s: ps) { fn rust_printer(writer: io::Writer, intr: @ident_interner) -> ps { return @{s: pp::mk_printer(writer, default_columns), - cm: None::<codemap>, + cm: None::<CodeMap>, intr: intr, comments: None::<~[comments::cmnt]>, literals: None::<~[comments::lit]>, @@ -63,7 +63,7 @@ const default_columns: uint = 78u; // Requires you to pass an input filename and reader so that // it can scan the input text for comments and literals to // copy forward. -fn print_crate(cm: codemap, intr: @ident_interner, +fn print_crate(cm: CodeMap, intr: @ident_interner, span_diagnostic: diagnostic::span_handler, crate: @ast::crate, filename: ~str, in: io::Reader, out: io::Writer, ann: pp_ann, is_expanded: bool) { @@ -91,7 +91,7 @@ fn print_crate_(s: ps, &&crate: @ast::crate) { eof(s.s); } -fn ty_to_str(ty: @ast::ty, intr: @ident_interner) -> ~str { +fn ty_to_str(ty: @ast::Ty, intr: @ident_interner) -> ~str { to_str(ty, print_type, intr) } @@ -348,11 +348,11 @@ fn print_region(s: ps, region: @ast::region, sep: ~str) { word(s.s, sep); } -fn print_type(s: ps, &&ty: @ast::ty) { +fn print_type(s: ps, &&ty: @ast::Ty) { print_type_ex(s, ty, false); } -fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) { +fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) { maybe_print_comment(s, ty.span.lo); ibox(s, 0u); match ty.node { @@ -399,9 +399,21 @@ fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) { } ast::ty_path(path, _) => print_path(s, path, print_colons), ast::ty_fixed_length(t, v) => { - print_type(s, t); - word(s.s, ~"/"); + word(s.s, ~"["); + match t.node { + ast::ty_vec(mt) => { + match mt.mutbl { + ast::m_mutbl => word_space(s, ~"mut"), + ast::m_const => word_space(s, ~"const"), + ast::m_imm => () + } + print_type(s, mt.ty); + } + _ => fail ~"ty_fixed_length can only contain ty_vec as type" + } + word(s.s, ~" * "); print_vstore(s, ast::vstore_fixed(v)); + word(s.s, ~"]"); } ast::ty_mac(_) => { fail ~"print_type doesn't know how to print a ty_mac"; @@ -433,6 +445,7 @@ fn print_foreign_item(s: ps, item: @ast::foreign_item) { print_type(s, t); word(s.s, ~";"); end(s); // end the head-ibox + end(s); // end the outer cbox } } } @@ -443,7 +456,6 @@ fn print_item(s: ps, &&item: @ast::item) { print_outer_attributes(s, item.attrs); let ann_node = node_item(s, item); s.ann.pre(ann_node); - print_visibility(s, item.vis); match item.node { ast::item_const(ty, expr) => { head(s, visibility_qualified(item.vis, ~"const")); @@ -479,10 +491,10 @@ fn print_item(s: ps, &&item: @ast::item) { ast::named => { word_nbsp(s, ~"mod"); print_ident(s, item.ident); + nbsp(s); } ast::anonymous => {} } - nbsp(s); bopen(s); print_foreign_mod(s, nmod, item.attrs); bclose(s, item.span); @@ -490,7 +502,7 @@ fn print_item(s: ps, &&item: @ast::item) { ast::item_ty(ty, params) => { ibox(s, indent_unit); ibox(s, 0u); - word_nbsp(s, ~"type"); + word_nbsp(s, visibility_qualified(item.vis, ~"type")); print_ident(s, item.ident); print_type_params(s, params); end(s); // end the inner ibox @@ -502,15 +514,16 @@ fn print_item(s: ps, &&item: @ast::item) { end(s); // end the outer ibox } ast::item_enum(enum_definition, params) => { - print_enum_def(s, enum_definition, params, item.ident, item.span); + print_enum_def(s, enum_definition, params, item.ident, + item.span, item.vis); } ast::item_class(struct_def, tps) => { - head(s, ~"struct"); + head(s, visibility_qualified(item.vis, ~"struct")); print_struct(s, struct_def, tps, item.ident, item.span); } ast::item_impl(tps, opt_trait, ty, methods) => { - head(s, ~"impl"); + head(s, visibility_qualified(item.vis, ~"impl")); if tps.is_not_empty() { print_type_params(s, tps); space(s.s); @@ -533,7 +546,7 @@ fn print_item(s: ps, &&item: @ast::item) { bclose(s, item.span); } ast::item_trait(tps, traits, methods) => { - head(s, ~"trait"); + head(s, visibility_qualified(item.vis, ~"trait")); print_ident(s, item.ident); print_type_params(s, tps); if vec::len(traits) != 0u { @@ -549,6 +562,7 @@ fn print_item(s: ps, &&item: @ast::item) { bclose(s, item.span); } ast::item_mac({node: ast::mac_invoc_tt(pth, tts), _}) => { + print_visibility(s, item.vis); print_path(s, pth, false); word(s.s, ~"! "); print_ident(s, item.ident); @@ -569,7 +583,7 @@ fn print_item(s: ps, &&item: @ast::item) { fn print_enum_def(s: ps, enum_definition: ast::enum_def, params: ~[ast::ty_param], ident: ast::ident, - span: ast::span) { + span: ast::span, visibility: ast::visibility) { let mut newtype = vec::len(enum_definition.variants) == 1u && ident == enum_definition.variants[0].node.name; @@ -581,9 +595,9 @@ fn print_enum_def(s: ps, enum_definition: ast::enum_def, } if newtype { ibox(s, indent_unit); - word_space(s, ~"enum"); + word_space(s, visibility_qualified(visibility, ~"enum")); } else { - head(s, ~"enum"); + head(s, visibility_qualified(visibility, ~"enum")); } print_ident(s, ident); @@ -653,18 +667,6 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param], } bopen(s); hardbreak_if_not_bol(s); - do struct_def.ctor.iter |ctor| { - maybe_print_comment(s, ctor.span.lo); - print_outer_attributes(s, ctor.node.attrs); - // Doesn't call head because there shouldn't be a space after new. - cbox(s, indent_unit); - ibox(s, 4); - word(s.s, ~"new("); - print_fn_args(s, ctor.node.dec, ~[], None); - word(s.s, ~")"); - space(s.s); - print_block(s, ctor.node.body); - } do struct_def.dtor.iter |dtor| { hardbreak_if_not_bol(s); maybe_print_comment(s, dtor.span.lo); @@ -888,7 +890,7 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type, indented: uint, attrs: ~[ast::attribute], close_box: bool) { match blk.node.rules { - ast::unsafe_blk => word(s.s, ~"unsafe"), + ast::unsafe_blk => word_space(s, ~"unsafe"), ast::default_blk => () } maybe_print_comment(s, blk.span.lo); @@ -1178,7 +1180,10 @@ fn print_expr(s: ps, &&expr: @ast::expr) { ast::expr_loop(blk, opt_ident) => { head(s, ~"loop"); space(s.s); - opt_ident.iter(|ident| {print_ident(s, *ident); space(s.s)}); + opt_ident.iter(|ident| { + print_ident(s, *ident); + word_space(s, ~":"); + }); print_block(s, blk); } ast::expr_match(expr, arms) => { @@ -1702,17 +1707,11 @@ fn print_arg_mode(s: ps, m: ast::mode) { } fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) { - if vec::len(*bounds) > 0u { + if bounds.is_not_empty() { word(s.s, ~":"); for vec::each(*bounds) |bound| { nbsp(s); - match *bound { - ast::bound_copy => word(s.s, ~"Copy"), - ast::bound_send => word(s.s, ~"Send"), - ast::bound_const => word(s.s, ~"Const"), - ast::bound_owned => word(s.s, ~"Owned"), - ast::bound_trait(t) => print_type(s, t) - } + print_type(s, **bound); } } } diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 38abf5f445c..7c73deed1a9 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -1,5 +1,5 @@ #[link(name = "syntax", - vers = "0.4", + vers = "0.5", uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")]; @@ -16,8 +16,8 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); use core::*; @@ -131,8 +131,6 @@ mod ext { #[legacy_exports] mod auto_serialize; #[legacy_exports] - mod auto_serialize2; - #[legacy_exports] mod source_util; mod pipes { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 021c25e3dd7..f564589cbe0 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -12,14 +12,14 @@ type hash_interner<T: Const> = {map: HashMap<T, uint>, vect: DVec<T>}; -fn mk<T:Eq IterBytes Hash Const Copy>() -> interner<T> { +fn mk<T:Eq IterBytes Hash Const Copy>() -> Interner<T> { let m = map::HashMap::<T, uint>(); let hi: hash_interner<T> = {map: m, vect: DVec()}; - move (hi as interner::<T>) + move ((move hi) as Interner::<T>) } -fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> interner<T> { +fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> Interner<T> { let rv = mk(); for init.each() |v| { rv.intern(*v); } return rv; @@ -27,14 +27,14 @@ fn mk_prefill<T:Eq IterBytes Hash Const Copy>(init: ~[T]) -> interner<T> { /* when traits can extend traits, we should extend index<uint,T> to get [] */ -trait interner<T:Eq IterBytes Hash Const Copy> { +trait Interner<T:Eq IterBytes Hash Const Copy> { fn intern(T) -> uint; fn gensym(T) -> uint; pure fn get(uint) -> T; fn len() -> uint; } -impl <T:Eq IterBytes Hash Const Copy> hash_interner<T>: interner<T> { +impl <T:Eq IterBytes Hash Const Copy> hash_interner<T>: Interner<T> { fn intern(val: T) -> uint { match self.map.find(val) { Some(idx) => return idx, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e6fd65eb458..b45af2d4ae8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -17,8 +17,6 @@ enum fn_kind { fk_method(ident, ~[ty_param], @method), fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) fk_fn_block(capture_clause), //< a block {||...} - fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */, - def_id /* parent class id */), // class constructor fk_dtor(~[ty_param], ~[attribute], node_id /* self id */, def_id /* parent class id */) // class destructor @@ -26,8 +24,9 @@ enum fn_kind { fn name_of_fn(fk: fn_kind) -> ident { match fk { - fk_item_fn(name, _, _) | fk_method(name, _, _) - | fk_ctor(name, _, _, _, _) => /* FIXME (#2543) */ copy name, + fk_item_fn(name, _, _) | fk_method(name, _, _) => { + /* FIXME (#2543) */ copy name + } fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon, fk_dtor(*) => parse::token::special_idents::dtor } @@ -35,11 +34,11 @@ fn name_of_fn(fk: fn_kind) -> ident { fn tps_of_fn(fk: fn_kind) -> ~[ty_param] { match fk { - fk_item_fn(_, tps, _) | fk_method(_, tps, _) - | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => { - /* FIXME (#2543) */ copy tps - } - fk_anon(*) | fk_fn_block(*) => ~[] + fk_item_fn(_, tps, _) | fk_method(_, tps, _) | + fk_dtor(tps, _, _, _) => { + /* FIXME (#2543) */ copy tps + } + fk_anon(*) | fk_fn_block(*) => ~[] } } @@ -56,7 +55,7 @@ type visitor<E> = visit_decl: fn@(@decl, E, vt<E>), visit_expr: fn@(@expr, E, vt<E>), visit_expr_post: fn@(@expr, E, vt<E>), - visit_ty: fn@(@ty, E, vt<E>), + visit_ty: fn@(@Ty, E, vt<E>), visit_ty_params: fn@(~[ty_param], E, vt<E>), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>), visit_ty_method: fn@(ty_method, E, vt<E>), @@ -183,12 +182,14 @@ fn visit_enum_def<E>(enum_definition: ast::enum_def, tps: ~[ast::ty_param], visit_enum_def(enum_definition, tps, e, v); } } + // Visit the disr expr if it exists + vr.node.disr_expr.iter(|ex| v.visit_expr(*ex, e, v)); } } -fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {} +fn skip_ty<E>(_t: @Ty, _e: E, _v: vt<E>) {} -fn visit_ty<E>(t: @ty, e: E, v: vt<E>) { +fn visit_ty<E>(t: @Ty, e: E, v: vt<E>) { match t.node { ty_box(mt) | ty_uniq(mt) | ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) => { @@ -263,10 +264,7 @@ fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) { fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) { for vec::each(*bounds) |bound| { - match *bound { - bound_trait(t) => v.visit_ty(t, e, v), - bound_copy | bound_send | bound_const | bound_owned => () - } + v.visit_ty(**bound, e, v) } } @@ -291,17 +289,6 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) { m.decl, m.body, m.span, m.id, e, v); } -// Similar logic to the comment on visit_method_helper - Tim -fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param], - parent_id: def_id, e: E, v: vt<E>) { - v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm, - ctor.node.attrs, - /* FIXME (#2543) */ copy tps, - ctor.node.self_id, parent_id), - ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v) - -} - fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param], parent_id: def_id, e: E, v: vt<E>) { v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs, @@ -330,7 +317,7 @@ fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) { } } -fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], +fn visit_struct_def<E>(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param], id: node_id, e: E, v: vt<E>) { for sd.fields.each |f| { v.visit_struct_field(*f, e, v); @@ -341,9 +328,6 @@ fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], for sd.traits.each |p| { visit_path(p.path, e, v); } - do option::iter(&sd.ctor) |ctor| { - visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v); - }; do option::iter(&sd.dtor) |dtor| { visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v) }; @@ -503,7 +487,7 @@ type simple_visitor = visit_decl: fn@(@decl), visit_expr: fn@(@expr), visit_expr_post: fn@(@expr), - visit_ty: fn@(@ty), + visit_ty: fn@(@Ty), visit_ty_params: fn@(~[ty_param]), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id), visit_ty_method: fn@(ty_method), @@ -512,7 +496,7 @@ type simple_visitor = visit_struct_field: fn@(@struct_field), visit_struct_method: fn@(@method)}; -fn simple_ignore_ty(_t: @ty) {} +fn simple_ignore_ty(_t: @Ty) {} fn default_simple_visitor() -> simple_visitor { return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { }, @@ -590,7 +574,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> { fn v_expr_post(f: fn@(@expr), ex: @expr, &&_e: (), _v: vt<()>) { f(ex); } - fn v_ty(f: fn@(@ty), ty: @ty, &&e: (), v: vt<()>) { + fn v_ty(f: fn@(@Ty), ty: @Ty, &&e: (), v: vt<()>) { f(ty); visit_ty(ty, e, v); } diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 706e8ff4380..c34fd166bae 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -270,6 +270,20 @@ rust_uv_tcp_bind6 } extern "C" int +rust_uv_tcp_getpeername +(uv_tcp_t* handle, sockaddr_in* name) { + int namelen = sizeof(sockaddr_in); + return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen); +} + +extern "C" int +rust_uv_tcp_getpeername6 +(uv_tcp_t* handle, sockaddr_in6* name) { + int namelen = sizeof(sockaddr_in6); + return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen); +} + +extern "C" int rust_uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { return uv_listen(stream, backlog, cb); @@ -480,6 +494,14 @@ rust_uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { int result = uv_ip6_name(src, dst, size); return result; } +extern "C" unsigned int +rust_uv_ip4_port(struct sockaddr_in* src) { + return ntohs(src->sin_port); +} +extern "C" unsigned int +rust_uv_ip6_port(struct sockaddr_in6* src) { + return ntohs(src->sin6_port); +} extern "C" uintptr_t* rust_uv_get_kernel_global_chan_ptr() { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 890aa352c92..6a2bdd622cb 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -204,3 +204,7 @@ tdefl_compress_mem_to_heap tinfl_decompress_mem_to_heap rust_annihilate_box rust_gc_metadata +rust_uv_ip4_port +rust_uv_ip6_port +rust_uv_tcp_getpeername +rust_uv_tcp_getpeername6 \ No newline at end of file diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs index 2e310785306..61fd68c193a 100644 --- a/src/rustc/back/link.rs +++ b/src/rustc/back/link.rs @@ -1,6 +1,6 @@ use libc::{c_int, c_uint, c_char}; use driver::session; -use session::session; +use session::Session; use lib::llvm::llvm; use syntax::attr; use middle::ty; @@ -33,14 +33,14 @@ impl output_type : cmp::Eq { pure fn ne(other: &output_type) -> bool { !self.eq(other) } } -fn llvm_err(sess: session, msg: ~str) -> ! unsafe { +fn llvm_err(sess: Session, msg: ~str) -> ! unsafe { let cstr = llvm::LLVMRustGetLastError(); if cstr == ptr::null() { sess.fatal(msg); } else { sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); } } -fn WriteOutputFile(sess:session, +fn WriteOutputFile(sess: Session, PM: lib::llvm::PassManagerRef, M: ModuleRef, Triple: *c_char, // FIXME: When #2334 is fixed, change @@ -69,7 +69,7 @@ mod jit { env: *(), } - fn exec(sess: session, + fn exec(sess: Session, pm: PassManagerRef, m: ModuleRef, opt: c_int, @@ -131,7 +131,7 @@ mod write { return false; } - fn run_passes(sess: session, llmod: ModuleRef, output: &Path) { + fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } let mut pm = mk_pass_manager(); @@ -384,7 +384,7 @@ mod write { * */ -fn build_link_meta(sess: session, c: ast::crate, output: &Path, +fn build_link_meta(sess: Session, c: ast::crate, output: &Path, symbol_hasher: &hash::State) -> link_meta { type provided_metas = @@ -392,7 +392,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: &Path, vers: Option<~str>, cmh_items: ~[@ast::meta_item]}; - fn provided_link_metas(sess: session, c: ast::crate) -> + fn provided_link_metas(sess: Session, c: ast::crate) -> provided_metas { let mut name: Option<~str> = None; let mut vers: Option<~str> = None; @@ -454,13 +454,13 @@ fn build_link_meta(sess: session, c: ast::crate, output: &Path, return truncated_hash_result(symbol_hasher); } - fn warn_missing(sess: session, name: ~str, default: ~str) { + fn warn_missing(sess: Session, name: ~str, default: ~str) { if !sess.building_library { return; } sess.warn(fmt!("missing crate link meta `%s`, using `%s` as default", name, default)); } - fn crate_meta_name(sess: session, _crate: ast::crate, + fn crate_meta_name(sess: Session, _crate: ast::crate, output: &Path, metas: provided_metas) -> ~str { return match metas.name { Some(v) => v, @@ -477,7 +477,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: &Path, }; } - fn crate_meta_vers(sess: session, _crate: ast::crate, + fn crate_meta_vers(sess: Session, _crate: ast::crate, metas: provided_metas) -> ~str { return match metas.vers { Some(v) => v, @@ -569,7 +569,7 @@ fn sanitize(s: ~str) -> ~str { return result; } -fn mangle(sess: session, ss: path) -> ~str { +fn mangle(sess: Session, ss: path) -> ~str { // Follow C++ namespace-mangling style let mut n = ~"_ZN"; // Begin name-sequence. @@ -584,7 +584,7 @@ fn mangle(sess: session, ss: path) -> ~str { n } -fn exported_name(sess: session, path: path, hash: ~str, vers: ~str) -> ~str { +fn exported_name(sess: Session, path: path, hash: ~str, vers: ~str) -> ~str { return mangle(sess, vec::append_one( vec::append_one(path, path_name(sess.ident_of(hash))), @@ -623,7 +623,7 @@ fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: ~str) -> ~str { // If the user wants an exe generated we need to invoke // cc to link the object file with some libs -fn link_binary(sess: session, +fn link_binary(sess: Session, obj_filename: &Path, out_filename: &Path, lm: link_meta) { @@ -723,10 +723,8 @@ fn link_binary(sess: session, } } - if !sess.debugging_opt(session::no_rt) { - // Always want the runtime linked in - cc_args.push(~"-lrustrt"); - } + // Always want the runtime linked in + cc_args.push(~"-lrustrt"); // On linux librt and libdl are an indirect dependencies via rustrt, // and binutils 2.22+ won't add them automatically diff --git a/src/rustc/back/rpath.rs b/src/rustc/back/rpath.rs index 8aa7caefc7a..8038d7bb6dd 100644 --- a/src/rustc/back/rpath.rs +++ b/src/rustc/back/rpath.rs @@ -13,7 +13,7 @@ pure fn not_win32(os: session::os) -> bool { } } -fn get_rpath_flags(sess: session::session, out_filename: &Path) -> ~[~str] { +fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] { let os = sess.targ_cfg.os; // No rpath on windows @@ -35,7 +35,7 @@ fn get_rpath_flags(sess: session::session, out_filename: &Path) -> ~[~str] { rpaths_to_flags(rpaths) } -fn get_sysroot_absolute_rt_lib(sess: session::session) -> Path { +fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path { let r = filesearch::relative_target_lib_path(sess.opts.target_triple); sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt")) } diff --git a/src/rustc/back/upcall.rs b/src/rustc/back/upcall.rs index a2c864f6f46..45e7cd4e9d4 100644 --- a/src/rustc/back/upcall.rs +++ b/src/rustc/back/upcall.rs @@ -27,8 +27,7 @@ fn declare_upcalls(targ_cfg: @session::config, fn decl(llmod: ModuleRef, prefix: ~str, name: ~str, tys: ~[TypeRef], rv: TypeRef) -> ValueRef { - let mut arg_tys: ~[TypeRef] = ~[]; - for tys.each |t| { arg_tys.push(*t); } + let arg_tys = tys.map(|t| *t); let fn_ty = T_fn(arg_tys, rv); return base::decl_cdecl_fn(llmod, prefix + name, fn_ty); } diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index e389f3a4bdf..934a02d6dd3 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -1,6 +1,6 @@ // -*- rust -*- use metadata::{creader, cstore, filesearch}; -use session::{session, session_, OptLevel, No, Less, Default, Aggressive}; +use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive}; use syntax::parse; use syntax::{ast, codemap}; use syntax::attr; @@ -10,8 +10,10 @@ use util::ppaux; use back::link; use result::{Ok, Err}; use std::getopts; +use std::getopts::{opt_present}; +use std::getopts::groups; +use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; use io::WriterUtil; -use getopts::{optopt, optmulti, optflag, optflagopt, opt_present}; use back::{x86, x86_64}; use std::map::HashMap; use lib::llvm::llvm; @@ -32,7 +34,7 @@ fn source_name(input: input) -> ~str { } } -fn default_configuration(sess: session, argv0: ~str, input: input) -> +fn default_configuration(sess: Session, argv0: ~str, input: input) -> ast::crate_cfg { let libc = match sess.targ_cfg.os { session::os_win32 => ~"msvcrt.dll", @@ -70,7 +72,7 @@ fn append_configuration(cfg: ast::crate_cfg, name: ~str) -> ast::crate_cfg { } } -fn build_configuration(sess: session, argv0: ~str, input: input) -> +fn build_configuration(sess: Session, argv0: ~str, input: input) -> ast::crate_cfg { // Combine the configuration requested by the session (command line) with // some default and generated configuration items @@ -106,7 +108,7 @@ enum input { str_input(~str) } -fn parse_input(sess: session, cfg: ast::crate_cfg, input: input) +fn parse_input(sess: Session, cfg: ast::crate_cfg, input: input) -> @ast::crate { match input { file_input(file) => { @@ -145,7 +147,7 @@ impl compile_upto : cmp::Eq { pure fn ne(other: &compile_upto) -> bool { !self.eq(other) } } -fn compile_upto(sess: session, cfg: ast::crate_cfg, +fn compile_upto(sess: Session, cfg: ast::crate_cfg, input: input, upto: compile_upto, outputs: Option<output_filenames>) -> {crate: @ast::crate, tcx: Option<ty::ctxt>} { @@ -277,7 +279,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, return {crate: crate, tcx: Some(ty_cx)}; } -fn compile_input(sess: session, cfg: ast::crate_cfg, input: input, +fn compile_input(sess: Session, cfg: ast::crate_cfg, input: input, outdir: &Option<Path>, output: &Option<Path>) { let upto = if sess.opts.parse_only { cu_parse } @@ -287,7 +289,7 @@ fn compile_input(sess: session, cfg: ast::crate_cfg, input: input, compile_upto(sess, cfg, input, upto, Some(outputs)); } -fn pretty_print_input(sess: session, cfg: ast::crate_cfg, input: input, +fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: input, ppm: pp_mode) { fn ann_paren_for_expr(node: pprust::ann_node) { match node { @@ -571,7 +573,7 @@ fn build_session_options(binary: ~str, } fn build_session(sopts: @session::options, - demitter: diagnostic::emitter) -> session { + demitter: diagnostic::emitter) -> Session { let codemap = codemap::new_codemap(); let diagnostic_handler = diagnostic::mk_handler(Some(demitter)); @@ -581,11 +583,10 @@ fn build_session(sopts: @session::options, } fn build_session_(sopts: @session::options, - cm: codemap::codemap, + cm: codemap::CodeMap, demitter: diagnostic::emitter, span_diagnostic_handler: diagnostic::span_handler) - -> session { - + -> Session { let target_cfg = build_target_config(sopts, demitter); let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, cm); @@ -595,7 +596,7 @@ fn build_session_(sopts: @session::options, sopts.target_triple, sopts.addl_lib_search_paths); let lint_settings = lint::mk_lint_settings(); - session_(@{targ_cfg: target_cfg, + Session_(@{targ_cfg: target_cfg, opts: sopts, cstore: cstore, parse_sess: p_s, @@ -609,7 +610,7 @@ fn build_session_(sopts: @session::options, lint_settings: lint_settings}) } -fn parse_pretty(sess: session, &&name: ~str) -> pp_mode { +fn parse_pretty(sess: Session, &&name: ~str) -> pp_mode { match name { ~"normal" => ppm_normal, ~"expanded" => ppm_expanded, @@ -624,27 +625,69 @@ fn parse_pretty(sess: session, &&name: ~str) -> pp_mode { } } -fn opts() -> ~[getopts::Opt] { - return ~[optflag(~"h"), optflag(~"help"), - optflag(~"v"), optflag(~"version"), - optflag(~"emit-llvm"), optflagopt(~"pretty"), - optflag(~"ls"), optflag(~"parse-only"), optflag(~"no-trans"), - optflag(~"O"), optopt(~"opt-level"), optmulti(~"L"), optflag(~"S"), - optopt(~"o"), optopt(~"out-dir"), optflag(~"xg"), - optflag(~"c"), optflag(~"g"), optflag(~"save-temps"), - optopt(~"sysroot"), optopt(~"target"), - optflag(~"jit"), - - optmulti(~"W"), optmulti(~"warn"), - optmulti(~"A"), optmulti(~"allow"), - optmulti(~"D"), optmulti(~"deny"), - optmulti(~"F"), optmulti(~"forbid"), - - optmulti(~"Z"), - - optmulti(~"cfg"), optflag(~"test"), - optflag(~"lib"), optflag(~"bin"), - optflag(~"static"), optflag(~"gc")]; +// rustc command line options +fn optgroups() -> ~[getopts::groups::OptGroup] { + ~[ + optflag(~"", ~"bin", ~"Compile an executable crate (default)"), + optflag(~"c", ~"", ~"Compile and assemble, but do not link"), + optmulti(~"", ~"cfg", ~"Configure the compilation + environment", ~"SPEC"), + optflag(~"", ~"emit-llvm", + ~"Produce an LLVM bitcode file"), + optflag(~"g", ~"", ~"Produce debug info (experimental)"), + optflag(~"", ~"gc", ~"Garbage collect shared data (experimental)"), + optflag(~"h", ~"help",~"Display this message"), + optmulti(~"L", ~"", ~"Add a directory to the library search path", + ~"PATH"), + optflag(~"", ~"lib", ~"Compile a library crate"), + optflag(~"", ~"ls", ~"List the symbols defined by a library crate"), + optflag(~"", ~"jit", ~"Execute using JIT (experimental)"), + optflag(~"", ~"no-trans", + ~"Run all passes except translation; no output"), + optflag(~"O", ~"", ~"Equivalent to --opt-level=2"), + optopt(~"o", ~"", ~"Write output to <filename>", ~"FILENAME"), + optopt(~"", ~"opt-level", + ~"Optimize with possible levels 0-3", ~"LEVEL"), + optopt( ~"", ~"out-dir", + ~"Write output to compiler-chosen filename + in <dir>", ~"DIR"), + optflag(~"", ~"parse-only", + ~"Parse only; do not compile, assemble, or link"), + optflagopt(~"", ~"pretty", + ~"Pretty-print the input instead of compiling; + valid types are: normal (un-annotated source), + expanded (crates expanded), + typed (crates expanded, with type annotations), + or identified (fully parenthesized, + AST nodes and blocks with IDs)", ~"TYPE"), + optflag(~"S", ~"", ~"Compile only; do not assemble or link"), + optflag(~"", ~"xg", ~"Extra debugging info (experimental)"), + optflag(~"", ~"save-temps", + ~"Write intermediate files (.bc, .opt.bc, .o) + in addition to normal output"), + optflag(~"", ~"static", + ~"Use or produce static libraries or binaries + (experimental)"), + optopt(~"", ~"sysroot", + ~"Override the system root", ~"PATH"), + optflag(~"", ~"test", ~"Build a test harness"), + optopt(~"", ~"target", + ~"Target triple cpu-manufacturer-kernel[-os] + to compile for (see + http://sources.redhat.com/autobook/autobook/autobook_17.html + for detail)", ~"TRIPLE"), + optmulti(~"W", ~"warn", + ~"Set lint warnings", ~"OPT"), + optmulti(~"A", ~"allow", + ~"Set lint allowed", ~"OPT"), + optmulti(~"D", ~"deny", + ~"Set lint denied", ~"OPT"), + optmulti(~"F", ~"forbid", + ~"Set lint forbidden", ~"OPT"), + optmulti(~"Z", ~"", ~"Set internal debugging options", "FLAG"), + optflag( ~"v", ~"version", + ~"Print version info and exit"), + ] } type output_filenames = @{out_filename:Path, obj_filename:Path}; @@ -652,7 +695,7 @@ type output_filenames = @{out_filename:Path, obj_filename:Path}; fn build_output_filenames(input: input, odir: &Option<Path>, ofile: &Option<Path>, - sess: session) + sess: Session) -> output_filenames { let obj_path; let out_path; @@ -728,7 +771,7 @@ fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! { fail; } -fn list_metadata(sess: session, path: &Path, out: io::Writer) { +fn list_metadata(sess: Session, path: &Path, out: io::Writer) { metadata::loader::list_file_metadata( sess.parse_sess.interner, session::sess_os_to_meta_os(sess.targ_cfg.os), path, out); @@ -742,7 +785,7 @@ mod test { #[test] fn test_switch_implies_cfg_test() { let matches = - match getopts::getopts(~[~"--test"], opts()) { + match getopts(~[~"--test"], optgroups()) { Ok(m) => m, Err(f) => fail ~"test_switch_implies_cfg_test: " + getopts::fail_str(f) @@ -759,7 +802,7 @@ mod test { #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = - match getopts::getopts(~[~"--test", ~"--cfg=test"], opts()) { + match getopts(~[~"--test", ~"--cfg=test"], optgroups()) { Ok(m) => m, Err(f) => { fail ~"test_switch_implies_cfg_test_unless_cfg_test: " + diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index c60904419d5..a6de92ceeb3 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -3,10 +3,10 @@ #[allow(non_camel_case_types)]; #[legacy_modes]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod rustc(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod rustc(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; @@ -16,6 +16,7 @@ use io::ReaderUtil; use std::getopts; use std::map::HashMap; use getopts::{opt_present}; +use getopts::groups; use rustc::driver::driver::*; use syntax::codemap; use syntax::diagnostic; @@ -31,58 +32,23 @@ fn version(argv0: &str) { } fn usage(argv0: &str) { - io::println(fmt!("Usage: %s [options] <input>\n", argv0) + - ~" -Options: - - --bin Compile an executable crate (default) - -c Compile and assemble, but do not link - --cfg <cfgspec> Configure the compilation environment - --emit-llvm Produce an LLVM bitcode file - -g Produce debug info (experimental) - --gc Garbage collect shared data (experimental/temporary) - -h --help Display this message - -L <path> Add a directory to the library search path - --lib Compile a library crate - --ls List the symbols defined by a compiled library crate - --jit Execute using JIT (experimental) - --no-trans Run all passes except translation; no output - -O Equivalent to --opt-level=2 - -o <filename> Write output to <filename> - --opt-level <lvl> Optimize with possible levels 0-3 - --out-dir <dir> Write output to compiler-chosen filename in <dir> - --parse-only Parse only; do not compile, assemble, or link - --pretty [type] Pretty-print the input instead of compiling; - valid types are: normal (un-annotated source), - expanded (crates expanded), typed (crates expanded, - with type annotations), or identified (fully - parenthesized, AST nodes and blocks with IDs) - -S Compile only; do not assemble or link - --save-temps Write intermediate files (.bc, .opt.bc, .o) - in addition to normal output - --static Use or produce static libraries or binaries - (experimental) - --sysroot <path> Override the system root - --test Build a test harness - --target <triple> Target cpu-manufacturer-kernel[-os] to compile for - (default: host triple) - (see http://sources.redhat.com/autobook/autobook/ - autobook_17.html for detail) - - -(W|A|D|F) help Print available 'lint' checks and default settings - - -W <foo> warn about <foo> by default - -A <foo> allow <foo> by default - -D <foo> deny <foo> by default - -F <foo> forbid <foo> (deny, and deny all overrides) - - -Z help list internal options for debugging rustc - - -v --version Print version info and exit + let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0); + io::println(groups::usage(message, optgroups()) + + ~"Additional help: + -W help Print 'lint' options and default settings + -Z help Print internal options for debugging rustc "); } fn describe_warnings() { + io::println(fmt!(" +Available lint options: + -W <foo> Warn about <foo> + -A <foo> Allow <foo> + -D <foo> Deny <foo> + -F <foo> Forbid <foo> (deny, and deny all overrides) +")); + let lint_dict = lint::get_lint_dict(); let mut max_key = 0; for lint_dict.each_key |k| { max_key = uint::max(k.len(), max_key); } @@ -113,7 +79,7 @@ fn describe_debug_flags() { io::println(fmt!("\nAvailable debug options:\n")); for session::debugging_opts_map().each |pair| { let (name, desc, _) = *pair; - io::println(fmt!(" -Z%-20s -- %s", name, desc)); + io::println(fmt!(" -Z %-20s -- %s", name, desc)); } } @@ -127,7 +93,7 @@ fn run_compiler(args: &~[~str], demitter: diagnostic::emitter) { if args.is_empty() { usage(binary); return; } let matches = - match getopts::getopts(args, opts()) { + match getopts::groups::getopts(args, optgroups()) { Ok(m) => m, Err(f) => { early_error(demitter, getopts::fail_str(f)) @@ -235,7 +201,7 @@ fn monitor(+f: fn~(diagnostic::emitter)) { // The 'diagnostics emitter'. Every error, warning, etc. should // go through this function. - let demitter = fn@(cmsp: Option<(codemap::codemap, codemap::span)>, + let demitter = fn@(cmsp: Option<(codemap::CodeMap, codemap::span)>, msg: &str, lvl: diagnostic::level) { if lvl == diagnostic::fatal { comm::send(ch, fatal); @@ -267,7 +233,7 @@ fn monitor(+f: fn~(diagnostic::emitter)) { ~"try running with RUST_LOG=rustc=0,::rt::backtrace \ to get further details and report the results \ to github.com/mozilla/rust/issues" - ]/_.each |note| { + ].each |note| { diagnostic::emit(None, *note, diagnostic::note) } } diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index c6c0ff2826a..ed73bcb6d72 100644 --- a/src/rustc/driver/session.rs +++ b/src/rustc/driver/session.rs @@ -46,18 +46,15 @@ const trans_stats: uint = 1 << 4; const no_asm_comments: uint = 1 << 5; const no_verify: uint = 1 << 6; const trace: uint = 1 << 7; -// FIXME (#2377): This exists to transition to a Rust crate runtime -// It should be removed -const no_rt: uint = 1 << 8; -const coherence: uint = 1 << 9; -const borrowck_stats: uint = 1 << 10; -const borrowck_note_pure: uint = 1 << 11; -const borrowck_note_loan: uint = 1 << 12; -const no_landing_pads: uint = 1 << 13; -const debug_llvm: uint = 1 << 14; -const count_type_sizes: uint = 1 << 15; -const meta_stats: uint = 1 << 16; -const no_opt: uint = 1 << 17; +const coherence: uint = 1 << 8; +const borrowck_stats: uint = 1 << 9; +const borrowck_note_pure: uint = 1 << 10; +const borrowck_note_loan: uint = 1 << 11; +const no_landing_pads: uint = 1 << 12; +const debug_llvm: uint = 1 << 13; +const count_type_sizes: uint = 1 << 14; +const meta_stats: uint = 1 << 15; +const no_opt: uint = 1 << 16; fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"verbose", ~"in general, enable more debug printouts", verbose), @@ -70,7 +67,6 @@ fn debugging_opts_map() -> ~[(~str, ~str, uint)] { (~"no-asm-comments", ~"omit comments when using -S", no_asm_comments), (~"no-verify", ~"skip LLVM verification", no_verify), (~"trace", ~"emit trace logs", trace), - (~"no-rt", ~"do not link to the runtime", no_rt), (~"coherence", ~"perform coherence checking", coherence), (~"borrowck-stats", ~"gather borrowck statistics", borrowck_stats), (~"borrowck-note-pure", ~"note where purity is req'd", @@ -131,24 +127,24 @@ type options = type crate_metadata = {name: ~str, data: ~[u8]}; -type session_ = {targ_cfg: @config, +type Session_ = {targ_cfg: @config, opts: @options, - cstore: metadata::cstore::cstore, + cstore: metadata::cstore::CStore, parse_sess: parse_sess, - codemap: codemap::codemap, + codemap: codemap::CodeMap, // For a library crate, this is always none mut main_fn: Option<(node_id, codemap::span)>, span_diagnostic: diagnostic::span_handler, - filesearch: filesearch::filesearch, + filesearch: filesearch::FileSearch, mut building_library: bool, working_dir: Path, lint_settings: lint::lint_settings}; -enum session { - session_(@session_) +enum Session { + Session_(@Session_) } -impl session { +impl Session { fn span_fatal(sp: span, msg: ~str) -> ! { self.span_diagnostic.span_fatal(sp, msg) } @@ -220,7 +216,7 @@ impl session { // This exists to help with refactoring to eliminate impossible // cases later on fn impossible_case(sp: span, msg: &str) -> ! { - self.span_bug(sp, #fmt("Impossible case reached: %s", msg)); + self.span_bug(sp, fmt!("Impossible case reached: %s", msg)); } fn verbose() -> bool { self.debugging_opt(verbose) } fn time_passes() -> bool { self.debugging_opt(time_passes) } @@ -274,7 +270,7 @@ fn basic_options() -> @options { } // Seems out of place, but it uses session, so I'm putting it here -fn expect<T: Copy>(sess: session, opt: Option<T>, msg: fn() -> ~str) -> T { +fn expect<T: Copy>(sess: Session, opt: Option<T>, msg: fn() -> ~str) -> T { diagnostic::expect(sess.diagnostic(), opt, msg) } diff --git a/src/rustc/front/core_inject.rs b/src/rustc/front/core_inject.rs index f198a2ca79d..e9be56e7d48 100644 --- a/src/rustc/front/core_inject.rs +++ b/src/rustc/front/core_inject.rs @@ -1,4 +1,4 @@ -use driver::session::session; +use driver::session::Session; use syntax::codemap; use syntax::ast; use syntax::ast_util::*; @@ -6,7 +6,7 @@ use syntax::attr; export maybe_inject_libcore_ref; -fn maybe_inject_libcore_ref(sess: session, +fn maybe_inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { if use_core(crate) { inject_libcore_ref(sess, crate) @@ -19,7 +19,7 @@ fn use_core(crate: @ast::crate) -> bool { !attr::attrs_contains_name(crate.node.attrs, ~"no_core") } -fn inject_libcore_ref(sess: session, +fn inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { fn spanned<T: Copy>(x: T) -> @ast::spanned<T> { diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index 879c73308da..2a87f089c8d 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -6,7 +6,7 @@ mod intrinsic { pub use rusti::visit_tydesc; - // FIXME (#2712): remove this when the interface has settled and the + // FIXME (#3727): remove this when the interface has settled and the // version in sys is no longer present. pub fn get_tydesc<T>() -> *TyDesc { rusti::get_tydesc::<T>() as *TyDesc diff --git a/src/rustc/front/intrinsic_inject.rs b/src/rustc/front/intrinsic_inject.rs index 8fd885e8f8b..ac74bac3f2f 100644 --- a/src/rustc/front/intrinsic_inject.rs +++ b/src/rustc/front/intrinsic_inject.rs @@ -1,10 +1,10 @@ -use driver::session::session; +use driver::session::Session; use syntax::parse; use syntax::ast; export inject_intrinsic; -fn inject_intrinsic(sess: session, +fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate { let intrinsic_module = @include_str!("intrinsic.rs"); diff --git a/src/rustc/front/test.rs b/src/rustc/front/test.rs index 1a6cc6dd895..f0c9de4f2a2 100644 --- a/src/rustc/front/test.rs +++ b/src/rustc/front/test.rs @@ -7,7 +7,7 @@ use syntax::fold; use syntax::print::pprust; use syntax::codemap::span; use driver::session; -use session::session; +use session::Session; use syntax::attr; use dvec::DVec; @@ -19,14 +19,14 @@ type test = {span: span, path: ~[ast::ident], ignore: bool, should_fail: bool}; type test_ctxt = - @{sess: session::session, + @{sess: session::Session, crate: @ast::crate, mut path: ~[ast::ident], testfns: DVec<test>}; // Traverse the crate, collecting all the test functions, eliding any // existing main functions, and synthesizing a main test harness -fn modify_for_testing(sess: session::session, +fn modify_for_testing(sess: session::Session, crate: @ast::crate) -> @ast::crate { if sess.opts.test { @@ -36,7 +36,7 @@ fn modify_for_testing(sess: session::session, } } -fn generate_test_harness(sess: session::session, +fn generate_test_harness(sess: session::Session, crate: @ast::crate) -> @ast::crate { let cx: test_ctxt = @{sess: sess, @@ -261,13 +261,13 @@ fn mk_path(cx: test_ctxt, path: ~[ast::ident]) -> ~[ast::ident] { else { vec::append(~[cx.sess.ident_of(~"std")], path) } } -// The ast::ty of ~[std::test::test_desc] -fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::ty { +// The ast::Ty of ~[std::test::test_desc] +fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty { let test_desc_ty_path = path_node(mk_path(cx, ~[cx.sess.ident_of(~"test"), cx.sess.ident_of(~"TestDesc")])); - let test_desc_ty: ast::ty = + let test_desc_ty: ast::Ty = {id: cx.sess.next_node_id(), node: ast::ty_path(test_desc_ty_path, cx.sess.next_node_id()), span: dummy_sp()}; diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index 1857abf2cf2..06f1dfdab1a 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -124,5 +124,9 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f tag_table_legacy_boxed_trait = 0x63 } +const tag_item_trait_method_sort: uint = 0x70; + +const tag_item_impl_type_basename: uint = 0x71; + type link_meta = {name: ~str, vers: ~str, extras_hash: ~str}; diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs index 3ed56a1953e..3080426e531 100644 --- a/src/rustc/metadata/creader.rs +++ b/src/rustc/metadata/creader.rs @@ -7,7 +7,7 @@ use syntax::visit; use syntax::codemap::span; use std::map::HashMap; use syntax::print::pprust; -use filesearch::filesearch; +use filesearch::FileSearch; use common::*; use dvec::DVec; use syntax::parse::token::ident_interner; @@ -17,7 +17,7 @@ export read_crates; // Traverses an AST, reading all the information about use'd crates and extern // libraries necessary for later resolving, typechecking, linking, etc. fn read_crates(diag: span_handler, crate: ast::crate, - cstore: cstore::cstore, filesearch: filesearch, + cstore: cstore::CStore, filesearch: FileSearch, os: loader::os, static: bool, intr: @ident_interner) { let e = @{diag: diag, filesearch: filesearch, @@ -88,8 +88,8 @@ fn warn_if_multiple_versions(e: env, diag: span_handler, } type env = @{diag: span_handler, - filesearch: filesearch, - cstore: cstore::cstore, + filesearch: FileSearch, + cstore: cstore::CStore, os: loader::os, static: bool, crate_cache: DVec<cache_entry>, diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index e29a4fd436b..141613c2240 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -1,6 +1,6 @@ // Searching for information from the cstore -use std::{ebml}; +use std::ebml; use syntax::ast; use syntax::ast_util; use syntax::ast_map; @@ -23,7 +23,10 @@ export get_region_param; export get_enum_variants; export get_impls_for_mod; export get_trait_methods; +export get_provided_trait_methods; export get_method_names_if_trait; +export get_type_name_if_impl; +export get_static_methods_if_impl; export get_item_attrs; export each_path; export get_type; @@ -31,19 +34,32 @@ export get_impl_traits; export get_impl_method; export get_item_path; export maybe_get_item_ast, found_ast, found, found_parent, not_found; +export ProvidedTraitMethodInfo; +export StaticMethodInfo; -fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> ~str { +struct ProvidedTraitMethodInfo { + ty: ty::method, + def_id: ast::def_id +} + +struct StaticMethodInfo { + ident: ast::ident, + def_id: ast::def_id, + purity: ast::purity +} + +fn get_symbol(cstore: cstore::CStore, def: ast::def_id) -> ~str { let cdata = cstore::get_crate_data(cstore, def.crate).data; return decoder::get_symbol(cdata, def.node); } -fn get_type_param_count(cstore: cstore::cstore, def: ast::def_id) -> uint { +fn get_type_param_count(cstore: cstore::CStore, def: ast::def_id) -> uint { let cdata = cstore::get_crate_data(cstore, def.crate).data; return decoder::get_type_param_count(cdata, def.node); } /// Iterates over all the paths in the given crate. -fn each_path(cstore: cstore::cstore, cnum: ast::crate_num, +fn each_path(cstore: cstore::CStore, cnum: ast::crate_num, f: fn(decoder::path_entry) -> bool) { let crate_data = cstore::get_crate_data(cstore, cnum); decoder::each_path(cstore.intr, crate_data, f); @@ -84,7 +100,7 @@ fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id) return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx) } -fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id, +fn get_impls_for_mod(cstore: cstore::CStore, def: ast::def_id, name: Option<ast::ident>) -> @~[@decoder::_impl] { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -99,14 +115,33 @@ fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] { decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx) } -fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id) +fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> + ~[ProvidedTraitMethodInfo] { + let cstore = tcx.cstore; + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx) +} + +fn get_method_names_if_trait(cstore: cstore::CStore, def: ast::def_id) -> Option<@DVec<(ast::ident, ast::self_ty_)>> { let cdata = cstore::get_crate_data(cstore, def.crate); return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node); } -fn get_item_attrs(cstore: cstore::cstore, +fn get_type_name_if_impl(cstore: cstore::CStore, def: ast::def_id) -> + Option<ast::ident> { + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_type_name_if_impl(cstore.intr, cdata, def.node) +} + +fn get_static_methods_if_impl(cstore: cstore::CStore, def: ast::def_id) -> + Option<~[StaticMethodInfo]> { + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_static_methods_if_impl(cstore.intr, cdata, def.node) +} + +fn get_item_attrs(cstore: cstore::CStore, def_id: ast::def_id, f: fn(~[@ast::meta_item])) { @@ -126,7 +161,7 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty { decoder::get_type(cdata, def.node, tcx) } -fn get_region_param(cstore: metadata::cstore::cstore, +fn get_region_param(cstore: metadata::cstore::CStore, def: ast::def_id) -> Option<ty::region_variance> { let cdata = cstore::get_crate_data(cstore, def.crate); return decoder::get_region_param(cdata, def.node); @@ -163,7 +198,7 @@ fn get_impl_traits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { decoder::get_impl_traits(cdata, def.node, tcx) } -fn get_impl_method(cstore: cstore::cstore, +fn get_impl_method(cstore: cstore::CStore, def: ast::def_id, mname: ast::ident) -> ast::def_id { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -174,7 +209,7 @@ fn get_impl_method(cstore: cstore::cstore, for their methods (so that get_trait_methods can be reused to get class methods), classes require a slightly different version of get_impl_method. Sigh. */ -fn get_class_method(cstore: cstore::cstore, +fn get_class_method(cstore: cstore::CStore, def: ast::def_id, mname: ast::ident) -> ast::def_id { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -182,7 +217,7 @@ fn get_class_method(cstore: cstore::cstore, } /* If def names a class with a dtor, return it. Otherwise, return none. */ -fn class_dtor(cstore: cstore::cstore, def: ast::def_id) +fn class_dtor(cstore: cstore::CStore, def: ast::def_id) -> Option<ast::def_id> { let cdata = cstore::get_crate_data(cstore, def.crate); decoder::class_dtor(cdata, def.node) diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs index d59464d58c7..6db3982297e 100644 --- a/src/rustc/metadata/cstore.rs +++ b/src/rustc/metadata/cstore.rs @@ -6,7 +6,7 @@ use std::map::HashMap; use syntax::{ast, attr}; use syntax::parse::token::ident_interner; -export cstore; +export CStore; export cnum_map; export crate_metadata; export mk_cstore; @@ -49,7 +49,7 @@ type crate_metadata = @{name: ~str, // other modules to access the cstore's private data. This could also be // achieved with an obj, but at the expense of a vtable. Not sure if this is a // good pattern or not. -enum cstore { private(cstore_private), } +enum CStore { private(cstore_private), } type cstore_private = @{metas: map::HashMap<ast::crate_num, crate_metadata>, @@ -64,11 +64,11 @@ type cstore_private = type use_crate_map = map::HashMap<ast::node_id, ast::crate_num>; // Internal method to retrieve the data from the cstore -pure fn p(cstore: cstore) -> cstore_private { +pure fn p(cstore: CStore) -> cstore_private { match cstore { private(p) => p } } -fn mk_cstore(intr: @ident_interner) -> cstore { +fn mk_cstore(intr: @ident_interner) -> CStore { let meta_cache = map::HashMap(); let crate_map = map::HashMap(); let mod_path_map = HashMap(); @@ -81,21 +81,21 @@ fn mk_cstore(intr: @ident_interner) -> cstore { intr: intr}); } -fn get_crate_data(cstore: cstore, cnum: ast::crate_num) -> crate_metadata { +fn get_crate_data(cstore: CStore, cnum: ast::crate_num) -> crate_metadata { return p(cstore).metas.get(cnum); } -fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> ~str { +fn get_crate_hash(cstore: CStore, cnum: ast::crate_num) -> ~str { let cdata = get_crate_data(cstore, cnum); return decoder::get_crate_hash(cdata.data); } -fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> ~str { +fn get_crate_vers(cstore: CStore, cnum: ast::crate_num) -> ~str { let cdata = get_crate_data(cstore, cnum); return decoder::get_crate_vers(cdata.data); } -fn set_crate_data(cstore: cstore, cnum: ast::crate_num, +fn set_crate_data(cstore: CStore, cnum: ast::crate_num, data: crate_metadata) { p(cstore).metas.insert(cnum, data); for vec::each(decoder::get_crate_module_paths(cstore.intr, data)) |dp| { @@ -105,25 +105,25 @@ fn set_crate_data(cstore: cstore, cnum: ast::crate_num, } } -fn have_crate_data(cstore: cstore, cnum: ast::crate_num) -> bool { +fn have_crate_data(cstore: CStore, cnum: ast::crate_num) -> bool { return p(cstore).metas.contains_key(cnum); } -fn iter_crate_data(cstore: cstore, i: fn(ast::crate_num, crate_metadata)) { +fn iter_crate_data(cstore: CStore, i: fn(ast::crate_num, crate_metadata)) { for p(cstore).metas.each |k,v| { i(k, v);}; } -fn add_used_crate_file(cstore: cstore, lib: &Path) { +fn add_used_crate_file(cstore: CStore, lib: &Path) { if !vec::contains(p(cstore).used_crate_files, lib) { p(cstore).used_crate_files.push(copy *lib); } } -fn get_used_crate_files(cstore: cstore) -> ~[Path] { +fn get_used_crate_files(cstore: CStore) -> ~[Path] { return p(cstore).used_crate_files; } -fn add_used_library(cstore: cstore, lib: ~str) -> bool { +fn add_used_library(cstore: CStore, lib: ~str) -> bool { assert lib != ~""; if vec::contains(p(cstore).used_libraries, &lib) { return false; } @@ -131,31 +131,31 @@ fn add_used_library(cstore: cstore, lib: ~str) -> bool { return true; } -fn get_used_libraries(cstore: cstore) -> ~[~str] { +fn get_used_libraries(cstore: CStore) -> ~[~str] { return p(cstore).used_libraries; } -fn add_used_link_args(cstore: cstore, args: ~str) { +fn add_used_link_args(cstore: CStore, args: ~str) { p(cstore).used_link_args.push_all(str::split_char(args, ' ')); } -fn get_used_link_args(cstore: cstore) -> ~[~str] { +fn get_used_link_args(cstore: CStore) -> ~[~str] { return p(cstore).used_link_args; } -fn add_use_stmt_cnum(cstore: cstore, use_id: ast::node_id, +fn add_use_stmt_cnum(cstore: CStore, use_id: ast::node_id, cnum: ast::crate_num) { p(cstore).use_crate_map.insert(use_id, cnum); } -fn find_use_stmt_cnum(cstore: cstore, +fn find_use_stmt_cnum(cstore: CStore, use_id: ast::node_id) -> Option<ast::crate_num> { p(cstore).use_crate_map.find(use_id) } // returns hashes of crates directly used by this crate. Hashes are // sorted by crate name. -fn get_dep_hashes(cstore: cstore) -> ~[~str] { +fn get_dep_hashes(cstore: CStore) -> ~[~str] { type crate_hash = {name: ~str, hash: ~str}; let mut result = ~[]; @@ -175,7 +175,7 @@ fn get_dep_hashes(cstore: cstore) -> ~[~str] { return vec::map(sorted, mapper); } -fn get_path(cstore: cstore, d: ast::def_id) -> ~[~str] { +fn get_path(cstore: CStore, d: ast::def_id) -> ~[~str] { option::map_default(&p(cstore).mod_path_map.find(d), ~[], |ds| str::split_str(**ds, ~"::")) } diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 0e6bc2aee15..4e30132b1a7 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -1,7 +1,9 @@ // Decoding metadata from a single crate's metadata -use std::{ebml, map}; +use std::ebml; +use std::map; use std::map::HashMap; +use std::serialization::deserialize; use io::WriterUtil; use dvec::DVec; use syntax::{ast, ast_util}; @@ -17,6 +19,7 @@ use syntax::diagnostic::span_handler; use common::*; use syntax::parse::token::ident_interner; use hash::{Hash, HashUtil}; +use csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; export class_dtor; export get_class_fields; @@ -28,6 +31,7 @@ export get_type_param_count; export get_impl_traits; export get_class_method; export get_impl_method; +export get_static_methods_if_impl; export lookup_def; export resolve_path; export get_crate_attributes; @@ -38,7 +42,9 @@ export get_crate_hash; export get_crate_vers; export get_impls_for_mod; export get_trait_methods; +export get_provided_trait_methods; export get_method_names_if_trait; +export get_type_name_if_impl; export get_item_attrs; export get_crate_module_paths; export def_like; @@ -69,10 +75,10 @@ fn lookup_hash(d: ebml::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) -> let table = ebml::get_doc(index, tag_index_table); let hash_pos = table.start + hash % 256u * 4u; let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint; - let {tag:_, doc:bucket} = ebml::doc_at(d.data, pos); + let tagged_doc = ebml::doc_at(d.data, pos); let belt = tag_index_buckets_bucket_elt; - for ebml::tagged_docs(bucket, belt) |elt| { + for ebml::tagged_docs(tagged_doc.doc, belt) |elt| { let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint; if eq_fn(vec::view(*elt.data, elt.start + 4u, elt.end)) { return Some(ebml::doc_at(d.data, pos).doc); @@ -122,7 +128,6 @@ enum Family { Variant, // v Impl, // i Trait, // I - Class, // C Struct, // S PublicField, // g PrivateField, // j @@ -155,15 +160,21 @@ fn item_family(item: ebml::Doc) -> Family { 'v' => Variant, 'i' => Impl, 'I' => Trait, - 'C' => Class, 'S' => Struct, 'g' => PublicField, 'j' => PrivateField, 'N' => InheritedField, - c => fail (#fmt("unexpected family char: %c", c)) + c => fail (fmt!("unexpected family char: %c", c)) } } +fn item_method_sort(item: ebml::Doc) -> char { + for ebml::tagged_docs(item, tag_item_trait_method_sort) |doc| { + return str::from_bytes(ebml::doc_data(doc))[0] as char; + } + return 'r'; +} + fn item_symbol(item: ebml::Doc) -> ~str { let sym = ebml::get_doc(item, tag_items_data_item_symbol); return str::from_bytes(ebml::doc_data(sym)); @@ -176,6 +187,18 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> { None } +fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) -> + Option<ast::def_id> { + let trait_did_opt = item_parent_item(d); + trait_did_opt.map(|trait_did| {crate: cnum, node: trait_did.node}) +} + +fn item_reqd_and_translated_parent_item(cnum: ast::crate_num, + d: ebml::Doc) -> ast::def_id { + let trait_did = item_parent_item(d).expect(~"item without parent"); + {crate: cnum, node: trait_did.node} +} + fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { let tagdoc = ebml::get_doc(d, tag_def_id); return translate_def_id(cdata, ebml::with_doc_data(tagdoc, @@ -246,8 +269,7 @@ fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> { ebml::maybe_get_doc(item, tag_region_param).map(|doc| { - let d = ebml::ebml_deserializer(*doc); - ty::deserialize_region_variance(d) + deserialize(&ebml::Deserializer(*doc)) }) } @@ -296,35 +318,38 @@ fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) - -> def_like { + -> def_like +{ let fam = item_family(item); match fam { - Const => dl_def(ast::def_const(did)), - Class => dl_def(ast::def_class(did, true)), - Struct => dl_def(ast::def_class(did, false)), - UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), - Fn => dl_def(ast::def_fn(did, ast::impure_fn)), - PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), - ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), - UnsafeStaticMethod => dl_def(ast::def_static_method(did, - ast::unsafe_fn)), - StaticMethod => dl_def(ast::def_static_method(did, ast::impure_fn)), - PureStaticMethod => dl_def(ast::def_static_method(did, ast::pure_fn)), - Type | ForeignType => dl_def(ast::def_ty(did)), - Mod => dl_def(ast::def_mod(did)), - ForeignMod => dl_def(ast::def_foreign_mod(did)), - Variant => { - match item_parent_item(item) { - Some(t) => { - let tid = {crate: cnum, node: t.node}; - dl_def(ast::def_variant(tid, did)) - } - None => fail ~"item_to_def_like: enum item has no parent" - } - } - Trait | Enum => dl_def(ast::def_ty(did)), - Impl => dl_impl(did), - PublicField | PrivateField | InheritedField => dl_field, + Const => dl_def(ast::def_const(did)), + Struct => dl_def(ast::def_class(did)), + UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), + Fn => dl_def(ast::def_fn(did, ast::impure_fn)), + PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), + ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), + UnsafeStaticMethod => { + let trait_did_opt = translated_parent_item_opt(cnum, item); + dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn)) + } + StaticMethod => { + let trait_did_opt = translated_parent_item_opt(cnum, item); + dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn)) + } + PureStaticMethod => { + let trait_did_opt = translated_parent_item_opt(cnum, item); + dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn)) + } + Type | ForeignType => dl_def(ast::def_ty(did)), + Mod => dl_def(ast::def_mod(did)), + ForeignMod => dl_def(ast::def_foreign_mod(did)), + Variant => { + let enum_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_variant(enum_did, did)) + } + Trait | Enum => dl_def(ast::def_ty(did)), + Impl => dl_impl(did), + PublicField | PrivateField | InheritedField => dl_field, } } @@ -581,13 +606,12 @@ fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, let ctor_ty = item_type({crate: cdata.cnum, node: id}, item, tcx, cdata); let name = item_name(intr, item); - let mut arg_tys: ~[ty::t] = ~[]; - match ty::get(ctor_ty).sty { - ty::ty_fn(f) => { - for f.sig.inputs.each |a| { arg_tys.push(a.ty); } - } - _ => { /* Nullary enum variant. */ } - } + let arg_tys = match ty::get(ctor_ty).sty { + ty::ty_fn(f) => f.sig.inputs.map(|a| a.ty), + + // Nullary enum variant. + _ => ~[], + }; match variant_disr_val(item) { Some(val) => { disr_val = val; } _ => { /* empty */ } @@ -646,7 +670,6 @@ fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc, let mth_item = lookup_item(m_did.node, cdata.data); let self_ty = get_self_ty(mth_item); rslt.push(@{did: translate_def_id(cdata, m_did), - /* FIXME (maybe #2323) tjc: take a look at this. */ n_tps: item_ty_param_count(mth_item) - base_tps, ident: item_name(intr, mth_item), self_type: self_ty}); @@ -694,6 +717,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, let bounds = item_ty_param_bounds(mth, tcx, cdata); let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); + let def_id = item_def_id(mth, cdata); let fty = match ty::get(ty).sty { ty::ty_fn(f) => f, _ => { @@ -701,14 +725,52 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, ~"get_trait_methods: id has non-function type"); } }; let self_ty = get_self_ty(mth); - result.push({ident: name, tps: bounds, fty: fty, - self_ty: self_ty, - vis: ast::public}); + result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty, + vis: ast::public, def_id: def_id}); } - #debug("get_trait_methods: }"); + debug!("get_trait_methods: }"); @result } +fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, + id: ast::node_id, tcx: ty::ctxt) -> + ~[ProvidedTraitMethodInfo] { + let data = cdata.data; + let item = lookup_item(id, data); + let mut result = ~[]; + + for ebml::tagged_docs(item, tag_item_trait_method) |mth| { + if item_method_sort(mth) != 'p' { loop; } + + let did = item_def_id(mth, cdata); + + let bounds = item_ty_param_bounds(mth, tcx, cdata); + let name = item_name(intr, mth); + let ty = doc_type(mth, tcx, cdata); + + let fty; + match ty::get(ty).sty { + ty::ty_fn(f) => fty = f, + _ => { + tcx.diag.handler().bug(~"get_provided_trait_methods(): id \ + has non-function type"); + } + } + + let self_ty = get_self_ty(mth); + let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty, + vis: ast::public, def_id: did}; + let provided_trait_method_info = ProvidedTraitMethodInfo { + ty: ty_method, + def_id: did + }; + + vec::push(&mut result, move provided_trait_method_info); + } + + return move result; +} + // If the item in question is a trait, returns its set of methods and // their self types. Otherwise, returns none. This overlaps in an // annoying way with get_trait_methods. @@ -729,6 +791,67 @@ fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd, return Some(resulting_methods); } +fn get_type_name_if_impl(intr: @ident_interner, + cdata: cmd, + node_id: ast::node_id) -> Option<ast::ident> { + let item = lookup_item(node_id, cdata.data); + if item_family(item) != Impl { + return None; + } + + for ebml::tagged_docs(item, tag_item_impl_type_basename) |doc| { + return Some(intr.intern(@str::from_bytes(ebml::doc_data(doc)))); + } + + return None; +} + +fn get_static_methods_if_impl(intr: @ident_interner, + cdata: cmd, + node_id: ast::node_id) -> + Option<~[StaticMethodInfo]> { + let item = lookup_item(node_id, cdata.data); + if item_family(item) != Impl { + return None; + } + + // If this impl has a trait ref, don't consider it. + for ebml::tagged_docs(item, tag_impl_trait) |_doc| { + return None; + } + + let impl_method_ids = DVec(); + for ebml::tagged_docs(item, tag_item_impl_method) |impl_method_doc| { + impl_method_ids.push(parse_def_id(ebml::doc_data(impl_method_doc))); + } + + let static_impl_methods = DVec(); + for impl_method_ids.each |impl_method_id| { + let impl_method_doc = lookup_item(impl_method_id.node, cdata.data); + let family = item_family(impl_method_doc); + match family { + StaticMethod | UnsafeStaticMethod | PureStaticMethod => { + let purity; + match item_family(impl_method_doc) { + StaticMethod => purity = ast::impure_fn, + UnsafeStaticMethod => purity = ast::unsafe_fn, + PureStaticMethod => purity = ast::pure_fn, + _ => fail + } + + static_impl_methods.push(StaticMethodInfo { + ident: item_name(intr, impl_method_doc), + def_id: item_def_id(impl_method_doc, cdata), + purity: purity + }); + } + _ => {} + } + } + + return Some(dvec::unwrap(move static_impl_methods)); +} + fn get_item_attrs(cdata: cmd, node_id: ast::node_id, f: fn(~[@ast::meta_item])) { @@ -822,7 +945,6 @@ fn item_family_to_str(fam: Family) -> ~str { Variant => ~"variant", Impl => ~"impl", Trait => ~"trait", - Class => ~"class", Struct => ~"struct", PublicField => ~"public field", PrivateField => ~"private field", diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index a65c25a46ef..f7e80e53ed5 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -5,7 +5,7 @@ use util::ppaux::ty_to_str; use std::{ebml, map}; use std::map::HashMap; use io::WriterUtil; -use ebml::Writer; +use ebml::Serializer; use syntax::ast::*; use syntax::print::pprust; use syntax::{ast_util, visit}; @@ -40,7 +40,7 @@ export encode_def_id; type abbrev_map = map::HashMap<ty::t, tyencode::ty_abbrev>; type encode_inlined_item = fn@(ecx: @encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, path: ast_map::path, ii: ast::inlined_item); @@ -52,7 +52,7 @@ type encode_parms = { item_symbols: HashMap<ast::node_id, ~str>, discrim_symbols: HashMap<ast::node_id, ~str>, link_meta: link_meta, - cstore: cstore::cstore, + cstore: cstore::CStore, encode_inlined_item: encode_inlined_item }; @@ -77,7 +77,7 @@ enum encode_ctxt = { item_symbols: HashMap<ast::node_id, ~str>, discrim_symbols: HashMap<ast::node_id, ~str>, link_meta: link_meta, - cstore: cstore::cstore, + cstore: cstore::CStore, encode_inlined_item: encode_inlined_item, type_abbrevs: abbrev_map }; @@ -86,25 +86,31 @@ fn reachable(ecx: @encode_ctxt, id: node_id) -> bool { ecx.reachable.contains_key(id) } -fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Writer, name: ident) { +fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Serializer, name: ident) { ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name)); } -fn encode_def_id(ebml_w: ebml::Writer, id: def_id) { +fn encode_impl_type_basename(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + name: ident) { + ebml_w.wr_tagged_str(tag_item_impl_type_basename, + ecx.tcx.sess.str_of(name)); +} + +fn encode_def_id(ebml_w: ebml::Serializer, id: def_id) { ebml_w.wr_tagged_str(tag_def_id, def_to_str(id)); } -fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::Serializer, it: @ast::item) { let opt_rp = ecx.tcx.region_paramd_items.find(it.id); for opt_rp.each |rp| { do ebml_w.wr_tag(tag_region_param) { - ty::serialize_region_variance(ebml_w, *rp); + (*rp).serialize(&ebml_w); } } } -fn encode_mutability(ebml_w: ebml::Writer, mt: class_mutability) { +fn encode_mutability(ebml_w: ebml::Serializer, mt: class_mutability) { do ebml_w.wr_tag(tag_class_mut) { let val = match mt { class_immutable => 'a', @@ -116,7 +122,7 @@ fn encode_mutability(ebml_w: ebml::Writer, mt: class_mutability) { type entry<T> = {val: T, pos: uint}; -fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: &[ident], +fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Serializer, path: &[ident], index: &mut ~[entry<~str>], name: ident) { let mut full_path = ~[]; full_path.push_all(path); @@ -127,7 +133,8 @@ fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: &[ident], pos: ebml_w.writer.tell()}); } -fn encode_trait_ref(ebml_w: ebml::Writer, ecx: @encode_ctxt, t: @trait_ref) { +fn encode_trait_ref(ebml_w: ebml::Serializer, ecx: @encode_ctxt, + t: @trait_ref) { ebml_w.start_tag(tag_impl_trait); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id)); ebml_w.end_tag(); @@ -135,7 +142,7 @@ fn encode_trait_ref(ebml_w: ebml::Writer, ecx: @encode_ctxt, t: @trait_ref) { // Item info table encoding -fn encode_family(ebml_w: ebml::Writer, c: char) { +fn encode_family(ebml_w: ebml::Serializer, c: char) { ebml_w.start_tag(tag_items_data_item_family); ebml_w.writer.write(&[c as u8]); ebml_w.end_tag(); @@ -143,7 +150,7 @@ fn encode_family(ebml_w: ebml::Writer, c: char) { fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } -fn encode_ty_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, +fn encode_ty_type_param_bounds(ebml_w: ebml::Serializer, ecx: @encode_ctxt, params: @~[ty::param_bounds]) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -157,7 +164,7 @@ fn encode_ty_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, } } -fn encode_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, +fn encode_type_param_bounds(ebml_w: ebml::Serializer, ecx: @encode_ctxt, params: ~[ty_param]) { let ty_param_bounds = @params.map(|param| ecx.tcx.ty_param_bounds.get(param.id)); @@ -165,13 +172,13 @@ fn encode_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, } -fn encode_variant_id(ebml_w: ebml::Writer, vid: def_id) { +fn encode_variant_id(ebml_w: ebml::Serializer, vid: def_id) { ebml_w.start_tag(tag_items_data_item_variant); ebml_w.writer.write(str::to_bytes(def_to_str(vid))); ebml_w.end_tag(); } -fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) { +fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Serializer, typ: ty::t) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -181,7 +188,8 @@ fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) { tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } -fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) { +fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + vstore: ty::vstore) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -191,13 +199,13 @@ fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) { tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } -fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) { +fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Serializer, typ: ty::t) { ebml_w.start_tag(tag_items_data_item_type); write_type(ecx, ebml_w, typ); ebml_w.end_tag(); } -fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::Writer, id: node_id) { +fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); let sym = match ecx.item_symbols.find(id) { Some(x) => x, @@ -210,25 +218,27 @@ fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::Writer, id: node_id) { ebml_w.end_tag(); } -fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml::Writer, id: node_id) { +fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); ebml_w.writer.write(str::to_bytes(ecx.discrim_symbols.get(id))); ebml_w.end_tag(); } -fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::Writer, disr_val: int) { +fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::Serializer, + disr_val: int) { ebml_w.start_tag(tag_disr_val); ebml_w.writer.write(str::to_bytes(int::to_str(disr_val,10u))); ebml_w.end_tag(); } -fn encode_parent_item(ebml_w: ebml::Writer, id: def_id) { +fn encode_parent_item(ebml_w: ebml::Serializer, id: def_id) { ebml_w.start_tag(tag_items_data_parent_item); ebml_w.writer.write(str::to_bytes(def_to_str(id))); ebml_w.end_tag(); } -fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, variants: ~[variant], path: ast_map::path, index: @mut ~[entry<int>], ty_params: ~[ty_param]) { @@ -265,9 +275,9 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::Writer, } } -fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: ast_map::path, - name: ast_map::path_elt) { - fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + path: ast_map::path, name: ast_map::path_elt) { + fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml::Serializer, elt: ast_map::path_elt) { let (tag, name) = match elt { ast_map::path_mod(name) => (tag_path_elt_mod, name), @@ -286,7 +296,7 @@ fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: ast_map::path, } } -fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::Writer, md: _mod, +fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::Serializer, md: _mod, id: node_id, path: ast_map::path, name: ident) { ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(id)); @@ -344,7 +354,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::Writer, md: _mod, ebml_w.end_tag(); } -fn encode_visibility(ebml_w: ebml::Writer, visibility: visibility) { +fn encode_visibility(ebml_w: ebml::Serializer, visibility: visibility) { encode_family(ebml_w, match visibility { public => 'g', private => 'j', @@ -352,7 +362,7 @@ fn encode_visibility(ebml_w: ebml::Writer, visibility: visibility) { }); } -fn encode_self_type(ebml_w: ebml::Writer, self_type: ast::self_ty_) { +fn encode_self_type(ebml_w: ebml::Serializer, self_type: ast::self_ty_) { ebml_w.start_tag(tag_item_trait_method_self_ty); // Encode the base self type. @@ -384,8 +394,14 @@ fn encode_self_type(ebml_w: ebml::Writer, self_type: ast::self_ty_) { ebml_w.end_tag(); } +fn encode_method_sort(ebml_w: ebml::Serializer, sort: char) { + ebml_w.start_tag(tag_item_trait_method_sort); + ebml_w.writer.write(&[ sort as u8 ]); + ebml_w.end_tag(); +} + /* Returns an index of items in this class */ -fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, path: ast_map::path, class_tps: ~[ty_param], fields: ~[@struct_field], @@ -441,7 +457,7 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Writer, } // This is for encoding info for ctors and dtors -fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, ident: ident, path: ast_map::path, item: Option<inlined_item>, tps: ~[ty_param]) { ebml_w.start_tag(tag_items_data_item); @@ -466,7 +482,7 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Serializer, impl_path: ast_map::path, should_inline: bool, parent_id: node_id, m: @method, all_tps: ~[ty_param]) { @@ -474,7 +490,12 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Writer, ecx.tcx.sess.str_of(m.ident), all_tps.len()); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(m.id)); - encode_family(ebml_w, purity_fn_family(m.purity)); + match m.self_ty.node { + ast::sty_static => { + encode_family(ebml_w, purity_static_method_family(m.purity)); + } + _ => encode_family(ebml_w, purity_fn_family(m.purity)) + } encode_type_param_bounds(ebml_w, ecx, all_tps); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id)); encode_name(ecx, ebml_w, m.ident); @@ -516,8 +537,9 @@ fn should_inline(attrs: ~[attribute]) -> bool { } -fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, - index: @mut ~[entry<int>], path: ast_map::path) { +fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + item: @item, index: @mut ~[entry<int>], + path: ast_map::path) { let tcx = ecx.tcx; let must_write = @@ -528,7 +550,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, }; if !must_write && !reachable(ecx, item.id) { return; } - fn add_to_index_(item: @item, ebml_w: ebml::Writer, + fn add_to_index_(item: @item, ebml_w: ebml::Serializer, index: @mut ~[entry<int>]) { index.push({val: item.id, pos: ebml_w.writer.tell()}); } @@ -630,12 +652,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, /* Now, make an item for the class itself */ ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - - match struct_def.ctor { - None => encode_family(ebml_w, 'S'), - Some(_) => encode_family(ebml_w, 'C') - } - + encode_family(ebml_w, 'S'); encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); @@ -694,23 +711,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, let bkts = create_index(idx); encode_index(ebml_w, bkts, write_int); ebml_w.end_tag(); - - /* Encode the constructor */ - for struct_def.ctor.each |ctor| { - debug!("encoding info for ctor %s %d", - ecx.tcx.sess.str_of(item.ident), ctor.node.id); - index.push({ - val: ctor.node.id, - pos: ebml_w.writer.tell() - }); - encode_info_for_ctor(ecx, ebml_w, ctor.node.id, item.ident, - path, if tps.len() > 0u { - Some(ii_ctor(*ctor, item.ident, tps, - local_def(item.id))) } - else { None }, tps); - } } - item_impl(tps, opt_trait, _, methods) => { + item_impl(tps, opt_trait, ty, methods) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -720,6 +722,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); + match ty.node { + ast::ty_path(path, _) if path.idents.len() == 1 => { + encode_impl_type_basename(ecx, ebml_w, + ast_util::path_to_ident(path)); + } + _ => {} + } for methods.each |m| { ebml_w.start_tag(tag_item_impl_method); ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id)))); @@ -741,6 +750,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, } } item_trait(tps, traits, ms) => { + let provided_methods = dvec::DVec(); + add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -761,12 +772,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty)); encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); encode_self_type(ebml_w, mty.self_ty); + encode_method_sort(ebml_w, 'r'); ebml_w.end_tag(); } provided(m) => { - encode_info_for_method(ecx, ebml_w, path, - should_inline(m.attrs), item.id, - m, m.tps); + provided_methods.push(m); + + ebml_w.start_tag(tag_item_trait_method); + encode_def_id(ebml_w, local_def(m.id)); + encode_name(ecx, ebml_w, mty.ident); + encode_type_param_bounds(ebml_w, ecx, m.tps); + encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty)); + encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); + encode_self_type(ebml_w, mty.self_ty); + encode_method_sort(ebml_w, 'p'); + ebml_w.end_tag(); } } i += 1u; @@ -789,6 +809,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(ty_m.id)); + encode_parent_item(ebml_w, local_def(item.id)); encode_name(ecx, ebml_w, ty_m.ident); encode_family(ebml_w, purity_static_method_family(ty_m.purity)); @@ -799,13 +820,18 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, ebml_w.end_tag(); } - + // Finally, output all the provided methods as items. + for provided_methods.each |m| { + index.push({val: m.id, pos: ebml_w.writer.tell()}); + encode_info_for_method(ecx, ebml_w, path, true, item.id, *m, + m.tps); + } } item_mac(*) => fail ~"item macros unimplemented" } } -fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, nitem: @foreign_item, index: @mut ~[entry<int>], path: ast_map::path, abi: foreign_abi) { @@ -838,7 +864,7 @@ fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::Serializer, crate: @crate) -> ~[entry<int>] { let index = @mut ~[]; ebml_w.start_tag(tag_items_data); @@ -893,7 +919,7 @@ fn create_index<T: Copy Hash IterBytes>(index: ~[entry<T>]) -> return buckets_frozen; } -fn encode_index<T>(ebml_w: ebml::Writer, buckets: ~[@~[entry<T>]], +fn encode_index<T>(ebml_w: ebml::Serializer, buckets: ~[@~[entry<T>]], write_fn: fn(io::Writer, T)) { let writer = ebml_w.writer; ebml_w.start_tag(tag_index); @@ -928,7 +954,7 @@ fn write_int(writer: io::Writer, &&n: int) { writer.write_be_u32(n as u32); } -fn encode_meta_item(ebml_w: ebml::Writer, mi: meta_item) { +fn encode_meta_item(ebml_w: ebml::Serializer, mi: meta_item) { match mi.node { meta_word(name) => { ebml_w.start_tag(tag_meta_item_word); @@ -965,7 +991,7 @@ fn encode_meta_item(ebml_w: ebml::Writer, mi: meta_item) { } } -fn encode_attributes(ebml_w: ebml::Writer, attrs: ~[attribute]) { +fn encode_attributes(ebml_w: ebml::Serializer, attrs: ~[attribute]) { ebml_w.start_tag(tag_attributes); for attrs.each |attr| { ebml_w.start_tag(tag_attribute); @@ -1026,10 +1052,10 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] { return attrs; } -fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Writer, - cstore: cstore::cstore) { +fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + cstore: cstore::CStore) { - fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::cstore) + fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::CStore) -> ~[decoder::crate_dep] { type hashkv = @{key: crate_num, val: cstore::crate_metadata}; @@ -1072,7 +1098,7 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::Serializer, dep: decoder::crate_dep) { ebml_w.start_tag(tag_crate_dep); ebml_w.start_tag(tag_crate_dep_name); @@ -1087,7 +1113,7 @@ fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_hash(ebml_w: ebml::Writer, hash: ~str) { +fn encode_hash(ebml_w: ebml::Serializer, hash: ~str) { ebml_w.start_tag(tag_crate_hash); ebml_w.writer.write(str::to_bytes(hash)); ebml_w.end_tag(); @@ -1125,7 +1151,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { type_abbrevs: ty::new_ty_hash() }); - let ebml_w = ebml::Writer(wr as io::Writer); + let ebml_w = ebml::Serializer(wr as io::Writer); encode_hash(ebml_w, ecx.link_meta.extras_hash); @@ -1154,7 +1180,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { if (parms.tcx.sess.meta_stats()) { - do wr.buf.borrow |v| { + do wr.bytes.borrow |v| { do v.each |e| { if *e == 0 { ecx.stats.zero_bytes += 1; @@ -1187,7 +1213,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { (do str::as_bytes(&~"rust\x00\x00\x00\x01") |bytes| { vec::slice(*bytes, 0, 8) - }) + flate::deflate_bytes(wr.buf.check_out(|buf| buf)) + }) + flate::deflate_bytes(wr.bytes.check_out(|buf| buf)) } // Get the encoded string for a type diff --git a/src/rustc/metadata/filesearch.rs b/src/rustc/metadata/filesearch.rs index 63370b09321..b2d20ce56e8 100644 --- a/src/rustc/metadata/filesearch.rs +++ b/src/rustc/metadata/filesearch.rs @@ -3,7 +3,7 @@ // probably just be folded into cstore. use result::Result; -export filesearch; +export FileSearch; export mk_filesearch; export pick; export pick_file; @@ -21,7 +21,7 @@ fn pick_file(file: Path, path: &Path) -> Option<Path> { else { option::None } } -trait filesearch { +trait FileSearch { fn sysroot() -> Path; fn lib_search_paths() -> ~[Path]; fn get_target_lib_path() -> Path; @@ -30,11 +30,11 @@ trait filesearch { fn mk_filesearch(maybe_sysroot: Option<Path>, target_triple: &str, - addl_lib_search_paths: ~[Path]) -> filesearch { + addl_lib_search_paths: ~[Path]) -> FileSearch { type filesearch_impl = {sysroot: Path, addl_lib_search_paths: ~[Path], target_triple: ~str}; - impl filesearch_impl: filesearch { + impl filesearch_impl: FileSearch { fn sysroot() -> Path { self.sysroot } fn lib_search_paths() -> ~[Path] { let mut paths = self.addl_lib_search_paths; @@ -64,10 +64,10 @@ fn mk_filesearch(maybe_sysroot: Option<Path>, debug!("using sysroot = %s", sysroot.to_str()); {sysroot: sysroot, addl_lib_search_paths: addl_lib_search_paths, - target_triple: str::from_slice(target_triple)} as filesearch + target_triple: str::from_slice(target_triple)} as FileSearch } -fn search<T: Copy>(filesearch: filesearch, pick: pick<T>) -> Option<T> { +fn search<T: Copy>(filesearch: FileSearch, pick: pick<T>) -> Option<T> { let mut rslt = None; for filesearch.lib_search_paths().each |lib_search_path| { debug!("searching %s", lib_search_path.to_str()); diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs index 0a8354be71f..61b8bcf9067 100644 --- a/src/rustc/metadata/loader.rs +++ b/src/rustc/metadata/loader.rs @@ -5,7 +5,7 @@ use syntax::{ast, attr}; use syntax::print::pprust; use syntax::codemap::span; use lib::llvm::{False, llvm, mk_object_file, mk_section_iter}; -use filesearch::filesearch; +use filesearch::FileSearch; use io::WriterUtil; use syntax::parse::token::ident_interner; @@ -28,7 +28,7 @@ enum os { type ctxt = { diag: span_handler, - filesearch: filesearch, + filesearch: FileSearch, span: span, ident: ast::ident, metas: ~[@ast::meta_item], @@ -66,7 +66,7 @@ fn libname(cx: ctxt) -> {prefix: ~str, suffix: ~str} { fn find_library_crate_aux(cx: ctxt, nn: {prefix: ~str, suffix: ~str}, - filesearch: filesearch::filesearch) -> + filesearch: filesearch::FileSearch) -> Option<{ident: ~str, data: @~[u8]}> { let crate_name = crate_name_from_metas(cx.metas); let prefix: ~str = nn.prefix + crate_name + ~"-"; diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index 1375ff2d0be..14aef6db1ad 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -162,7 +162,7 @@ fn parse_bound_region(st: @pstate) -> ty::bound_region { } } -fn parse_region(st: @pstate) -> ty::region { +fn parse_region(st: @pstate) -> ty::Region { match next(st) { 'b' => { ty::re_bound(parse_bound_region(st)) diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 69689b16e15..941dd35bdf0 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -125,7 +125,7 @@ fn enc_substs(w: io::Writer, cx: @ctxt, substs: ty::substs) { w.write_char(']'); } -fn enc_region(w: io::Writer, cx: @ctxt, r: ty::region) { +fn enc_region(w: io::Writer, cx: @ctxt, r: ty::Region) { match r { ty::re_bound(br) => { w.write_char('b'); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index a364c1d75d4..d264188e65d 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -8,22 +8,19 @@ use syntax::ast_map; use syntax::ast_util; use syntax::codemap::span; use std::ebml; -use std::ebml::Writer; -use std::ebml::get_doc; +use std::ebml::{Serializer, get_doc}; use std::map::HashMap; -use std::serialization::Serializer; -use std::serialization::Deserializer; -use std::serialization::SerializerHelpers; -use std::serialization::DeserializerHelpers; -use std::prettyprint::Serializer; +use std::serialization; +use std::serialization::{Serializable, + SerializerHelpers, + DeserializerHelpers, + deserialize}; use middle::{ty, typeck}; use middle::typeck::{method_origin, method_map_entry, vtable_res, vtable_origin}; -use driver::session::session; -use middle::freevars::{freevar_entry, - serialize_freevar_entry, - deserialize_freevar_entry}; +use driver::session::Session; +use middle::freevars::freevar_entry; use c = metadata::common; use e = metadata::encoder; use cstore = metadata::cstore; @@ -76,7 +73,7 @@ trait tr { // Top-level methods. fn encode_inlined_item(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, path: ast_map::path, ii: ast::inlined_item, maps: maps) { @@ -87,7 +84,7 @@ fn encode_inlined_item(ecx: @e::encode_ctxt, let id_range = ast_util::compute_id_range_for_inlined_item(ii); do ebml_w.wr_tag(c::tag_ast as uint) { - ast_util::serialize_id_range(ebml_w, id_range); + id_range.serialize(&ebml_w); encode_ast(ebml_w, simplify_ast(ii)); encode_side_tables_for_ii(ecx, maps, ebml_w, ii); } @@ -109,8 +106,8 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, Some(ast_doc) => { debug!("> Decoding inlined fn: %s::?", ast_map::path_to_str(path, tcx.sess.parse_sess.interner)); - let ast_dsr = ebml::ebml_deserializer(ast_doc); - let from_id_range = ast_util::deserialize_id_range(ast_dsr); + let ast_dsr = &ebml::Deserializer(ast_doc); + let from_id_range = deserialize(ast_dsr); let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range); let xcx = extended_decode_ctxt_(@{dcx: dcx, from_id_range: from_id_range, @@ -139,7 +136,7 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -fn reserve_id_range(sess: session, +fn reserve_id_range(sess: Session, from_id_range: ast_util::id_range) -> ast_util::id_range { // Handle the case of an empty range: if ast_util::empty(from_id_range) { return from_id_range; } @@ -187,9 +184,9 @@ trait def_id_serializer_helpers { fn emit_def_id(did: ast::def_id); } -impl<S: Serializer> S: def_id_serializer_helpers { +impl<S: serialization::Serializer> S: def_id_serializer_helpers { fn emit_def_id(did: ast::def_id) { - ast::serialize_def_id(self, did) + did.serialize(&self) } } @@ -197,10 +194,10 @@ trait def_id_deserializer_helpers { fn read_def_id(xcx: extended_decode_ctxt) -> ast::def_id; } -impl<D: Deserializer> D: def_id_deserializer_helpers { +impl<D: serialization::Deserializer> D: def_id_deserializer_helpers { fn read_def_id(xcx: extended_decode_ctxt) -> ast::def_id { - let did = ast::deserialize_def_id(self); + let did: ast::def_id = deserialize(&self); did.tr(xcx) } } @@ -220,9 +217,9 @@ impl<D: Deserializer> D: def_id_deserializer_helpers { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(ebml_w: ebml::Writer, item: ast::inlined_item) { +fn encode_ast(ebml_w: ebml::Serializer, item: ast::inlined_item) { do ebml_w.wr_tag(c::tag_tree as uint) { - ast::serialize_inlined_item(ebml_w, item) + item.serialize(&ebml_w) } } @@ -264,13 +261,6 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_ctor(ctor, nm, tps, parent_id) => { - let ctor_body = fld.fold_block(ctor.node.body); - let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); - ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, - .. ctor.node}, - .. ctor}, nm, tps, parent_id) - } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); ast::ii_dtor({node: {body: dtor_body, @@ -282,8 +272,8 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item { let chi_doc = par_doc[c::tag_tree as uint]; - let d = ebml::ebml_deserializer(chi_doc); - ast::deserialize_inlined_item(d) + let d = &ebml::Deserializer(chi_doc); + deserialize(d) } fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) @@ -304,18 +294,6 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_ctor(ctor, nm, tps, parent_id) => { - let ctor_body = fld.fold_block(ctor.node.body); - let ctor_attrs = fld.fold_attributes(ctor.node.attrs); - let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); - let new_params = fold::fold_ty_params(tps, fld); - let ctor_id = fld.new_id(ctor.node.id); - let new_parent = xcx.tr_def_id(parent_id); - ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs, - dec: ctor_decl, id: ctor_id, - .. ctor.node}, - .. ctor}, nm, new_params, new_parent) - } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); let dtor_attrs = fld.fold_attributes(dtor.node.attrs); @@ -334,13 +312,13 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) // ______________________________________________________________________ // Encoding and decoding of ast::def -fn encode_def(ebml_w: ebml::Writer, def: ast::def) { - ast::serialize_def(ebml_w, def) +fn encode_def(ebml_w: ebml::Serializer, def: ast::def) { + def.serialize(&ebml_w) } fn decode_def(xcx: extended_decode_ctxt, doc: ebml::Doc) -> ast::def { - let dsr = ebml::ebml_deserializer(doc); - let def = ast::deserialize_def(dsr); + let dsr = &ebml::Deserializer(doc); + let def: ast::def = deserialize(dsr); def.tr(xcx) } @@ -348,8 +326,10 @@ impl ast::def: tr { fn tr(xcx: extended_decode_ctxt) -> ast::def { match self { ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) } - ast::def_static_method(did, p) => { - ast::def_static_method(did.tr(xcx), p) + ast::def_static_method(did, did2_opt, p) => { + ast::def_static_method(did.tr(xcx), + did2_opt.map(|did2| did2.tr(xcx)), + p) } ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } @@ -371,8 +351,8 @@ impl ast::def: tr { xcx.tr_id(nid2), xcx.tr_id(nid3)) } - ast::def_class(did, has_constructor) => { - ast::def_class(did.tr(xcx), has_constructor) + ast::def_class(did) => { + ast::def_class(did.tr(xcx)) } ast::def_region(nid) => ast::def_region(xcx.tr_id(nid)), ast::def_typaram_binder(nid) => { @@ -401,8 +381,8 @@ impl ty::AutoRef: tr { } } -impl ty::region: tr { - fn tr(xcx: extended_decode_ctxt) -> ty::region { +impl ty::Region: tr { + fn tr(xcx: extended_decode_ctxt) -> ty::Region { match self { ty::re_bound(br) => ty::re_bound(br.tr(xcx)), ty::re_free(id, br) => ty::re_free(xcx.tr_id(id), br.tr(xcx)), @@ -425,17 +405,17 @@ impl ty::bound_region: tr { // ______________________________________________________________________ // Encoding and decoding of freevar information -fn encode_freevar_entry(ebml_w: ebml::Writer, fv: freevar_entry) { - serialize_freevar_entry(ebml_w, fv) +fn encode_freevar_entry(ebml_w: ebml::Serializer, fv: @freevar_entry) { + (*fv).serialize(&ebml_w) } trait ebml_deserializer_helper { fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry; } -impl ebml::EbmlDeserializer: ebml_deserializer_helper { +impl ebml::Deserializer: ebml_deserializer_helper { fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry { - let fv = deserialize_freevar_entry(self); + let fv: freevar_entry = deserialize(&self); fv.tr(xcx) } } @@ -454,28 +434,29 @@ trait read_method_map_entry_helper { } fn serialize_method_map_entry(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, mme: method_map_entry) { do ebml_w.emit_rec { - do ebml_w.emit_rec_field(~"self_arg", 0u) { + do ebml_w.emit_field(~"self_arg", 0u) { ebml_w.emit_arg(ecx, mme.self_arg); } - do ebml_w.emit_rec_field(~"origin", 1u) { - typeck::serialize_method_origin(ebml_w, mme.origin); + do ebml_w.emit_field(~"origin", 1u) { + mme.origin.serialize(&ebml_w); } } } -impl ebml::EbmlDeserializer: read_method_map_entry_helper { +impl ebml::Deserializer: read_method_map_entry_helper { fn read_method_map_entry(xcx: extended_decode_ctxt) -> method_map_entry { do self.read_rec { {self_arg: - self.read_rec_field(~"self_arg", 0u, || { + self.read_field(~"self_arg", 0u, || { self.read_arg(xcx) }), origin: - self.read_rec_field(~"origin", 1u, || { - typeck::deserialize_method_origin(self).tr(xcx) + self.read_field(~"origin", 1u, || { + let method_origin: method_origin = deserialize(&self); + method_origin.tr(xcx) })} } } @@ -504,19 +485,19 @@ impl method_origin: tr { // Encoding and decoding vtable_res fn encode_vtable_res(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, dr: typeck::vtable_res) { // can't autogenerate this code because automatic serialization of // ty::t doesn't work, and there is no way (atm) to have // hand-written serialization routines combine with auto-generated // ones. perhaps we should fix this. do ebml_w.emit_from_vec(*dr) |vtable_origin| { - encode_vtable_origin(ecx, ebml_w, vtable_origin) + encode_vtable_origin(ecx, ebml_w, *vtable_origin) } } fn encode_vtable_origin(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, vtable_origin: typeck::vtable_origin) { do ebml_w.emit_enum(~"vtable_origin") { match vtable_origin { @@ -563,7 +544,7 @@ trait vtable_deserialization_helpers { fn read_vtable_origin(xcx: extended_decode_ctxt) -> typeck::vtable_origin; } -impl ebml::EbmlDeserializer: vtable_deserialization_helpers { +impl ebml::Deserializer: vtable_deserialization_helpers { fn read_vtable_res(xcx: extended_decode_ctxt) -> typeck::vtable_res { @self.read_to_vec(|| self.read_vtable_origin(xcx) ) } @@ -640,7 +621,7 @@ trait ebml_writer_helpers { fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty); } -impl ebml::Writer: ebml_writer_helpers { +impl ebml::Serializer: ebml_writer_helpers { fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t) { do self.emit_opaque { e::write_type(ecx, self, ty) @@ -661,7 +642,7 @@ impl ebml::Writer: ebml_writer_helpers { fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]) { do self.emit_from_vec(tys) |ty| { - self.emit_ty(ecx, ty) + self.emit_ty(ecx, *ty) } } @@ -673,17 +654,15 @@ impl ebml::Writer: ebml_writer_helpers { fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty) { do self.emit_rec { - do self.emit_rec_field(~"bounds", 0u) { + do self.emit_field(~"bounds", 0u) { do self.emit_from_vec(*tpbt.bounds) |bs| { - self.emit_bounds(ecx, bs); + self.emit_bounds(ecx, *bs); } } - do self.emit_rec_field(~"region_param", 1u) { - ty::serialize_opt_region_variance( - self, - tpbt.region_param); + do self.emit_field(~"region_param", 1u) { + tpbt.region_param.serialize(&self); } - do self.emit_rec_field(~"ty", 2u) { + do self.emit_field(~"ty", 2u) { self.emit_ty(ecx, tpbt.ty); } } @@ -695,7 +674,7 @@ trait write_tag_and_id { fn id(id: ast::node_id); } -impl ebml::Writer: write_tag_and_id { +impl ebml::Serializer: write_tag_and_id { fn tag(tag_id: c::astencode_tag, f: fn()) { do self.wr_tag(tag_id as uint) { f() } } @@ -707,7 +686,7 @@ impl ebml::Writer: write_tag_and_id { fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, maps: maps, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, ii: ast::inlined_item) { do ebml_w.wr_tag(c::tag_table as uint) { ast_util::visit_ids_for_inlined_item( @@ -723,7 +702,7 @@ fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, fn encode_side_tables_for_id(ecx: @e::encode_ctxt, maps: maps, - ebml_w: ebml::Writer, + ebml_w: ebml::Serializer, id: ast::node_id) { let tcx = ecx.tcx; @@ -733,7 +712,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, do ebml_w.tag(c::tag_table_def) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - ast::serialize_def(ebml_w, *def) + (*def).serialize(&ebml_w) } } } @@ -810,7 +789,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { do ebml_w.emit_from_vec((*m).get()) |id| { - ebml_w.emit_int(id); + id.serialize(&ebml_w); } } } @@ -838,7 +817,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, do ebml_w.tag(c::tag_table_adjustments) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - ty::serialize_AutoAdjustment(ebml_w, **adj) + (**adj).serialize(&ebml_w) } } } @@ -871,7 +850,7 @@ trait ebml_deserializer_decoder_helpers { -> ty::ty_param_bounds_and_ty; } -impl ebml::EbmlDeserializer: ebml_deserializer_decoder_helpers { +impl ebml::Deserializer: ebml_deserializer_decoder_helpers { fn read_arg(xcx: extended_decode_ctxt) -> ty::arg { do self.read_opaque |doc| { @@ -911,13 +890,13 @@ impl ebml::EbmlDeserializer: ebml_deserializer_decoder_helpers { { do self.read_rec { { - bounds: self.read_rec_field(~"bounds", 0u, || { + bounds: self.read_field(~"bounds", 0u, || { @self.read_to_vec(|| self.read_bounds(xcx) ) }), - region_param: self.read_rec_field(~"region_param", 1u, || { - ty::deserialize_opt_region_variance(self) + region_param: self.read_field(~"region_param", 1u, || { + deserialize(&self) }), - ty: self.read_rec_field(~"ty", 2u, || { + ty: self.read_field(~"ty", 2u, || { self.read_ty(xcx) }) } @@ -943,7 +922,7 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.tcx.legacy_boxed_traits.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val as uint]; - let val_dsr = ebml::ebml_deserializer(val_doc); + let val_dsr = &ebml::Deserializer(val_doc); if tag == (c::tag_table_def as uint) { let def = decode_def(xcx, val_doc); dcx.tcx.def_map.insert(id, def); @@ -979,7 +958,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.maps.vtable_map.insert(id, val_dsr.read_vtable_res(xcx)); } else if tag == (c::tag_table_adjustments as uint) { - let adj = @ty::deserialize_AutoAdjustment(val_dsr).tr(xcx); + let adj: @ty::AutoAdjustment = @deserialize(val_dsr); + adj.tr(xcx); dcx.tcx.adjustments.insert(id, adj); } else { xcx.dcx.tcx.sess.bug( @@ -995,17 +975,17 @@ fn decode_side_tables(xcx: extended_decode_ctxt, // Testing of astencode_gen #[cfg(test)] -fn encode_item_ast(ebml_w: ebml::Writer, item: @ast::item) { +fn encode_item_ast(ebml_w: ebml::Serializer, item: @ast::item) { do ebml_w.wr_tag(c::tag_tree as uint) { - ast::serialize_item(ebml_w, *item); + (*item).serialize(&ebml_w) } } #[cfg(test)] fn decode_item_ast(par_doc: ebml::Doc) -> @ast::item { let chi_doc = par_doc[c::tag_tree as uint]; - let d = ebml::ebml_deserializer(chi_doc); - @ast::deserialize_item(d) + let d = &ebml::Deserializer(chi_doc); + @deserialize(d) } #[cfg(test)] @@ -1031,16 +1011,18 @@ fn mk_ctxt() -> fake_ext_ctxt { #[cfg(test)] fn roundtrip(in_item: @ast::item) { let bytes = do io::with_bytes_writer |wr| { - let ebml_w = ebml::Writer(wr); + let ebml_w = ebml::Serializer(wr); encode_item_ast(ebml_w, in_item); }; let ebml_doc = ebml::Doc(@bytes); let out_item = decode_item_ast(ebml_doc); - let exp_str = - io::with_str_writer(|w| ast::serialize_item(w, *in_item) ); - let out_str = - io::with_str_writer(|w| ast::serialize_item(w, *out_item) ); + let exp_str = do io::with_str_writer |w| { + in_item.serialize(&std::prettyprint::Serializer(w)) + }; + let out_str = do io::with_str_writer |w| { + out_item.serialize(&std::prettyprint::Serializer(w)) + }; debug!("expected string: %s", exp_str); debug!("actual string : %s", out_str); diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index e2f7ba20642..db0e092ed83 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -229,7 +229,6 @@ use result::{Result, Ok, Err}; use syntax::print::pprust; use util::common::indenter; use ty::to_str; -use driver::session::session; use dvec::DVec; use mem_categorization::*; @@ -319,8 +318,8 @@ enum bckerr_code { err_mut_variant, err_root_not_permitted, err_mutbl(ast::mutability), - err_out_of_root_scope(ty::region, ty::region), // superscope, subscope - err_out_of_scope(ty::region, ty::region) // superscope, subscope + err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope + err_out_of_scope(ty::Region, ty::Region) // superscope, subscope } impl bckerr_code : cmp::Eq { @@ -383,7 +382,7 @@ impl bckerr : cmp::Eq { type bckres<T> = Result<T, bckerr>; /// a complete record of a loan that was granted -type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}; +struct Loan {lp: @loan_path, cmt: cmt, mutbl: ast::mutability} /// maps computed by `gather_loans` that are then used by `check_loans` /// @@ -392,7 +391,7 @@ type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}; /// - `pure_map`: map from block/expr that must be pure to the error message /// that should be reported if they are not pure type req_maps = { - req_loan_map: HashMap<ast::node_id, @DVec<@DVec<loan>>>, + req_loan_map: HashMap<ast::node_id, @DVec<Loan>>, pure_map: HashMap<ast::node_id, bckerr> }; @@ -436,7 +435,7 @@ fn root_map() -> root_map { // Misc impl borrowck_ctxt { - fn is_subregion_of(r_sub: ty::region, r_sup: ty::region) -> bool { + fn is_subregion_of(r_sub: ty::Region, r_sup: ty::Region) -> bool { region::is_subregion_of(self.tcx.region_map, r_sub, r_sup) } @@ -582,6 +581,11 @@ impl borrowck_ctxt { method_map: self.method_map}; mc.mut_to_str(mutbl) } + + fn loan_to_repr(loan: &Loan) -> ~str { + fmt!("Loan(lp=%?, cmt=%s, mutbl=%?)", + loan.lp, self.cmt_to_repr(loan.cmt), loan.mutbl) + } } // The inherent mutability of a component is its default mutability diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index cc8d89a8ace..7f95d44fd3b 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -17,10 +17,6 @@ enum check_loan_ctxt = @{ reported: HashMap<ast::node_id, ()>, - // Keep track of whether we're inside a ctor, so as to - // allow mutating immutable fields in the same class if - // we are in a ctor, we track the self id - mut in_ctor: bool, mut declared_purity: ast::purity, mut fn_args: @~[ast::node_id] }; @@ -62,7 +58,6 @@ fn check_loans(bccx: borrowck_ctxt, let clcx = check_loan_ctxt(@{bccx: bccx, req_maps: req_maps, reported: HashMap(), - mut in_ctor: false, mut declared_purity: ast::impure_fn, mut fn_args: @~[]}); let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, @@ -136,18 +131,15 @@ impl check_loan_ctxt { } } - fn walk_loans(scope_id: ast::node_id, - f: fn(v: &loan) -> bool) { + fn walk_loans(scope_id: ast::node_id, f: fn(v: &Loan) -> bool) { let mut scope_id = scope_id; let region_map = self.tcx().region_map; let req_loan_map = self.req_maps.req_loan_map; loop { - for req_loan_map.find(scope_id).each |loanss| { - for loanss.each |loans| { - for loans.each |loan| { - if !f(loan) { return; } - } + for req_loan_map.find(scope_id).each |loans| { + for loans.each |loan| { + if !f(loan) { return; } } } @@ -160,7 +152,7 @@ impl check_loan_ctxt { fn walk_loans_of(scope_id: ast::node_id, lp: @loan_path, - f: fn(v: &loan) -> bool) { + f: fn(v: &Loan) -> bool) { for self.walk_loans(scope_id) |loan| { if loan.lp == lp { if !f(loan) { return; } @@ -261,36 +253,58 @@ impl check_loan_ctxt { } fn check_for_conflicting_loans(scope_id: ast::node_id) { - let new_loanss = match self.req_maps.req_loan_map.find(scope_id) { + debug!("check_for_conflicting_loans(scope_id=%?)", scope_id); + + let new_loans = match self.req_maps.req_loan_map.find(scope_id) { None => return, - Some(loanss) => loanss + Some(loans) => loans }; + debug!("new_loans has length %?", new_loans.len()); + let par_scope_id = self.tcx().region_map.get(scope_id); for self.walk_loans(par_scope_id) |old_loan| { - for new_loanss.each |new_loans| { - for new_loans.each |new_loan| { - if old_loan.lp != new_loan.lp { loop; } - match (old_loan.mutbl, new_loan.mutbl) { - (m_const, _) | (_, m_const) | - (m_mutbl, m_mutbl) | (m_imm, m_imm) => { - /*ok*/ - } - - (m_mutbl, m_imm) | (m_imm, m_mutbl) => { - self.bccx.span_err( - new_loan.cmt.span, - fmt!("loan of %s as %s \ - conflicts with prior loan", - self.bccx.cmt_to_str(new_loan.cmt), - self.bccx.mut_to_str(new_loan.mutbl))); - self.bccx.span_note( - old_loan.cmt.span, - fmt!("prior loan as %s granted here", - self.bccx.mut_to_str(old_loan.mutbl))); - } - } - } + debug!("old_loan=%?", self.bccx.loan_to_repr(old_loan)); + + for new_loans.each |new_loan| { + self.report_error_if_loans_conflict(old_loan, new_loan); + } + } + + let len = new_loans.len(); + for uint::range(0, len) |i| { + let loan_i = new_loans[i]; + for uint::range(i+1, len) |j| { + let loan_j = new_loans[j]; + self.report_error_if_loans_conflict(&loan_i, &loan_j); + } + } + } + + fn report_error_if_loans_conflict(&self, + old_loan: &Loan, + new_loan: &Loan) { + if old_loan.lp != new_loan.lp { + return; + } + + match (old_loan.mutbl, new_loan.mutbl) { + (m_const, _) | (_, m_const) | + (m_mutbl, m_mutbl) | (m_imm, m_imm) => { + /*ok*/ + } + + (m_mutbl, m_imm) | (m_imm, m_mutbl) => { + self.bccx.span_err( + new_loan.cmt.span, + fmt!("loan of %s as %s \ + conflicts with prior loan", + self.bccx.cmt_to_str(new_loan.cmt), + self.bccx.mut_to_str(new_loan.mutbl))); + self.bccx.span_note( + old_loan.cmt.span, + fmt!("prior loan as %s granted here", + self.bccx.mut_to_str(old_loan.mutbl))); } } } @@ -320,10 +334,7 @@ impl check_loan_ctxt { debug!("check_assignment(cmt=%s)", self.bccx.cmt_to_repr(cmt)); - if self.in_ctor && self.is_self_field(cmt) - && at.checked_by_liveness() { - // assigning to self.foo in a ctor is always allowed. - } else if self.is_local_variable(cmt) && at.checked_by_liveness() { + if self.is_local_variable(cmt) && at.checked_by_liveness() { // liveness guarantees that immutable local variables // are only assigned once } else { @@ -542,42 +553,28 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt<check_loan_ctxt>) { debug!("purity on entry=%?", copy self.declared_purity); - do save_and_restore(&mut(self.in_ctor)) { - do save_and_restore(&mut(self.declared_purity)) { - do save_and_restore(&mut(self.fn_args)) { - let is_stack_closure = self.is_stack_closure(id); - let fty = ty::node_id_to_type(self.tcx(), id); - self.declared_purity = ty::determine_inherited_purity( - copy self.declared_purity, - ty::ty_fn_purity(fty), - ty::ty_fn_proto(fty)); - - // In principle, we could consider fk_anon(*) or - // fk_fn_block(*) to be in a ctor, I suppose, but the - // purpose of the in_ctor flag is to allow modifications - // of otherwise immutable fields and typestate wouldn't be - // able to "see" into those functions anyway, so it - // wouldn't be very helpful. - match fk { - visit::fk_ctor(*) => { - self.in_ctor = true; - self.fn_args = @decl.inputs.map(|i| i.id ); - } - visit::fk_anon(*) | - visit::fk_fn_block(*) if is_stack_closure => { - self.in_ctor = false; + do save_and_restore(&mut(self.declared_purity)) { + do save_and_restore(&mut(self.fn_args)) { + let is_stack_closure = self.is_stack_closure(id); + let fty = ty::node_id_to_type(self.tcx(), id); + self.declared_purity = ty::determine_inherited_purity( + copy self.declared_purity, + ty::ty_fn_purity(fty), + ty::ty_fn_proto(fty)); + + match fk { + visit::fk_anon(*) | + visit::fk_fn_block(*) if is_stack_closure => { // inherits the fn_args from enclosing ctxt - } - visit::fk_anon(*) | visit::fk_fn_block(*) | - visit::fk_method(*) | visit::fk_item_fn(*) | - visit::fk_dtor(*) => { - self.in_ctor = false; + } + visit::fk_anon(*) | visit::fk_fn_block(*) | + visit::fk_method(*) | visit::fk_item_fn(*) | + visit::fk_dtor(*) => { self.fn_args = @decl.inputs.map(|i| i.id ); - } } - - visit::visit_fn(fk, decl, body, sp, id, self, visitor); } + + visit::visit_fn(fk, decl, body, sp, id, self, visitor); } } debug!("purity on exit=%?", copy self.declared_purity); diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 5dfde8c9af6..e0eb5519d4d 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -71,11 +71,11 @@ fn req_loans_in_fn(fk: visit::fn_kind, self.root_ub = body.node.id; match fk { - visit::fk_anon(*) | visit::fk_fn_block(*) => {} - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => { - self.item_ub = body.node.id; - } + visit::fk_anon(*) | visit::fk_fn_block(*) => {} + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + self.item_ub = body.node.id; + } } visit::visit_fn(fk, decl, body, sp, id, self, v); @@ -119,12 +119,7 @@ fn req_loans_in_expr(ex: @ast::expr, let arg_cmt = self.bccx.cat_expr(*arg); self.guarantee_valid(arg_cmt, m_imm, scope_r); } - ast::by_val => { - // FIXME (#2493): safety checks would be required here, - // but the correct set is really hard to get right, - // and modes are going away anyhow. - } - ast::by_move | ast::by_copy => {} + ast::by_val | ast::by_move | ast::by_copy => {} } } visit::visit_expr(ex, self, vt); @@ -218,9 +213,10 @@ fn req_loans_in_expr(ex: @ast::expr, } impl gather_loan_ctxt { - fn tcx() -> ty::ctxt { self.bccx.tcx } + fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - fn guarantee_adjustments(expr: @ast::expr, + fn guarantee_adjustments(&self, + expr: @ast::expr, adjustment: &ty::AutoAdjustment) { debug!("guarantee_adjustments(expr=%s, adjustment=%?)", expr_repr(self.tcx(), expr), adjustment); @@ -261,9 +257,10 @@ impl gather_loan_ctxt { // out loans, which will be added to the `req_loan_map`. This can // also entail "rooting" GC'd pointers, which means ensuring // dynamically that they are not freed. - fn guarantee_valid(cmt: cmt, + fn guarantee_valid(&self, + cmt: cmt, req_mutbl: ast::mutability, - scope_r: ty::region) { + scope_r: ty::Region) { self.bccx.guaranteed_paths += 1; @@ -285,35 +282,12 @@ impl gather_loan_ctxt { // it within that scope, the loan will be detected and an // error will be reported. Some(_) => { - match self.bccx.loan(cmt, scope_r, req_mutbl) { - Err(e) => { self.bccx.report(e); } - Ok(loans) if loans.len() == 0 => {} - Ok(loans) => { - match scope_r { - ty::re_scope(scope_id) => { - self.add_loans(scope_id, loans); - - if req_mutbl == m_imm && cmt.mutbl != m_imm { - self.bccx.loaned_paths_imm += 1; - - if self.tcx().sess.borrowck_note_loan() { - self.bccx.span_note( - cmt.span, - fmt!("immutable loan required")); - } - } else { - self.bccx.loaned_paths_same += 1; - } - } - _ => { - self.bccx.tcx.sess.span_bug( - cmt.span, - #fmt["loans required but scope is scope_region is %s", - region_to_str(self.tcx(), scope_r)]); + match self.bccx.loan(cmt, scope_r, req_mutbl) { + Err(e) => { self.bccx.report(e); } + Ok(move loans) => { + self.add_loans(cmt, req_mutbl, scope_r, move loans); } - } } - } } // The path is not loanable: in that case, we must try and @@ -390,7 +364,8 @@ impl gather_loan_ctxt { // has type `@mut{f:int}`, this check might fail because `&x.f` // reqires an immutable pointer, but `f` lives in (aliased) // mutable memory. - fn check_mutbl(req_mutbl: ast::mutability, + fn check_mutbl(&self, + req_mutbl: ast::mutability, cmt: cmt) -> bckres<preserve_condition> { debug!("check_mutbl(req_mutbl=%?, cmt.mutbl=%?)", req_mutbl, cmt.mutbl); @@ -412,21 +387,58 @@ impl gather_loan_ctxt { } } - fn add_loans(scope_id: ast::node_id, loans: @DVec<loan>) { + fn add_loans(&self, + cmt: cmt, + req_mutbl: ast::mutability, + scope_r: ty::Region, + +loans: ~[Loan]) { + if loans.len() == 0 { + return; + } + + let scope_id = match scope_r { + ty::re_scope(scope_id) => scope_id, + _ => { + self.bccx.tcx.sess.span_bug( + cmt.span, + fmt!("loans required but scope is scope_region is %s", + region_to_str(self.tcx(), scope_r))); + } + }; + + self.add_loans_to_scope_id(scope_id, move loans); + + if req_mutbl == m_imm && cmt.mutbl != m_imm { + self.bccx.loaned_paths_imm += 1; + + if self.tcx().sess.borrowck_note_loan() { + self.bccx.span_note( + cmt.span, + fmt!("immutable loan required")); + } + } else { + self.bccx.loaned_paths_same += 1; + } + } + + fn add_loans_to_scope_id(&self, scope_id: ast::node_id, +loans: ~[Loan]) { debug!("adding %u loans to scope_id %?", loans.len(), scope_id); match self.req_maps.req_loan_map.find(scope_id) { - Some(l) => { - l.push(loans); + Some(req_loans) => { + req_loans.push_all(loans); } None => { - self.req_maps.req_loan_map.insert( - scope_id, @dvec::from_vec(~[loans])); + let dvec = @dvec::from_vec(move loans); + self.req_maps.req_loan_map.insert(scope_id, dvec); } } } - fn gather_pat(discr_cmt: cmt, root_pat: @ast::pat, - arm_id: ast::node_id, alt_id: ast::node_id) { + fn gather_pat(&self, + discr_cmt: cmt, + root_pat: @ast::pat, + arm_id: ast::node_id, + alt_id: ast::node_id) { do self.bccx.cat_pattern(discr_cmt, root_pat) |cmt, pat| { match pat.node { ast::pat_ident(bm, _, _) if !self.pat_is_variant(pat) => { @@ -480,7 +492,7 @@ impl gather_loan_ctxt { } } - fn pat_is_variant(pat: @ast::pat) -> bool { + fn pat_is_variant(&self, pat: @ast::pat) -> bool { pat_util::pat_is_variant(self.bccx.tcx.def_map, pat) } } diff --git a/src/rustc/middle/borrowck/loan.rs b/src/rustc/middle/borrowck/loan.rs index 8d9d7a5796a..71414e6e724 100644 --- a/src/rustc/middle/borrowck/loan.rs +++ b/src/rustc/middle/borrowck/loan.rs @@ -7,37 +7,39 @@ use result::{Result, Ok, Err}; impl borrowck_ctxt { fn loan(cmt: cmt, - scope_region: ty::region, - mutbl: ast::mutability) -> bckres<@DVec<loan>> { - let lc = loan_ctxt_(@{bccx: self, - scope_region: scope_region, - loans: @DVec()}); + scope_region: ty::Region, + mutbl: ast::mutability) -> bckres<~[Loan]> { + let lc = LoanContext { + bccx: self, + scope_region: scope_region, + loans: ~[] + }; match lc.loan(cmt, mutbl) { - Ok(()) => {Ok(lc.loans)} - Err(e) => {Err(e)} + Err(e) => Err(e), + Ok(()) => { + let LoanContext {loans, _} = move lc; + Ok(loans) + } } } } -type loan_ctxt_ = { +struct LoanContext { bccx: borrowck_ctxt, // the region scope for which we must preserve the memory - scope_region: ty::region, + scope_region: ty::Region, // accumulated list of loans that will be required - loans: @DVec<loan> -}; - -enum loan_ctxt { - loan_ctxt_(@loan_ctxt_) + mut loans: ~[Loan] } -impl loan_ctxt { - fn tcx() -> ty::ctxt { self.bccx.tcx } +impl LoanContext { + fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - fn issue_loan(cmt: cmt, - scope_ub: ty::region, + fn issue_loan(&self, + cmt: cmt, + scope_ub: ty::Region, req_mutbl: ast::mutability) -> bckres<()> { if self.bccx.is_subregion_of(self.scope_region, scope_ub) { match req_mutbl { @@ -57,12 +59,13 @@ impl loan_ctxt { } } - (*self.loans).push({ + self.loans.push(Loan { // Note: cmt.lp must be Some(_) because otherwise this // loan process does not apply at all. lp: cmt.lp.get(), cmt: cmt, - mutbl: req_mutbl}); + mutbl: req_mutbl + }); return Ok(()); } else { // The loan being requested lives longer than the data @@ -73,7 +76,7 @@ impl loan_ctxt { } } - fn loan(cmt: cmt, req_mutbl: ast::mutability) -> bckres<()> { + fn loan(&self, cmt: cmt, req_mutbl: ast::mutability) -> bckres<()> { debug!("loan(%s, %s)", self.bccx.cmt_to_repr(cmt), self.bccx.mut_to_str(req_mutbl)); @@ -103,23 +106,26 @@ impl loan_ctxt { cat_discr(base, _) => { self.loan(base, req_mutbl) } - cat_comp(cmt_base, comp_field(*)) | - cat_comp(cmt_base, comp_index(*)) | - cat_comp(cmt_base, comp_tuple) => { + cat_comp(cmt_base, comp_field(_, m)) | + cat_comp(cmt_base, comp_index(_, m)) => { // For most components, the type of the embedded data is // stable. Therefore, the base structure need only be // const---unless the component must be immutable. In // that case, it must also be embedded in an immutable // location, or else the whole structure could be // overwritten and the component along with it. - self.loan_stable_comp(cmt, cmt_base, req_mutbl) + self.loan_stable_comp(cmt, cmt_base, req_mutbl, m) + } + cat_comp(cmt_base, comp_tuple) => { + // As above. + self.loan_stable_comp(cmt, cmt_base, req_mutbl, m_imm) } cat_comp(cmt_base, comp_variant(enum_did)) => { // For enums, the memory is unstable if there are multiple // variants, because if the enum value is overwritten then // the memory changes type. if ty::enum_is_univariant(self.bccx.tcx, enum_did) { - self.loan_stable_comp(cmt, cmt_base, req_mutbl) + self.loan_stable_comp(cmt, cmt_base, req_mutbl, m_imm) } else { self.loan_unstable_deref(cmt, cmt_base, req_mutbl) } @@ -144,12 +150,62 @@ impl loan_ctxt { // A "stable component" is one where assigning the base of the // component cannot cause the component itself to change types. // Example: record fields. - fn loan_stable_comp(cmt: cmt, + fn loan_stable_comp(&self, + cmt: cmt, cmt_base: cmt, - req_mutbl: ast::mutability) -> bckres<()> { - let base_mutbl = match req_mutbl { - m_imm => m_imm, - m_const | m_mutbl => m_const + req_mutbl: ast::mutability, + comp_mutbl: ast::mutability) -> bckres<()> { + // Determine the mutability that the base component must have, + // given the required mutability of the pointer (`req_mutbl`) + // and the declared mutability of the component (`comp_mutbl`). + // This is surprisingly subtle. + // + // Note that the *declared* mutability of the component is not + // necessarily the same as cmt.mutbl, since a component + // declared as immutable but embedded in a mutable context + // becomes mutable. It's best to think of comp_mutbl as being + // either MUTABLE or DEFAULT, not MUTABLE or IMMUTABLE. We + // should really patch up the AST to reflect this distinction. + // + // Let's consider the cases below: + // + // 1. mut required, mut declared: In this case, the base + // component must merely be const. The reason is that it + // does not matter if the base component is borrowed as + // mutable or immutable, as the mutability of the base + // component is overridden in the field declaration itself + // (see `compile-fail/borrowck-mut-field-imm-base.rs`) + // + // 2. mut required, imm declared: This would only be legal if + // the component is embeded in a mutable context. However, + // we detect mismatches between the mutability of the value + // as a whole and the required mutability in `issue_loan()` + // above. In any case, presuming that the component IS + // embedded in a mutable context, both the component and + // the base must be loaned as MUTABLE. This is to ensure + // that there is no loan of the base as IMMUTABLE, which + // would imply that the component must be IMMUTABLE too + // (see `compile-fail/borrowck-imm-field-imm-base.rs`). + // + // 3. mut required, const declared: this shouldn't really be + // possible, since I don't think you can declare a const + // field, but I guess if we DID permit such a declaration + // it would be equivalent to the case above? + // + // 4. imm required, * declared: In this case, the base must be + // immutable. This is true regardless of what was declared + // for this subcomponent, this if the base is mutable, the + // subcomponent must be mutable. + // (see `compile-fail/borrowck-imm-field-mut-base.rs`). + // + // 5. const required, * declared: In this case, the base need + // only be const, since we don't ultimately care whether + // the subcomponent is mutable or not. + let base_mutbl = match (req_mutbl, comp_mutbl) { + (m_mutbl, m_mutbl) => m_const, // (1) + (m_mutbl, _) => m_mutbl, // (2, 3) + (m_imm, _) => m_imm, // (4) + (m_const, _) => m_const // (5) }; do self.loan(cmt_base, base_mutbl).chain |_ok| { @@ -162,7 +218,8 @@ impl loan_ctxt { // An "unstable deref" means a deref of a ptr/comp where, if the // base of the deref is assigned to, pointers into the result of the // deref would be invalidated. Examples: interior of variants, uniques. - fn loan_unstable_deref(cmt: cmt, + fn loan_unstable_deref(&self, + cmt: cmt, cmt_base: cmt, req_mutbl: ast::mutability) -> bckres<()> { // Variant components: the base must be immutable, because diff --git a/src/rustc/middle/borrowck/preserve.rs b/src/rustc/middle/borrowck/preserve.rs index 6bfb0d091a4..556ea7867cf 100644 --- a/src/rustc/middle/borrowck/preserve.rs +++ b/src/rustc/middle/borrowck/preserve.rs @@ -23,7 +23,7 @@ impl preserve_condition { impl borrowck_ctxt { fn preserve(cmt: cmt, - scope_region: ty::region, + scope_region: ty::Region, item_ub: ast::node_id, root_ub: ast::node_id) -> bckres<preserve_condition> { @@ -41,7 +41,7 @@ enum preserve_ctxt = { bccx: borrowck_ctxt, // the region scope for which we must preserve the memory - scope_region: ty::region, + scope_region: ty::Region, // the scope for the body of the enclosing fn/method item item_ub: ast::node_id, @@ -277,7 +277,7 @@ priv impl &preserve_ctxt { /// Checks that the scope for which the value must be preserved /// is a subscope of `scope_ub`; if so, success. fn compare_scope(cmt: cmt, - scope_ub: ty::region) -> bckres<preserve_condition> { + scope_ub: ty::Region) -> bckres<preserve_condition> { if self.bccx.is_subregion_of(self.scope_region, scope_ub) { Ok(pc_ok) } else { @@ -314,17 +314,17 @@ priv impl &preserve_ctxt { // we can only root values if the desired region is some concrete // scope within the fn body ty::re_scope(scope_id) => { - #debug["Considering root map entry for %s: \ + debug!("Considering root map entry for %s: \ node %d:%u -> scope_id %?, root_ub %?", self.bccx.cmt_to_repr(cmt), base.id, - derefs, scope_id, self.root_ub]; + derefs, scope_id, self.root_ub); if self.bccx.is_subregion_of(self.scope_region, root_region) { - #debug["Elected to root"]; + debug!("Elected to root"); let rk = {id: base.id, derefs: derefs}; self.bccx.root_map.insert(rk, scope_id); return Ok(pc_ok); } else { - #debug["Unable to root"]; + debug!("Unable to root"); return Err({cmt:cmt, code:err_out_of_root_scope(root_region, self.scope_region)}); diff --git a/src/rustc/middle/capture.rs b/src/rustc/middle/capture.rs index 618d43e121a..563ea8f84be 100644 --- a/src/rustc/middle/capture.rs +++ b/src/rustc/middle/capture.rs @@ -1,5 +1,4 @@ use syntax::{ast, ast_util}; -use driver::session::session; use syntax::codemap::span; use std::map; use std::map::HashMap; diff --git a/src/rustc/middle/check_alt.rs b/src/rustc/middle/check_alt.rs index f71b82a2be7..fc040ecc4cd 100644 --- a/src/rustc/middle/check_alt.rs +++ b/src/rustc/middle/check_alt.rs @@ -7,7 +7,6 @@ use syntax::print::pprust::pat_to_str; use util::ppaux::ty_to_str; use pat_util::*; use syntax::visit; -use driver::session::session; use middle::ty; use middle::ty::*; use std::map::HashMap; @@ -33,7 +32,7 @@ fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) { if arms.is_empty() { if !type_is_empty(tcx, pat_ty) { // We know the type is inhabited, so this must be wrong - tcx.sess.span_err(ex.span, #fmt("non-exhaustive patterns: \ + tcx.sess.span_err(ex.span, fmt!("non-exhaustive patterns: \ type %s is non-empty", ty_to_str(tcx, pat_ty))); } // If the type *is* empty, it's vacuously exhaustive diff --git a/src/rustc/middle/check_const.rs b/src/rustc/middle/check_const.rs index bd3abe20134..bdc042fb764 100644 --- a/src/rustc/middle/check_const.rs +++ b/src/rustc/middle/check_const.rs @@ -1,10 +1,10 @@ use syntax::ast::*; use syntax::{visit, ast_util, ast_map}; -use driver::session::session; +use driver::session::Session; use std::map::HashMap; use dvec::DVec; -fn check_crate(sess: session, crate: @crate, ast_map: ast_map::map, +fn check_crate(sess: Session, crate: @crate, ast_map: ast_map::map, def_map: resolve::DefMap, method_map: typeck::method_map, tcx: ty::ctxt) { visit::visit_crate(*crate, false, visit::mk_vt(@{ @@ -17,7 +17,7 @@ fn check_crate(sess: session, crate: @crate, ast_map: ast_map::map, sess.abort_if_errors(); } -fn check_item(sess: session, ast_map: ast_map::map, +fn check_item(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, it: @item, &&_is_const: bool, v: visit::vt<bool>) { match it.node { @@ -55,7 +55,7 @@ fn check_pat(p: @pat, &&_is_const: bool, v: visit::vt<bool>) { } } -fn check_expr(sess: session, def_map: resolve::DefMap, +fn check_expr(sess: Session, def_map: resolve::DefMap, method_map: typeck::method_map, tcx: ty::ctxt, e: @expr, &&is_const: bool, v: visit::vt<bool>) { if is_const { @@ -142,12 +142,12 @@ fn check_expr(sess: session, def_map: resolve::DefMap, // Make sure a const item doesn't recursively refer to itself // FIXME: Should use the dependency graph when it's available (#1356) -fn check_item_recursion(sess: session, ast_map: ast_map::map, +fn check_item_recursion(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, it: @item) { type env = { root_it: @item, - sess: session, + sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, idstack: @DVec<node_id>, diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index 3cd26f3039b..3fa7f34fb33 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -1,6 +1,5 @@ use syntax::ast::*; use syntax::visit; -use driver::session::session; type ctx = {in_loop: bool, can_ret: bool}; diff --git a/src/rustc/middle/const_eval.rs b/src/rustc/middle/const_eval.rs index 5def18cacc3..d0296ebd2e5 100644 --- a/src/rustc/middle/const_eval.rs +++ b/src/rustc/middle/const_eval.rs @@ -1,4 +1,4 @@ -use syntax::{ast,ast_util,visit}; +use syntax::{ast,ast_map,ast_util,visit}; use ast::*; // @@ -19,7 +19,7 @@ use ast::*; // target uses". This _includes_ integer-constants, plus the following // constructors: // -// fixed-size vectors and strings: []/_ and ""/_ +// fixed-size vectors and strings: [] and ""/_ // vector and string slices: &[] and &"" // tuples: (,) // records: {...} @@ -132,31 +132,10 @@ fn classify(e: @expr, classify(base, def_map, tcx) } - // FIXME: #1272, we can probably do something CCI-ish + // FIXME: (#3728) we can probably do something CCI-ish // surrounding nonlocal constants. But we don't yet. ast::expr_path(_) => { - match def_map.find(e.id) { - Some(ast::def_const(def_id)) => { - if ast_util::is_local(def_id) { - let ty = ty::expr_ty(tcx, e); - if ty::type_is_integral(ty) { - integral_const - } else { - general_const - } - } else { - non_const - } - } - Some(_) => { - non_const - } - None => { - tcx.sess.span_bug(e.span, - ~"unknown path when \ - classifying constants"); - } - } + lookup_constness(tcx, e) } _ => non_const @@ -167,6 +146,40 @@ fn classify(e: @expr, } } +fn lookup_const(tcx: ty::ctxt, e: @expr) -> Option<@expr> { + match tcx.def_map.find(e.id) { + Some(ast::def_const(def_id)) => { + if ast_util::is_local(def_id) { + match tcx.items.find(def_id.node) { + None => None, + Some(ast_map::node_item(it, _)) => match it.node { + item_const(_, const_expr) => Some(const_expr), + _ => None + }, + Some(_) => None + } + } + else { None } + } + Some(_) => None, + None => None + } +} + +fn lookup_constness(tcx: ty::ctxt, e: @expr) -> constness { + match lookup_const(tcx, e) { + Some(rhs) => { + let ty = ty::expr_ty(tcx, rhs); + if ty::type_is_integral(ty) { + integral_const + } else { + general_const + } + } + None => non_const + } +} + fn process_crate(crate: @ast::crate, def_map: resolve::DefMap, tcx: ty::ctxt) { @@ -204,58 +217,67 @@ impl const_val : cmp::Eq { pure fn ne(other: &const_val) -> bool { !self.eq(other) } } -// FIXME: issue #1417 fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { + match eval_const_expr_partial(tcx, e) { + Ok(r) => r, + Err(s) => fail s + } +} + +fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) + -> Result<const_val, ~str> { use middle::ty; - fn fromb(b: bool) -> const_val { const_int(b as i64) } + fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) } match e.node { expr_unary(neg, inner) => { - match eval_const_expr(tcx, inner) { - const_float(f) => const_float(-f), - const_int(i) => const_int(-i), - const_uint(i) => const_uint(-i), - const_str(_) => fail ~"Negate on string", - const_bool(_) => fail ~"Negate on boolean" + match eval_const_expr_partial(tcx, inner) { + Ok(const_float(f)) => Ok(const_float(-f)), + Ok(const_int(i)) => Ok(const_int(-i)), + Ok(const_uint(i)) => Ok(const_uint(-i)), + Ok(const_str(_)) => Err(~"Negate on string"), + Ok(const_bool(_)) => Err(~"Negate on boolean"), + err => err } } expr_unary(not, inner) => { - match eval_const_expr(tcx, inner) { - const_int(i) => const_int(!i), - const_uint(i) => const_uint(!i), - const_bool(b) => const_bool(!b), - _ => fail ~"Not on float or string" + match eval_const_expr_partial(tcx, inner) { + Ok(const_int(i)) => Ok(const_int(!i)), + Ok(const_uint(i)) => Ok(const_uint(!i)), + Ok(const_bool(b)) => Ok(const_bool(!b)), + _ => Err(~"Not on float or string") } } expr_binary(op, a, b) => { - match (eval_const_expr(tcx, a), eval_const_expr(tcx, b)) { - (const_float(a), const_float(b)) => { + match (eval_const_expr_partial(tcx, a), + eval_const_expr_partial(tcx, b)) { + (Ok(const_float(a)), Ok(const_float(b))) => { match op { - add => const_float(a + b), - subtract => const_float(a - b), - mul => const_float(a * b), - div => const_float(a / b), - rem => const_float(a % b), + add => Ok(const_float(a + b)), + subtract => Ok(const_float(a - b)), + mul => Ok(const_float(a * b)), + div => Ok(const_float(a / b)), + rem => Ok(const_float(a % b)), eq => fromb(a == b), lt => fromb(a < b), le => fromb(a <= b), ne => fromb(a != b), ge => fromb(a >= b), gt => fromb(a > b), - _ => fail ~"Can't do this op on floats" + _ => Err(~"Can't do this op on floats") } } - (const_int(a), const_int(b)) => { + (Ok(const_int(a)), Ok(const_int(b))) => { match op { - add => const_int(a + b), - subtract => const_int(a - b), - mul => const_int(a * b), - div => const_int(a / b), - rem => const_int(a % b), - and | bitand => const_int(a & b), - or | bitor => const_int(a | b), - bitxor => const_int(a ^ b), - shl => const_int(a << b), - shr => const_int(a >> b), + add => Ok(const_int(a + b)), + subtract => Ok(const_int(a - b)), + mul => Ok(const_int(a * b)), + div => Ok(const_int(a / b)), + rem => Ok(const_int(a % b)), + and | bitand => Ok(const_int(a & b)), + or | bitor => Ok(const_int(a | b)), + bitxor => Ok(const_int(a ^ b)), + shl => Ok(const_int(a << b)), + shr => Ok(const_int(a >> b)), eq => fromb(a == b), lt => fromb(a < b), le => fromb(a <= b), @@ -264,18 +286,18 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { gt => fromb(a > b) } } - (const_uint(a), const_uint(b)) => { + (Ok(const_uint(a)), Ok(const_uint(b))) => { match op { - add => const_uint(a + b), - subtract => const_uint(a - b), - mul => const_uint(a * b), - div => const_uint(a / b), - rem => const_uint(a % b), - and | bitand => const_uint(a & b), - or | bitor => const_uint(a | b), - bitxor => const_uint(a ^ b), - shl => const_uint(a << b), - shr => const_uint(a >> b), + add => Ok(const_uint(a + b)), + subtract => Ok(const_uint(a - b)), + mul => Ok(const_uint(a * b)), + div => Ok(const_uint(a / b)), + rem => Ok(const_uint(a % b)), + and | bitand => Ok(const_uint(a & b)), + or | bitor => Ok(const_uint(a | b)), + bitxor => Ok(const_uint(a ^ b)), + shl => Ok(const_uint(a << b)), + shr => Ok(const_uint(a >> b)), eq => fromb(a == b), lt => fromb(a < b), le => fromb(a <= b), @@ -285,22 +307,22 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { } } // shifts can have any integral type as their rhs - (const_int(a), const_uint(b)) => { + (Ok(const_int(a)), Ok(const_uint(b))) => { match op { - shl => const_int(a << b), - shr => const_int(a >> b), - _ => fail ~"Can't do this op on an int and uint" + shl => Ok(const_int(a << b)), + shr => Ok(const_int(a >> b)), + _ => Err(~"Can't do this op on an int and uint") } } - (const_uint(a), const_int(b)) => { + (Ok(const_uint(a)), Ok(const_int(b))) => { match op { - shl => const_uint(a << b), - shr => const_uint(a >> b), - _ => fail ~"Can't do this op on a uint and int" + shl => Ok(const_uint(a << b)), + shr => Ok(const_uint(a >> b)), + _ => Err(~"Can't do this op on a uint and int") } } - (const_bool(a), const_bool(b)) => { - const_bool(match op { + (Ok(const_bool(a)), Ok(const_bool(b))) => { + Ok(const_bool(match op { and => a && b, or => a || b, bitxor => a ^ b, @@ -308,47 +330,53 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { bitor => a | b, eq => a == b, ne => a != b, - _ => fail ~"Can't do this op on bools" - }) + _ => return Err(~"Can't do this op on bools") + })) } - _ => fail ~"Bad operands for binary" + _ => Err(~"Bad operands for binary") } } expr_cast(base, _) => { let ety = ty::expr_ty(tcx, e); - let base = eval_const_expr(tcx, base); + let base = eval_const_expr_partial(tcx, base); match ty::get(ety).sty { ty::ty_float(_) => { match base { - const_uint(u) => const_float(u as f64), - const_int(i) => const_float(i as f64), - const_float(_) => base, - _ => fail ~"Can't cast float to str" + Ok(const_uint(u)) => Ok(const_float(u as f64)), + Ok(const_int(i)) => Ok(const_float(i as f64)), + Ok(const_float(_)) => base, + _ => Err(~"Can't cast float to str") } } ty::ty_uint(_) => { match base { - const_uint(_) => base, - const_int(i) => const_uint(i as u64), - const_float(f) => const_uint(f as u64), - _ => fail ~"Can't cast str to uint" + Ok(const_uint(_)) => base, + Ok(const_int(i)) => Ok(const_uint(i as u64)), + Ok(const_float(f)) => Ok(const_uint(f as u64)), + _ => Err(~"Can't cast str to uint") } } ty::ty_int(_) | ty::ty_bool => { match base { - const_uint(u) => const_int(u as i64), - const_int(_) => base, - const_float(f) => const_int(f as i64), - _ => fail ~"Can't cast str to int" + Ok(const_uint(u)) => Ok(const_int(u as i64)), + Ok(const_int(_)) => base, + Ok(const_float(f)) => Ok(const_int(f as i64)), + _ => Err(~"Can't cast str to int") } } - _ => fail ~"Can't cast this type" + _ => Err(~"Can't cast this type") } } - expr_lit(lit) => lit_to_const(lit), + expr_path(_) => { + match lookup_const(tcx, e) { + Some(actual_e) => eval_const_expr_partial(tcx, actual_e), + None => Err(~"Non-constant path in constant expr") + } + } + expr_lit(lit) => Ok(lit_to_const(lit)), // If we have a vstore, just keep going; it has to be a string - expr_vstore(e, _) => eval_const_expr(tcx, e), - _ => fail ~"Unsupported constant expr" + expr_vstore(e, _) => eval_const_expr_partial(tcx, e), + _ => Err(~"Unsupported constant expr") } } diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 7e925d7d8d8..1b42c9bb4b6 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -5,19 +5,19 @@ use syntax::print::pprust::path_to_str; use std::map::*; use option::*; use syntax::{ast, ast_util, visit}; -use syntax::ast::{serialize_span, deserialize_span}; use syntax::codemap::span; export annotate_freevars; export freevar_map; export freevar_info; -export freevar_entry, serialize_freevar_entry, deserialize_freevar_entry; +export freevar_entry; export get_freevars; export has_freevars; // A vector of defs representing the free variables referred to in a function. // (The def_upvar will already have been stripped). #[auto_serialize] +#[auto_deserialize] type freevar_entry = { def: ast::def, //< The variable being accessed free. span: span //< First span where it is accessed (there can be multiple) diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index e2b85441a8f..e4dc9e8330e 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -1,8 +1,7 @@ use syntax::{visit, ast_util}; use syntax::ast::*; use syntax::codemap::span; -use ty::{kind, kind_copyable, kind_noncopyable, kind_const}; -use driver::session::session; +use middle::ty::{Kind, kind_copyable, kind_noncopyable, kind_const}; use std::map::HashMap; use util::ppaux::{ty_to_str, tys_to_str}; use syntax::print::pprust::expr_to_str; @@ -38,7 +37,9 @@ use lint::{non_implicitly_copyable_typarams,implicit_copies}; // primitives in the stdlib are explicitly annotated to only take sendable // types. -fn kind_to_str(k: kind) -> ~str { +const try_adding: &str = "Try adding a move"; + +fn kind_to_str(k: Kind) -> ~str { let mut kinds = ~[]; if ty::kind_lteq(kind_const(), k) { @@ -89,8 +90,11 @@ fn check_crate(tcx: ty::ctxt, tcx.sess.abort_if_errors(); } +// bool flag is only used for checking closures, +// where it refers to whether a var is 'move' in the +// capture clause type check_fn = fn@(ctx, node_id, Option<@freevar_entry>, - bool, ty::t, sp: span); + bool, ty::t, sp: span); // Yields the appropriate function to check the kind of closed over // variables. `id` is the node_id for some expression that creates the @@ -111,7 +115,6 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { "to copy values into a ~fn closure, use a \ capture clause: `fn~(copy x)` or `|copy x|`"))); } - // check that only immutable variables are implicitly copied in for fv.each |fv| { check_imm_free_var(cx, fv.def, fv.span); @@ -132,7 +135,6 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { "to copy values into a @fn closure, use a \ capture clause: `fn~(copy x)` or `|copy x|`"))); } - // check that only immutable variables are implicitly copied in for fv.each |fv| { check_imm_free_var(cx, fv.def, fv.span); @@ -151,7 +153,7 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { } fn check_for_bare(cx: ctx, _id: node_id, _fv: Option<@freevar_entry>, - _is_move: bool,_var_t: ty::t, sp: span) { + _is_move: bool, _var_t: ty::t, sp: span) { cx.tcx.sess.span_err(sp, ~"attempted dynamic environment capture"); } @@ -181,14 +183,15 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, // variables. This list is used below to avoid checking and reporting // on a given variable twice. let cap_clause = match fk { - visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => @~[] + visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => @~[] }; let captured_vars = do (*cap_clause).map |cap_item| { let cap_def = cx.tcx.def_map.get(cap_item.id); let cap_def_id = ast_util::def_id_of_def(cap_def).node; let ty = ty::node_id_to_type(cx.tcx, cap_def_id); + // Here's where is_move isn't always false... chk(cx, fn_id, None, cap_item.is_move, ty, cap_item.span); cap_def_id }; @@ -201,17 +204,10 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, // skip over free variables that appear in the cap clause if captured_vars.contains(&id) { loop; } - // if this is the last use of the variable, then it will be - // a move and not a copy - let is_move = { - match cx.last_use_map.find(fn_id) { - Some(vars) => (*vars).contains(&id), - None => false - } - }; - let ty = ty::node_id_to_type(cx.tcx, id); - chk(cx, fn_id, Some(*fv), is_move, ty, fv.span); + // is_move is always false here. See the let captured_vars... + // code above for where it's not always false. + chk(cx, fn_id, Some(*fv), false, ty, fv.span); } } @@ -220,7 +216,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, fn check_block(b: blk, cx: ctx, v: visit::vt<ctx>) { match b.node.expr { - Some(ex) => maybe_copy(cx, ex, None), + Some(ex) => maybe_copy(cx, ex, + Some(("Tail expressions in blocks must be copyable", + try_adding))), _ => () } visit::visit_block(b, cx, v); @@ -281,33 +279,45 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { expr_assign(_, ex) | expr_unary(box(_), ex) | expr_unary(uniq(_), ex) | expr_ret(Some(ex)) => { - maybe_copy(cx, ex, None); + maybe_copy(cx, ex, Some(("Returned values must be copyable", + try_adding))); } expr_cast(source, _) => { - maybe_copy(cx, source, None); + maybe_copy(cx, source, Some(("Casted values must be copyable", + try_adding))); check_cast_for_escaping_regions(cx, source, e); } - expr_copy(expr) => check_copy_ex(cx, expr, false, None), + expr_copy(expr) => check_copy_ex(cx, expr, false, + Some(("Explicit copy requires a copyable argument", ""))), // Vector add copies, but not "implicitly" - expr_assign_op(_, _, ex) => check_copy_ex(cx, ex, false, None), + expr_assign_op(_, _, ex) => check_copy_ex(cx, ex, false, + Some(("Assignment with operation requires \ + a copyable argument", ""))), expr_binary(add, ls, rs) => { - check_copy_ex(cx, ls, false, None); - check_copy_ex(cx, rs, false, None); + let reason = Some(("Binary operators require copyable arguments", + "")); + check_copy_ex(cx, ls, false, reason); + check_copy_ex(cx, rs, false, reason); } - expr_rec(fields, def) => { - for fields.each |field| { maybe_copy(cx, field.node.expr, None); } + expr_rec(fields, def) | expr_struct(_, fields, def) => { + for fields.each |field| { maybe_copy(cx, field.node.expr, + Some(("Record or struct fields require \ + copyable arguments", ""))); } match def { Some(ex) => { // All noncopyable fields must be overridden let t = ty::expr_ty(cx.tcx, ex); let ty_fields = match ty::get(t).sty { ty::ty_rec(f) => f, - _ => cx.tcx.sess.span_bug(ex.span, ~"bad expr type in record") + ty::ty_class(did, substs) => + ty::class_items_as_fields(cx.tcx, did, &substs), + _ => cx.tcx.sess.span_bug(ex.span, + ~"bad base expr type in record") }; 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, + cx.tcx.sess.span_err(e.span, ~"copying a noncopyable value"); } } @@ -316,16 +326,16 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { } } expr_tup(exprs) | expr_vec(exprs, _) => { - for exprs.each |expr| { maybe_copy(cx, *expr, None); } + for exprs.each |expr| { maybe_copy(cx, *expr, + Some(("Tuple or vec elements must be copyable", ""))); } } expr_call(f, args, _) => { - let mut i = 0u; - for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each |arg_t| { + for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).eachi |i, arg_t| { match ty::arg_mode(cx.tcx, *arg_t) { - by_copy => maybe_copy(cx, args[i], None), + by_copy => maybe_copy(cx, args[i], + Some(("Callee takes its argument by copy", ""))), by_ref | by_val | by_move => () } - i += 1u; } } expr_field(lhs, _, _) => { @@ -334,7 +344,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { match cx.method_map.find(e.id) { Some(ref mme) => { match ty::arg_mode(cx.tcx, mme.self_arg) { - by_copy => maybe_copy(cx, lhs, None), + by_copy => maybe_copy(cx, lhs, + Some(("Method call takes its self argument by copy", + ""))), by_ref | by_val | by_move => () } } @@ -344,10 +356,12 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { expr_repeat(element, count_expr, _) => { let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span); if count == 1 { - maybe_copy(cx, element, None); + maybe_copy(cx, element, Some(("Trivial repeat takes its element \ + by copy", ""))); } else { let element_ty = ty::expr_ty(cx.tcx, element); - check_copy(cx, element.id, element_ty, element.span, true, None); + check_copy(cx, element.id, element_ty, element.span, true, + Some(("Repeat takes its elements by copy", ""))); } } _ => { } @@ -360,7 +374,9 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) { stmt_decl(@{node: decl_local(locals), _}, _) => { for locals.each |local| { match local.node.init { - Some({op: init_assign, expr}) => maybe_copy(cx, expr, None), + Some({op: init_assign, expr}) => + maybe_copy(cx, expr, Some(("Initializer statement \ + takes its right-hand side by copy", ""))), _ => {} } } @@ -370,7 +386,7 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) { visit::visit_stmt(stmt, cx, v); } -fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) { +fn check_ty(aty: @Ty, cx: ctx, v: visit::vt<ctx>) { match aty.node { ty_path(_, id) => { do option::iter(&cx.tcx.node_type_substs.find(id)) |ts| { @@ -434,9 +450,6 @@ fn check_copy_ex(cx: ctx, ex: @expr, implicit_copy: bool, why: Option<(&str,&str)>) { if ty::expr_is_lval(cx.tcx, cx.method_map, ex) && - // this is a move - !cx.last_use_map.contains_key(ex.id) && - // a reference to a constant like `none`... no need to warn // about *this* even if the type is Option<~int> !is_nullary_variant(cx, ex) && diff --git a/src/rustc/middle/lang_items.rs b/src/rustc/middle/lang_items.rs index 7cb2c9eb9cf..383fe2db323 100644 --- a/src/rustc/middle/lang_items.rs +++ b/src/rustc/middle/lang_items.rs @@ -9,7 +9,7 @@ // // * Functions called by the compiler itself. -use driver::session::session; +use driver::session::Session; use metadata::csearch::{each_path, get_item_attrs}; use metadata::cstore::{iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; @@ -50,7 +50,7 @@ struct LanguageItems { mut log_type_fn: Option<def_id> } -mod LanguageItems { +mod language_items { #[legacy_exports]; fn make() -> LanguageItems { LanguageItems { @@ -83,7 +83,7 @@ mod LanguageItems { } } -fn LanguageItemCollector(crate: @crate, session: session, +fn LanguageItemCollector(crate: @crate, session: Session, items: &r/LanguageItems) -> LanguageItemCollector/&r { @@ -127,7 +127,7 @@ struct LanguageItemCollector { items: &LanguageItems, crate: @crate, - session: session, + session: Session, item_refs: HashMap<~str,&mut Option<def_id>>, } @@ -239,8 +239,8 @@ impl LanguageItemCollector { } } -fn collect_language_items(crate: @crate, session: session) -> LanguageItems { - let items = LanguageItems::make(); +fn collect_language_items(crate: @crate, session: Session) -> LanguageItems { + let items = language_items::make(); let collector = LanguageItemCollector(crate, session, &items); collector.collect(); copy items diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs index 0f31f2056a1..0768a092522 100644 --- a/src/rustc/middle/lint.rs +++ b/src/rustc/middle/lint.rs @@ -1,5 +1,5 @@ use driver::session; -use driver::session::session; +use driver::session::Session; use middle::ty; use syntax::{ast, ast_util, visit}; use syntax::attr; @@ -244,7 +244,7 @@ fn clone_lint_modes(modes: lint_modes) -> lint_modes { type ctxt_ = {dict: lint_dict, curr: lint_modes, is_default: bool, - sess: session}; + sess: Session}; enum ctxt { ctxt_(ctxt_) @@ -355,7 +355,7 @@ fn build_settings_item(i: @ast::item, &&cx: ctxt, v: visit::vt<ctxt>) { } } -fn build_settings_crate(sess: session::session, crate: @ast::crate) { +fn build_settings_crate(sess: session::Session, crate: @ast::crate) { let cx = ctxt_({dict: get_lint_dict(), curr: std::smallintmap::mk(), diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 12d63cdacbf..da3e7b175d0 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -35,12 +35,6 @@ * Any use of the variable where the variable is dead afterwards is a * last use. * - * # Extension to handle constructors - * - * Each field is assigned an index just as with local variables. A use of - * `self` is considered a use of all fields. A use of `self.f` is just a use - * of `f`. - * * # Implementation details * * The actual implementation contains two (nested) walks over the AST. @@ -96,18 +90,15 @@ * - `no_ret_var`: a synthetic variable that is only 'read' from, the * fallthrough node. This allows us to detect functions where we fail * to return explicitly. - * - * - `self_var`: a variable representing 'self' */ use dvec::DVec; use std::map::HashMap; use syntax::{visit, ast_util}; -use syntax::print::pprust::{expr_to_str}; +use syntax::print::pprust::{expr_to_str, block_to_str}; use visit::vt; -use syntax::codemap::span; +use syntax::codemap::{span, span_to_str}; use syntax::ast::*; -use driver::session::session; use io::WriterUtil; use capture::{cap_move, cap_drop, cap_copy, cap_ref}; @@ -176,6 +167,16 @@ impl LiveNodeKind : cmp::Eq { pure fn ne(other: &LiveNodeKind) -> bool { !self.eq(other) } } +fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str { + let cm = cx.sess.codemap; + match lnk { + FreeVarNode(s) => fmt!("Free var node [%s]", span_to_str(s, cm)), + ExprNode(s) => fmt!("Expr node [%s]", span_to_str(s, cm)), + VarDefNode(s) => fmt!("Var def node [%s]", span_to_str(s, cm)), + ExitNode => ~"Exit node" + } +} + fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, crate: @crate) -> last_use_map { @@ -195,11 +196,11 @@ fn check_crate(tcx: ty::ctxt, } impl LiveNode: to_str::ToStr { - fn to_str() -> ~str { fmt!("ln(%u)", *self) } + pure fn to_str() -> ~str { fmt!("ln(%u)", *self) } } impl Variable: to_str::ToStr { - fn to_str() -> ~str { fmt!("v(%u)", *self) } + pure fn to_str() -> ~str { fmt!("v(%u)", *self) } } // ______________________________________________________________________ @@ -230,9 +231,11 @@ impl LiveNode { fn invalid_node() -> LiveNode { LiveNode(uint::max_value) } -enum RelevantDef { RelevantVar(node_id), RelevantSelf } - -type CaptureInfo = {ln: LiveNode, is_move: bool, rv: RelevantDef}; +struct CaptureInfo { + ln: LiveNode, + is_move: bool, + var_nid: node_id +} enum LocalKind { FromMatch(binding_mode), @@ -250,18 +253,15 @@ struct LocalInfo { enum VarKind { Arg(node_id, ident, rmode), Local(LocalInfo), - Field(ident), Self, ImplicitRet } -fn relevant_def(def: def) -> Option<RelevantDef> { +fn relevant_def(def: def) -> Option<node_id> { match def { - def_self(_) => Some(RelevantSelf), - def_binding(nid, _) | def_arg(nid, _) | - def_local(nid, _) => Some(RelevantVar(nid)), + def_local(nid, _) => Some(nid), _ => None } @@ -276,7 +276,6 @@ struct IrMaps { mut num_vars: uint, live_node_map: HashMap<node_id, LiveNode>, variable_map: HashMap<node_id, Variable>, - field_map: HashMap<ident, Variable>, capture_map: HashMap<node_id, @~[CaptureInfo]>, mut var_kinds: ~[VarKind], mut lnks: ~[LiveNodeKind], @@ -288,12 +287,11 @@ fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, tcx: tcx, method_map: method_map, last_use_map: last_use_map, - num_live_nodes: 0u, - num_vars: 0u, + num_live_nodes: 0, + num_vars: 0, live_node_map: HashMap(), variable_map: HashMap(), capture_map: HashMap(), - field_map: HashMap(), var_kinds: ~[], lnks: ~[] } @@ -303,9 +301,10 @@ impl IrMaps { fn add_live_node(lnk: LiveNodeKind) -> LiveNode { let ln = LiveNode(self.num_live_nodes); self.lnks.push(lnk); - self.num_live_nodes += 1u; + self.num_live_nodes += 1; - debug!("%s is of kind %?", ln.to_str(), lnk); + debug!("%s is of kind %s", ln.to_str(), + live_node_kind_to_str(lnk, self.tcx)); ln } @@ -320,18 +319,15 @@ impl IrMaps { fn add_variable(vk: VarKind) -> Variable { let v = Variable(self.num_vars); self.var_kinds.push(vk); - self.num_vars += 1u; + self.num_vars += 1; match vk { - Local(LocalInfo {id:node_id, _}) | - Arg(node_id, _, _) => { - self.variable_map.insert(node_id, v); - } - Field(name) => { - self.field_map.insert(name, v); - } - Self | ImplicitRet => { - } + Local(LocalInfo {id:node_id, _}) | + Arg(node_id, _, _) => { + self.variable_map.insert(node_id, v); + } + Self | ImplicitRet => { + } } debug!("%s is %?", v.to_str(), vk); @@ -351,11 +347,10 @@ impl IrMaps { fn variable_name(var: Variable) -> ~str { match copy self.var_kinds[*var] { - Local(LocalInfo {ident: nm, _}) | - Arg(_, nm, _) => self.tcx.sess.str_of(nm), - Field(nm) => ~"self." + self.tcx.sess.str_of(nm), - Self => ~"self", - ImplicitRet => ~"<implicit-ret>" + Local(LocalInfo {ident: nm, _}) | + Arg(_, nm, _) => self.tcx.sess.str_of(nm), + Self => ~"self", + ImplicitRet => ~"<implicit-ret>" } } @@ -399,7 +394,7 @@ impl IrMaps { (*v).push(id); } Arg(_, _, by_ref) | - Arg(_, _, by_val) | Self | Field(_) | ImplicitRet | + Arg(_, _, by_val) | Self | ImplicitRet | Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => { debug!("--but it is not owned"); } @@ -428,13 +423,6 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, // and so forth: visit::visit_fn(fk, decl, body, sp, id, fn_maps, v); - match fk { - visit::fk_ctor(_, _, _, _, class_did) => { - add_class_fields(fn_maps, class_did); - } - _ => {} - } - // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or fail // - implicit_ret_var is a pseudo-variable that represents @@ -442,8 +430,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, let specials = { exit_ln: (*fn_maps).add_live_node(ExitNode), fallthrough_ln: (*fn_maps).add_live_node(ExitNode), - no_ret_var: (*fn_maps).add_variable(ImplicitRet), - self_var: (*fn_maps).add_variable(Self) + no_ret_var: (*fn_maps).add_variable(ImplicitRet) }; // compute liveness @@ -460,18 +447,9 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, }); check_vt.visit_block(body, lsets, check_vt); lsets.check_ret(id, sp, fk, entry_ln); - lsets.check_fields(sp, entry_ln); lsets.warn_about_unused_args(sp, decl, entry_ln); } -fn add_class_fields(self: @IrMaps, did: def_id) { - for ty::lookup_class_fields(self.tcx, did).each |field_ty| { - assert field_ty.id.crate == local_crate; - let var = self.add_variable(Field(field_ty.ident)); - self.field_map.insert(field_ty.ident, var); - } -} - fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| { @@ -524,6 +502,10 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) { } expr_fn(_, _, _, cap_clause) | expr_fn_block(_, _, cap_clause) => { + // Interesting control flow (for loops can contain labeled + // breaks or continues) + self.add_live_node_for_node(expr.id, ExprNode(expr.span)); + // Make a live_node for each captured variable, with the span // being the location that the variable is used. This results // in better error messages than just pointing at the closure @@ -540,7 +522,9 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) { cap_move | cap_drop => true, // var must be dead afterwards cap_copy | cap_ref => false // var can still be used }; - call_caps.push({ln: cv_ln, is_move: is_move, rv: rv}); + call_caps.push(CaptureInfo {ln: cv_ln, + is_move: is_move, + var_nid: rv}); } None => {} } @@ -595,22 +579,29 @@ fn invalid_users() -> users { type Specials = { exit_ln: LiveNode, fallthrough_ln: LiveNode, - no_ret_var: Variable, - self_var: Variable + no_ret_var: Variable }; const ACC_READ: uint = 1u; const ACC_WRITE: uint = 2u; const ACC_USE: uint = 4u; +type LiveNodeMap = HashMap<node_id, LiveNode>; + struct Liveness { tcx: ty::ctxt, ir: @IrMaps, s: Specials, successors: ~[mut LiveNode], users: ~[mut users], - mut break_ln: LiveNode, - mut cont_ln: LiveNode, + // The list of node IDs for the nested loop scopes + // we're in. + loop_scope: DVec<node_id>, + // mappings from loop node ID to LiveNode + // ("break" label should map to loop node ID, + // it probably doesn't now) + break_ln: LiveNodeMap, + cont_ln: LiveNodeMap } fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { @@ -626,8 +617,9 @@ fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { vec::to_mut( vec::from_elem(ir.num_live_nodes * ir.num_vars, invalid_users())), - break_ln: invalid_node(), - cont_ln: invalid_node() + loop_scope: DVec(), + break_ln: HashMap(), + cont_ln: HashMap() } } @@ -647,19 +639,12 @@ impl Liveness { } } - fn variable_from_rdef(rv: RelevantDef, span: span) -> Variable { - match rv { - RelevantSelf => self.s.self_var, - RelevantVar(nid) => self.variable(nid, span) - } - } - fn variable_from_path(expr: @expr) -> Option<Variable> { match expr.node { expr_path(_) => { let def = self.tcx.def_map.get(expr.id); relevant_def(def).map( - |rdef| self.variable_from_rdef(*rdef, expr.span) + |rdef| self.variable(*rdef, expr.span) ) } _ => None @@ -675,7 +660,7 @@ impl Liveness { match self.tcx.def_map.find(node_id) { Some(def) => { relevant_def(def).map( - |rdef| self.variable_from_rdef(*rdef, span) + |rdef| self.variable(*rdef, span) ) } None => { @@ -730,6 +715,9 @@ impl Liveness { if reader.is_valid() {Some((*self.ir).lnk(reader))} else {None} } + /* + Is this variable live on entry to any of its successor nodes? + */ fn live_on_exit(ln: LiveNode, var: Variable) -> Option<LiveNodeKind> { @@ -756,8 +744,8 @@ impl Liveness { } fn indices(ln: LiveNode, op: fn(uint)) { - let node_base_idx = self.idx(ln, Variable(0u)); - for uint::range(0u, self.ir.num_vars) |var_idx| { + let node_base_idx = self.idx(ln, Variable(0)); + for uint::range(0, self.ir.num_vars) |var_idx| { op(node_base_idx + var_idx) } } @@ -774,8 +762,8 @@ impl Liveness { fn write_vars(wr: io::Writer, ln: LiveNode, test: fn(uint) -> LiveNode) { - let node_base_idx = self.idx(ln, Variable(0u)); - for uint::range(0u, self.ir.num_vars) |var_idx| { + let node_base_idx = self.idx(ln, Variable(0)); + for uint::range(0, self.ir.num_vars) |var_idx| { let idx = node_base_idx + var_idx; if test(idx).is_valid() { wr.write_str(~" "); @@ -784,6 +772,28 @@ impl Liveness { } } + fn find_loop_scope(opt_label: Option<ident>, id: node_id, sp: span) + -> node_id { + match opt_label { + Some(_) => // Refers to a labeled loop. Use the results of resolve + // to find with one + match self.tcx.def_map.find(id) { + Some(def_label(loop_id)) => loop_id, + _ => self.tcx.sess.span_bug(sp, ~"Label on break/loop \ + doesn't refer to a loop") + }, + None => + // Vanilla 'break' or 'loop', so use the enclosing + // loop scope + if self.loop_scope.len() == 0 { + self.tcx.sess.span_bug(sp, ~"break outside loop"); + } + else { + self.loop_scope.last() + } + } + } + fn ln_str(ln: LiveNode) -> ~str { do io::with_str_writer |wr| { wr.write_str(~"[ln("); @@ -872,18 +882,18 @@ impl Liveness { let idx = self.idx(ln, var); let user = &mut self.users[idx]; - if (acc & ACC_WRITE) != 0u { + if (acc & ACC_WRITE) != 0 { user.reader = invalid_node(); user.writer = ln; } // Important: if we both read/write, must do read second // or else the write will override. - if (acc & ACC_READ) != 0u { + if (acc & ACC_READ) != 0 { user.reader = ln; } - if (acc & ACC_USE) != 0u { + if (acc & ACC_USE) != 0 { self.users[idx].used = true; } @@ -897,16 +907,19 @@ impl Liveness { // if there is a `break` or `again` at the top level, then it's // effectively a return---this only occurs in `for` loops, // where the body is really a closure. + + debug!("compute: using id for block, %s", block_to_str(body, + self.tcx.sess.intr())); + let entry_ln: LiveNode = - self.with_loop_nodes(self.s.exit_ln, self.s.exit_ln, || { - self.propagate_through_fn_block(decl, body) - }); + self.with_loop_nodes(body.node.id, self.s.exit_ln, self.s.exit_ln, + || { self.propagate_through_fn_block(decl, body) }); - // hack to skip the loop unless #debug is enabled: + // hack to skip the loop unless debug! is enabled: debug!("^^ liveness computation results for body %d (entry=%s)", { for uint::range(0u, self.ir.num_live_nodes) |ln_idx| { - #debug["%s", self.ln_str(LiveNode(ln_idx))]; + debug!("%s", self.ln_str(LiveNode(ln_idx))); } body.node.id }, @@ -934,14 +947,6 @@ impl Liveness { } } - // as above, the "self" variable is a non-owned variable - self.acc(self.s.exit_ln, self.s.self_var, ACC_READ); - - // in a ctor, there is an implicit use of self.f for all fields f: - for self.ir.field_map.each_value |var| { - self.acc(self.s.exit_ln, var, ACC_READ|ACC_USE); - } - // the fallthrough exit is only for those cases where we do not // explicitly return: self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln); @@ -1019,40 +1024,41 @@ impl Liveness { } fn propagate_through_expr(expr: @expr, succ: LiveNode) -> LiveNode { + debug!("propagate_through_expr: %s", + expr_to_str(expr, self.tcx.sess.intr())); + match expr.node { // Interesting cases with control flow or which gen/kill expr_path(_) => { - self.access_path(expr, succ, ACC_READ | ACC_USE) + self.access_path(expr, succ, ACC_READ | ACC_USE) } - expr_field(e, nm, _) => { - // If this is a reference to `self.f` inside of a ctor, - // then we treat it as a read of that variable. - // Otherwise, we ignore it and just propagate down to - // process `e`. - match self.as_self_field(e, nm) { - Some((ln, var)) => { - self.init_from_succ(ln, succ); - self.acc(ln, var, ACC_READ | ACC_USE); - ln - } - None => { - self.propagate_through_expr(e, succ) - } - } + expr_field(e, _, _) => { + self.propagate_through_expr(e, succ) } - expr_fn(*) | expr_fn_block(*) => { - // the construction of a closure itself is not important, - // but we have to consider the closed over variables. - let caps = (*self.ir).captures(expr); - do (*caps).foldr(succ) |cap, succ| { - self.init_from_succ(cap.ln, succ); - let var = self.variable_from_rdef(cap.rv, expr.span); - self.acc(cap.ln, var, ACC_READ | ACC_USE); - cap.ln - } + expr_fn(_, _, blk, _) | expr_fn_block(_, blk, _) => { + debug!("%s is an expr_fn or expr_fn_block", + expr_to_str(expr, self.tcx.sess.intr())); + + /* + The next-node for a break is the successor of the entire + loop. The next-node for a continue is the top of this loop. + */ + self.with_loop_nodes(blk.node.id, succ, + self.live_node(expr.id, expr.span), || { + + // the construction of a closure itself is not important, + // but we have to consider the closed over variables. + let caps = (*self.ir).captures(expr); + do (*caps).foldr(succ) |cap, succ| { + self.init_from_succ(cap.ln, succ); + let var = self.variable(cap.var_nid, expr.span); + self.acc(cap.ln, var, ACC_READ | ACC_USE); + cap.ln + } + }) } expr_if(cond, then, els) => { @@ -1081,6 +1087,8 @@ impl Liveness { self.propagate_through_loop(expr, Some(cond), blk, succ) } + // Note that labels have been resolved, so we don't need to look + // at the label ident expr_loop(blk, _) => { self.propagate_through_loop(expr, None, blk, succ) } @@ -1122,29 +1130,31 @@ impl Liveness { } expr_break(opt_label) => { - if !self.break_ln.is_valid() { - self.tcx.sess.span_bug( - expr.span, ~"break with invalid break_ln"); - } + // Find which label this break jumps to + let sc = self.find_loop_scope(opt_label, expr.id, expr.span); - if opt_label.is_some() { - self.tcx.sess.span_unimpl(expr.span, ~"labeled break"); - } + // Now that we know the label we're going to, + // look it up in the break loop nodes table - self.break_ln + match self.break_ln.find(sc) { + Some(b) => b, + None => self.tcx.sess.span_bug(expr.span, + ~"Break to unknown label") + } } expr_again(opt_label) => { - if !self.cont_ln.is_valid() { - self.tcx.sess.span_bug( - expr.span, ~"cont with invalid cont_ln"); - } + // Find which label this expr continues to to + let sc = self.find_loop_scope(opt_label, expr.id, expr.span); - if opt_label.is_some() { - self.tcx.sess.span_unimpl(expr.span, ~"labeled again"); - } + // Now that we know the label we're going to, + // look it up in the continue loop nodes table - self.cont_ln + match self.cont_ln.find(sc) { + Some(b) => b, + None => self.tcx.sess.span_bug(expr.span, + ~"Loop to unknown label") + } } expr_move(l, r) | expr_assign(l, r) => { @@ -1269,8 +1279,8 @@ impl Liveness { // In general, the full flow graph structure for an // assignment/move/etc can be handled in one of two ways, // depending on whether what is being assigned is a "tracked - // value" or not. A tracked value is basically a local variable - // or argument, or a self-field (`self.f`) in a ctor. + // value" or not. A tracked value is basically a local + // variable or argument. // // The two kinds of graphs are: // @@ -1293,12 +1303,11 @@ impl Liveness { // // # Tracked lvalues // - // A tracked lvalue is either a local variable/argument `x` or - // else it is a self-field `self.f` in a constructor. In + // A tracked lvalue is a local variable/argument `x`. In // these cases, the link_node where the write occurs is linked - // to node id of `x` or `self`, respectively. The - // `write_lvalue()` routine generates the contents of this - // node. There are no subcomponents to consider. + // to node id of `x`. The `write_lvalue()` routine generates + // the contents of this node. There are no subcomponents to + // consider. // // # Non-tracked lvalues // @@ -1315,12 +1324,9 @@ impl Liveness { // just ignore such cases and treat them as reads. match expr.node { - expr_path(_) => succ, - expr_field(e, nm, _) => match self.as_self_field(e, nm) { - Some(_) => succ, - None => self.propagate_through_expr(e, succ) - }, - _ => self.propagate_through_expr(expr, succ) + expr_path(_) => succ, + expr_field(e, _, _) => self.propagate_through_expr(e, succ), + _ => self.propagate_through_expr(expr, succ) } } @@ -1330,14 +1336,6 @@ impl Liveness { acc: uint) -> LiveNode { match expr.node { expr_path(_) => self.access_path(expr, succ, acc), - expr_field(e, nm, _) => match self.as_self_field(e, nm) { - Some((ln, var)) => { - self.init_from_succ(ln, succ); - self.acc(ln, var, acc); - ln - } - None => succ - }, // We do not track other lvalues, so just propagate through // to their subcomponents. Also, it may happen that @@ -1350,27 +1348,7 @@ impl Liveness { fn access_path(expr: @expr, succ: LiveNode, acc: uint) -> LiveNode { let def = self.tcx.def_map.get(expr.id); match relevant_def(def) { - Some(RelevantSelf) => { - // Accessing `self` is like accessing every field of - // the current object. This allows something like - // `self = ...;` (it will be considered a write to - // every field, sensibly enough), though the borrowck - // pass will reject it later on. - // - // Also, note that, within a ctor at least, an - // expression like `self.f` is "shortcircuiting" - // before it reaches this point by the code for - // expr_field. - let ln = self.live_node(expr.id, expr.span); - if acc != 0u { - self.init_from_succ(ln, succ); - for self.ir.field_map.each_value |var| { - self.acc(ln, var, acc); - } - } - ln - } - Some(RelevantVar(nid)) => { + Some(nid) => { let ln = self.live_node(expr.id, expr.span); if acc != 0u { self.init_from_succ(ln, succ); @@ -1383,29 +1361,6 @@ impl Liveness { } } - fn as_self_field(expr: @expr, - fld: ident) -> Option<(LiveNode,Variable)> { - // If we checking a constructor, then we treat self.f as a - // variable. we use the live_node id that will be assigned to - // the reference to self but the variable id for `f`. - match expr.node { - expr_path(_) => { - let def = self.tcx.def_map.get(expr.id); - match def { - def_self(_) => { - // Note: the field_map is empty unless we are in a ctor - return self.ir.field_map.find(fld).map(|var| { - let ln = self.live_node(expr.id, expr.span); - (ln, *var) - }); - } - _ => return None - } - } - _ => return None - } - } - fn propagate_through_loop(expr: @expr, cond: Option<@expr>, body: blk, @@ -1429,6 +1384,7 @@ impl Liveness { */ + // first iteration: let mut first_merge = true; let ln = self.live_node(expr.id, expr.span); @@ -1440,8 +1396,11 @@ impl Liveness { self.merge_from_succ(ln, succ, first_merge); first_merge = false; } + debug!("propagate_through_loop: using id for loop body %d %s", + expr.id, block_to_str(body, self.tcx.sess.intr())); + let cond_ln = self.propagate_through_opt_expr(cond, ln); - let body_ln = self.with_loop_nodes(succ, ln, || { + let body_ln = self.with_loop_nodes(expr.id, succ, ln, || { self.propagate_through_block(body, cond_ln) }); @@ -1449,7 +1408,8 @@ impl Liveness { while self.merge_from_succ(ln, body_ln, first_merge) { first_merge = false; assert cond_ln == self.propagate_through_opt_expr(cond, ln); - assert body_ln == self.with_loop_nodes(succ, ln, || { + assert body_ln == self.with_loop_nodes(expr.id, succ, ln, + || { self.propagate_through_block(body, cond_ln) }); } @@ -1457,15 +1417,16 @@ impl Liveness { cond_ln } - fn with_loop_nodes<R>(break_ln: LiveNode, + fn with_loop_nodes<R>(loop_node_id: node_id, + break_ln: LiveNode, cont_ln: LiveNode, f: fn() -> R) -> R { - let bl = self.break_ln, cl = self.cont_ln; - self.break_ln = break_ln; - self.cont_ln = cont_ln; - let r <- f(); - self.break_ln = bl; - self.cont_ln = cl; + debug!("with_loop_nodes: %d %u", loop_node_id, *break_ln); + self.loop_scope.push(loop_node_id); + self.break_ln.insert(loop_node_id, break_ln); + self.cont_ln.insert(loop_node_id, cont_ln); + let r = f(); + self.loop_scope.pop(); move r } } @@ -1533,7 +1494,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { expr_fn(*) | expr_fn_block(*) => { let caps = (*self.ir).captures(expr); for (*caps).each |cap| { - let var = self.variable_from_rdef(cap.rv, expr.span); + let var = self.variable(cap.var_nid, expr.span); self.consider_last_use(expr, cap.ln, var); if cap.is_move { self.check_move_from_var(expr.span, cap.ln, var); @@ -1575,7 +1536,15 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { match ty::resolved_mode(self.tcx, arg_ty.mode) { by_val | by_copy | by_ref => {} by_move => { - self.check_move_from_expr(*arg_expr, vt); + if ty::expr_is_lval(self.tcx, self.ir.method_map, + *arg_expr) { + // Probably a bad error message (what's an rvalue?) + // but I can't think of anything better + self.tcx.sess.span_err(arg_expr.span, + #fmt("Move mode argument must be an rvalue: try \ + (move %s) instead", expr_to_str(*arg_expr, + self.tcx.sess.intr()))); + } } } } @@ -1613,24 +1582,7 @@ enum ReadKind { } impl @Liveness { - fn check_fields(sp: span, entry_ln: LiveNode) { - for self.ir.field_map.each |nm, var| { - match self.live_on_entry(entry_ln, var) { - None => { /* ok */ } - Some(ExitNode) => { - self.tcx.sess.span_err( - sp, fmt!("field `self.%s` is never initialized", - self.tcx.sess.str_of(nm))); - } - Some(lnk) => { - self.report_illegal_read( - sp, lnk, var, PossiblyUninitializedField); - } - } - } - } - - fn check_ret(id: node_id, sp: span, fk: visit::fn_kind, + fn check_ret(id: node_id, sp: span, _fk: visit::fn_kind, entry_ln: LiveNode) { if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { // if no_ret_var is live, then we fall off the end of the @@ -1644,19 +1596,16 @@ impl @Liveness { self.tcx.sess.span_err( sp, ~"some control paths may return"); } else { - match fk { - visit::fk_ctor(*) => { - // ctors are written as though they are unit. - } - _ => { - self.tcx.sess.span_err( - sp, ~"not all control paths return a value"); - } - } + self.tcx.sess.span_err( + sp, ~"not all control paths return a value"); } } } + /* + Checks whether <var> is live on entry to any of the successors of <ln>. + If it is, report an error. + */ fn check_move_from_var(span: span, ln: LiveNode, var: Variable) { debug!("check_move_from_var(%s, %s)", ln.to_str(), var.to_str()); @@ -1732,12 +1681,11 @@ impl @Liveness { } def => { match relevant_def(def) { - Some(RelevantVar(nid)) => { + Some(nid) => { let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, ln, var); } - Some(RelevantSelf) => {} None => {} } } @@ -1796,13 +1744,6 @@ impl @Liveness { copy or move mode", self.tcx.sess.str_of(name))); return; } - Field(name) => { - self.tcx.sess.span_err( - move_span, - fmt!("illegal move from field `%s`", - self.tcx.sess.str_of(name))); - return; - } Self => { self.tcx.sess.span_err( move_span, diff --git a/src/rustc/middle/mem_categorization.rs b/src/rustc/middle/mem_categorization.rs index dc5874ea2cf..a61cb28c16b 100644 --- a/src/rustc/middle/mem_categorization.rs +++ b/src/rustc/middle/mem_categorization.rs @@ -122,7 +122,7 @@ impl categorization : cmp::Eq { enum ptr_kind { uniq_ptr, gc_ptr, - region_ptr(ty::region), + region_ptr(ty::Region), unsafe_ptr } @@ -993,7 +993,7 @@ impl &mem_categorization_ctxt { } } - fn region_to_str(r: ty::region) -> ~str { + fn region_to_str(r: ty::Region) -> ~str { region_to_str(self.tcx, r) } } diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index ff708b7f4ef..95280032ae0 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -7,7 +7,7 @@ region parameterized. */ -use driver::session::session; +use driver::session::Session; use middle::ty; use syntax::{ast, visit}; use syntax::codemap::span; @@ -41,7 +41,7 @@ Encodes the bounding lifetime for a given AST node: type region_map = HashMap<ast::node_id, ast::node_id>; struct ctxt { - sess: session, + sess: Session, def_map: resolve::DefMap, // Generated maps: @@ -108,8 +108,8 @@ fn scope_contains(region_map: region_map, superscope: ast::node_id, /// intended to run *after inference* and sadly the logic is somewhat /// duplicated with the code in infer.rs. fn is_subregion_of(region_map: region_map, - sub_region: ty::region, - super_region: ty::region) -> bool { + sub_region: ty::Region, + super_region: ty::Region) -> bool { sub_region == super_region || match (sub_region, super_region) { (_, ty::re_static) => { @@ -305,16 +305,16 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt<ctxt>) { let fn_cx = match fk { - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => { - // Top-level functions are a root scope. - ctxt {parent: Some(id),.. cx} - } + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + // Top-level functions are a root scope. + ctxt {parent: Some(id),.. cx} + } - visit::fk_anon(*) | visit::fk_fn_block(*) => { - // Closures continue with the inherited scope. - cx - } + visit::fk_anon(*) | visit::fk_fn_block(*) => { + // Closures continue with the inherited scope. + cx + } }; debug!("visiting fn with body %d. cx.parent: %? \ @@ -328,7 +328,7 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visit::visit_fn(fk, decl, body, sp, id, fn_cx, visitor); } -fn resolve_crate(sess: session, def_map: resolve::DefMap, +fn resolve_crate(sess: Session, def_map: resolve::DefMap, crate: @ast::crate) -> region_map { let cx: ctxt = ctxt {sess: sess, def_map: def_map, @@ -382,7 +382,7 @@ impl region_dep : cmp::Eq { } type determine_rp_ctxt_ = { - sess: session, + sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, region_paramd_items: region_paramd_items, @@ -599,7 +599,7 @@ fn determine_rp_in_ty_method(ty_m: ast::ty_method, } } -fn determine_rp_in_ty(ty: @ast::ty, +fn determine_rp_in_ty(ty: @ast::Ty, &&cx: determine_rp_ctxt, visitor: visit::vt<determine_rp_ctxt>) { @@ -640,8 +640,8 @@ fn determine_rp_in_ty(ty: @ast::ty, // that as a direct dependency. match ty.node { ast::ty_path(path, id) => { - match cx.def_map.get(id) { - ast::def_ty(did) | ast::def_class(did, _) => { + match cx.def_map.find(id) { + Some(ast::def_ty(did)) | Some(ast::def_class(did)) => { if did.crate == ast::local_crate { if cx.opt_region_is_relevant(path.rp) { cx.add_dep(did.node); @@ -755,7 +755,7 @@ fn determine_rp_in_struct_field(cm: @ast::struct_field, } } -fn determine_rp_in_crate(sess: session, +fn determine_rp_in_crate(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, crate: @ast::crate) -> region_paramd_items { diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 5f30346a28e..3d2cd6a621c 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -1,5 +1,6 @@ -use driver::session::session; +use driver::session::Session; use metadata::csearch::{each_path, get_method_names_if_trait}; +use metadata::csearch::{get_static_methods_if_impl, get_type_name_if_impl}; use metadata::cstore::find_use_stmt_cnum; use metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; use middle::lang_items::LanguageItems; @@ -8,8 +9,7 @@ use middle::pat_util::{pat_bindings}; use syntax::ast::{_mod, add, arm}; use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value}; use syntax::ast::{bitand, bitor, bitxor}; -use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send}; -use syntax::ast::{bound_trait, binding_mode, +use syntax::ast::{binding_mode, blk, capture_clause, class_ctor, class_dtor}; use syntax::ast::{crate, crate_num, decl_item}; use syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn}; @@ -35,10 +35,11 @@ use syntax::ast::{pat_box, pat_lit, pat_range, pat_rec, pat_struct}; use syntax::ast::{pat_tup, pat_uniq, pat_wild, private, provided, public}; use syntax::ast::{required, rem, self_ty_, shl, shr, stmt_decl}; use syntax::ast::{struct_field, struct_variant_kind, sty_static, subtract}; -use syntax::ast::{trait_ref, tuple_variant_kind, ty, ty_bool, ty_char}; +use syntax::ast::{trait_ref, tuple_variant_kind, Ty, ty_bool, ty_char}; use syntax::ast::{ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16, ty_i32}; use syntax::ast::{ty_i64, ty_i8, ty_int, ty_param, ty_path, ty_str, ty_u}; use syntax::ast::{ty_u16, ty_u32, ty_u64, ty_u8, ty_uint, type_value_ns}; +use syntax::ast::{ty_param_bound}; use syntax::ast::{variant, view_item, view_item_export, view_item_import}; use syntax::ast::{view_item_use, view_path_glob, view_path_list}; use syntax::ast::{view_path_simple, visibility, anonymous, named}; @@ -115,7 +116,6 @@ impl PatternBindingMode : cmp::Eq { enum Namespace { - ModuleNS, TypeNS, ValueNS } @@ -166,19 +166,8 @@ enum CaptureClause { type ResolveVisitor = vt<()>; -enum ModuleDef { - NoModuleDef, // Does not define a module. - ModuleDef(Privacy, @Module), // Defines a module. -} - -impl ModuleDef { - pure fn is_none() -> bool { - match self { NoModuleDef => true, _ => false } - } -} - enum ImportDirectiveNS { - ModuleNSOnly, + TypeNSOnly, AnyNS } @@ -257,7 +246,10 @@ enum RibKind { MethodRibKind(node_id, MethodSort), // We passed through a function *item* scope. Disallow upvars. - OpaqueFunctionRibKind + OpaqueFunctionRibKind, + + // We're in a constant item. Can't refer to dynamic stuff. + ConstantItemRibKind } // Methods can be required or provided. Required methods only occur in traits. @@ -303,6 +295,35 @@ enum EnumVariantOrConstResolution { EnumVariantOrConstNotFound } +// Specifies how duplicates should be handled when adding a child item if +// another item exists with the same name in some namespace. +enum DuplicateCheckingMode { + ForbidDuplicateModules, + ForbidDuplicateTypes, + ForbidDuplicateValues, + ForbidDuplicateTypesAndValues, + OverwriteDuplicates +} + +impl DuplicateCheckingMode : cmp::Eq { + pure fn eq(other: &DuplicateCheckingMode) -> bool { + (self as uint) == (*other as uint) + } + pure fn ne(other: &DuplicateCheckingMode) -> bool { !self.eq(other) } +} + +// Returns the namespace associated with the given duplicate checking mode, +// or fails for OverwriteDuplicates. This is used for error messages. +fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode) -> + Namespace { + match mode { + ForbidDuplicateModules | ForbidDuplicateTypes | + ForbidDuplicateTypesAndValues => TypeNS, + ForbidDuplicateValues => ValueNS, + OverwriteDuplicates => fail ~"OverwriteDuplicates has no namespace" + } +} + /// One local scope. struct Rib { bindings: HashMap<ident,def_like>, @@ -360,7 +381,6 @@ struct ImportResolution { mut outstanding_references: uint, - mut module_target: Option<Target>, mut value_target: Option<Target>, mut type_target: Option<Target>, @@ -372,7 +392,6 @@ fn ImportResolution(privacy: Privacy, span: span) -> ImportResolution { privacy: privacy, span: span, outstanding_references: 0u, - module_target: None, value_target: None, type_target: None, used: false @@ -382,7 +401,6 @@ fn ImportResolution(privacy: Privacy, span: span) -> ImportResolution { impl ImportResolution { fn target_for_namespace(namespace: Namespace) -> Option<Target> { match namespace { - ModuleNS => return copy self.module_target, TypeNS => return copy self.type_target, ValueNS => return copy self.value_target } @@ -479,7 +497,7 @@ pure fn is_none<T>(x: Option<T>) -> bool { } } -fn unused_import_lint_level(session: session) -> level { +fn unused_import_lint_level(session: Session) -> level { for session.opts.lint_opts.each |lint_option_pair| { let (lint_type, lint_level) = *lint_option_pair; if lint_type == unused_imports { @@ -501,8 +519,15 @@ impl Privacy : cmp::Eq { pure fn ne(other: &Privacy) -> bool { !self.eq(other) } } -// Records a possibly-private definition. -struct Definition { +// Records a possibly-private type definition. +struct TypeNsDef { + mut privacy: Privacy, + mut module_def: Option<@Module>, + mut type_def: Option<def> +} + +// Records a possibly-private value definition. +struct ValueNsDef { privacy: Privacy, def: def, } @@ -510,13 +535,11 @@ struct Definition { // Records the definitions (at most one for each namespace) that a name is // bound to. struct NameBindings { - mut module_def: ModuleDef, //< Meaning in module namespace. - mut type_def: Option<Definition>, //< Meaning in type namespace. - mut value_def: Option<Definition>, //< Meaning in value namespace. + mut type_def: Option<TypeNsDef>, //< Meaning in type namespace. + mut value_def: Option<ValueNsDef>, //< Meaning in value namespace. // For error reporting - // XXX: Merge me into Definition. - mut module_span: Option<span>, + // FIXME (#3783): Merge me into TypeNsDef and ValueNsDef. mut type_span: Option<span>, mut value_span: Option<span>, } @@ -529,30 +552,60 @@ impl NameBindings { def_id: Option<def_id>, legacy_exports: bool, sp: span) { - if self.module_def.is_none() { - let module_ = @Module(parent_link, def_id, legacy_exports); - self.module_def = ModuleDef(privacy, module_); - self.module_span = Some(sp); + // Merges the module with the existing type def or creates a new one. + let module_ = @Module(parent_link, def_id, legacy_exports); + match self.type_def { + None => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: Some(module_), + type_def: None + }); + } + Some(copy type_def) => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: Some(module_), + .. type_def + }); + } } + self.type_span = Some(sp); } /// Records a type definition. fn define_type(privacy: Privacy, def: def, sp: span) { - self.type_def = Some(Definition { privacy: privacy, def: def }); + // Merges the type with the existing type def or creates a new one. + match self.type_def { + None => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: None, + type_def: Some(def) + }); + } + Some(copy type_def) => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + type_def: Some(def), + .. type_def + }); + } + } self.type_span = Some(sp); } /// Records a value definition. fn define_value(privacy: Privacy, def: def, sp: span) { - self.value_def = Some(Definition { privacy: privacy, def: def }); + self.value_def = Some(ValueNsDef { privacy: privacy, def: def }); self.value_span = Some(sp); } /// Returns the module node if applicable. fn get_module_if_available() -> Option<@Module> { - match self.module_def { - NoModuleDef => return None, - ModuleDef(_privacy, module_) => return Some(module_) + match self.type_def { + Some(type_def) => type_def.module_def, + None => None } } @@ -561,70 +614,88 @@ impl NameBindings { * definition. */ fn get_module() -> @Module { - match self.module_def { - NoModuleDef => { - fail - ~"get_module called on a node with no module definition!"; - } - ModuleDef(_, module_) => { - return module_; + match self.get_module_if_available() { + None => { + fail ~"get_module called on a node with no module \ + definition!" } + Some(module_def) => module_def } } fn defined_in_namespace(namespace: Namespace) -> bool { match namespace { - ModuleNS => { - match self.module_def { - NoModuleDef => false, - _ => true - } - } TypeNS => return self.type_def.is_some(), ValueNS => return self.value_def.is_some() } } - fn def_for_namespace(namespace: Namespace) -> Option<Definition> { + fn def_for_namespace(namespace: Namespace) -> Option<def> { match namespace { - TypeNS => return self.type_def, - ValueNS => return self.value_def, - ModuleNS => match self.module_def { - NoModuleDef => return None, - ModuleDef(privacy, module_) => - match module_.def_id { - None => return None, - Some(def_id) => { - return Some(Definition { - privacy: privacy, - def: def_mod(def_id) - }); + TypeNS => { + match self.type_def { + None => None, + Some(type_def) => { + // FIXME (#3784): This is reallllly questionable. + // Perhaps the right thing to do is to merge def_mod + // and def_ty. + match type_def.type_def { + Some(type_def) => Some(type_def), + None => { + match type_def.module_def { + Some(module_def) => { + module_def.def_id.map(|def_id| + def_mod(*def_id)) + } + None => None + } + } + } } } - } + } + ValueNS => { + match self.value_def { + None => None, + Some(value_def) => Some(value_def.def) + } + } + } + } + + fn privacy_for_namespace(namespace: Namespace) -> Option<Privacy> { + match namespace { + TypeNS => { + match self.type_def { + None => None, + Some(type_def) => Some(type_def.privacy) + } + } + ValueNS => { + match self.value_def { + None => None, + Some(value_def) => Some(value_def.privacy) + } + } } } fn span_for_namespace(namespace: Namespace) -> Option<span> { - match self.def_for_namespace(namespace) { - Some(_) => { + if self.defined_in_namespace(namespace) { match namespace { - TypeNS => self.type_span, - ValueNS => self.value_span, - ModuleNS => self.module_span + TypeNS => self.type_span, + ValueNS => self.value_span, } - } - None => None + } else { + None } } } fn NameBindings() -> NameBindings { NameBindings { - module_def: NoModuleDef, type_def: None, value_def: None, - module_span: None, type_span: None, value_span: None } @@ -672,9 +743,8 @@ fn PrimitiveTypeTable(intr: @ident_interner) -> PrimitiveTypeTable { fn namespace_to_str(ns: Namespace) -> ~str { match ns { - TypeNS => ~"type", - ValueNS => ~"value", - ModuleNS => ~"module" + TypeNS => ~"type", + ValueNS => ~"value", } } @@ -690,9 +760,8 @@ fn has_legacy_export_attr(attrs: &[syntax::ast::attribute]) -> bool { return false; } -fn Resolver(session: session, lang_items: LanguageItems, +fn Resolver(session: Session, lang_items: LanguageItems, crate: @crate) -> Resolver { - let graph_root = @NameBindings(); (*graph_root).define_module(Public, @@ -732,7 +801,7 @@ fn Resolver(session: session, lang_items: LanguageItems, primitive_type_table: @PrimitiveTypeTable(session. parse_sess.interner), - namespaces: ~[ ModuleNS, TypeNS, ValueNS ], + namespaces: ~[ TypeNS, ValueNS ], def_map: HashMap(), export_map2: HashMap(), @@ -746,7 +815,7 @@ fn Resolver(session: session, lang_items: LanguageItems, /// The main resolver class. struct Resolver { - session: session, + session: Session, lang_items: LanguageItems, crate: @crate, @@ -757,7 +826,7 @@ struct Resolver { unused_import_lint_level: level, trait_info: HashMap<def_id,@HashMap<ident,()>>, - structs: HashMap<def_id,bool>, + structs: HashMap<def_id,()>, // The number of imports that are currently unresolved. mut unresolved_imports: uint, @@ -886,9 +955,7 @@ impl Resolver { */ fn add_child(name: ident, reduced_graph_parent: ReducedGraphParent, - // Pass in the namespaces for the child item so that we can - // check for duplicate items in the same namespace - ns: ~[Namespace], + duplicate_checking_mode: DuplicateCheckingMode, // For printing errors sp: span) -> (@NameBindings, ReducedGraphParent) { @@ -908,29 +975,67 @@ impl Resolver { let new_parent = ModuleReducedGraphParent(module_); match module_.children.find(name) { None => { - let child = @NameBindings(); - module_.children.insert(name, child); - return (child, new_parent); + let child = @NameBindings(); + module_.children.insert(name, child); + return (child, new_parent); } Some(child) => { - // We don't want to complain if the multiple definitions - // are in different namespaces. - match ns.find(|n| child.defined_in_namespace(n)) { - Some(ns) => { - self.session.span_err(sp, - #fmt("Duplicate definition of %s %s", - namespace_to_str(ns), - self.session.str_of(name))); - do child.span_for_namespace(ns).iter() |sp| { - self.session.span_note(*sp, - #fmt("First definition of %s %s here:", - namespace_to_str(ns), - self.session.str_of(name))); - } + // Enforce the duplicate checking mode. If we're requesting + // duplicate module checking, check that there isn't a module + // in the module with the same name. If we're requesting + // duplicate type checking, check that there isn't a type in + // the module with the same name. If we're requesting + // duplicate value checking, check that there isn't a value in + // the module with the same name. If we're requesting + // duplicate type checking and duplicate value checking, check + // that there isn't a duplicate type and a duplicate value + // with the same name. If no duplicate checking was requested + // at all, do nothing. + + let mut is_duplicate = false; + match duplicate_checking_mode { + ForbidDuplicateModules => { + is_duplicate = + child.get_module_if_available().is_some(); + } + ForbidDuplicateTypes => { + match child.def_for_namespace(TypeNS) { + Some(def_mod(_)) | None => {} + Some(_) => is_duplicate = true + } + } + ForbidDuplicateValues => { + is_duplicate = child.defined_in_namespace(ValueNS); + } + ForbidDuplicateTypesAndValues => { + match child.def_for_namespace(TypeNS) { + Some(def_mod(_)) | None => {} + Some(_) => is_duplicate = true + }; + if child.defined_in_namespace(ValueNS) { + is_duplicate = true; + } + } + OverwriteDuplicates => {} + } + if duplicate_checking_mode != OverwriteDuplicates && + is_duplicate { + // Return an error here by looking up the namespace that + // had the duplicate. + let ns = namespace_for_duplicate_checking_mode( + duplicate_checking_mode); + self.session.span_err(sp, + fmt!("duplicate definition of %s %s", + namespace_to_str(ns), + self.session.str_of(name))); + do child.span_for_namespace(ns).iter() |sp| { + self.session.span_note(*sp, + fmt!("first definition of %s %s here:", + namespace_to_str(ns), + self.session.str_of(name))); + } } - _ => {} - } - return (child, new_parent); + return (child, new_parent); } } } @@ -979,7 +1084,6 @@ impl Resolver { fn build_reduced_graph_for_item(item: @item, parent: ReducedGraphParent, &&visitor: vt<ReducedGraphParent>) { - let ident = item.ident; let sp = item.span; let legacy = match parent { @@ -989,53 +1093,60 @@ impl Resolver { match item.node { item_mod(module_) => { - let legacy = has_legacy_export_attr(item.attrs); - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[ModuleNS], sp); + let legacy = has_legacy_export_attr(item.attrs); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateModules, sp); let parent_link = self.get_parent_link(new_parent, ident); let def_id = { crate: 0, node: item.id }; - (*name_bindings).define_module(privacy, parent_link, - Some(def_id), legacy, sp); + (*name_bindings).define_module(privacy, parent_link, + Some(def_id), legacy, sp); let new_parent = ModuleReducedGraphParent((*name_bindings).get_module()); visit_mod(module_, sp, item.id, new_parent, visitor); } + item_foreign_mod(fm) => { - let legacy = has_legacy_export_attr(item.attrs); - let new_parent = match fm.sort { - named => { - let (name_bindings, new_parent) = self.add_child(ident, - parent, ~[ModuleNS], sp); + let legacy = has_legacy_export_attr(item.attrs); + let new_parent = match fm.sort { + named => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, + ForbidDuplicateModules, sp); - let parent_link = self.get_parent_link(new_parent, ident); - let def_id = { crate: 0, node: item.id }; - (*name_bindings).define_module(privacy, parent_link, - Some(def_id), legacy, sp); + let parent_link = self.get_parent_link(new_parent, + ident); + let def_id = { crate: 0, node: item.id }; + (*name_bindings).define_module(privacy, + parent_link, + Some(def_id), + legacy, + sp); + + ModuleReducedGraphParent(name_bindings.get_module()) + } - ModuleReducedGraphParent((*name_bindings).get_module()) - } - // For anon foreign mods, the contents just go in the - // current scope - anonymous => parent - }; + // For anon foreign mods, the contents just go in the + // current scope + anonymous => parent + }; - visit_item(item, new_parent, visitor); + visit_item(item, new_parent, visitor); } // These items live in the value namespace. item_const(*) => { - let (name_bindings, _) = self.add_child(ident, parent, - ~[ValueNS], sp); + let (name_bindings, _) = + self.add_child(ident, parent, ForbidDuplicateValues, sp); (*name_bindings).define_value (privacy, def_const(local_def(item.id)), sp); } item_fn(_, purity, _, _) => { - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[ValueNS], sp); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateValues, sp); let def = def_fn(local_def(item.id), purity); (*name_bindings).define_value(privacy, def, sp); @@ -1044,17 +1155,16 @@ impl Resolver { // These items live in the type namespace. item_ty(*) => { - let (name_bindings, _) = self.add_child(ident, parent, - ~[TypeNS], sp); + let (name_bindings, _) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); (*name_bindings).define_type (privacy, def_ty(local_def(item.id)), sp); } item_enum(enum_definition, _) => { - - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[TypeNS], sp); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); (*name_bindings).define_type (privacy, def_ty(local_def(item.id)), sp); @@ -1069,47 +1179,88 @@ impl Resolver { } // These items live in both the type and value namespaces. - item_class(struct_definition, _) => { - let new_parent = - match struct_definition.ctor { - None => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); - - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); - new_parent - } - Some(ctor) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[ValueNS, TypeNS], - sp); - - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); + item_class(*) => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); - let purity = impure_fn; - let ctor_def = def_fn(local_def(ctor.node.id), - purity); - (*name_bindings).define_value(privacy, ctor_def, sp); - new_parent - } - }; + (*name_bindings).define_type + (privacy, def_ty(local_def(item.id)), sp); // Record the def ID of this struct. - self.structs.insert(local_def(item.id), - struct_definition.ctor.is_some()); + self.structs.insert(local_def(item.id), ()); visit_item(item, new_parent, visitor); } - item_impl(*) => { + item_impl(_, trait_ref_opt, ty, methods) => { + // If this implements an anonymous trait and it has static + // methods, then add all the static methods within to a new + // module, if the type was defined within this module. + // + // FIXME (#3785): This is quite unsatisfactory. Perhaps we + // should modify anonymous traits to only be implementable in + // the same module that declared the type. + + // Bail out early if there are no static methods. + let mut has_static_methods = false; + for methods.each |method| { + match method.self_ty.node { + sty_static => has_static_methods = true, + _ => {} + } + } + + // If there are static methods, then create the module + // and add them. + match (trait_ref_opt, ty) { + (None, @{ id: _, node: ty_path(path, _), span: _ }) if + has_static_methods && path.idents.len() == 1 => { + // Create the module. + let name = path_to_ident(path); + let (name_bindings, new_parent) = + self.add_child(name, + parent, + ForbidDuplicateModules, + sp); + + let parent_link = self.get_parent_link(new_parent, + ident); + let def_id = local_def(item.id); + name_bindings.define_module(privacy, parent_link, + Some(def_id), false, sp); + + let new_parent = ModuleReducedGraphParent( + name_bindings.get_module()); + + // For each static method... + for methods.each |method| { + match method.self_ty.node { + sty_static => { + // Add the static method to the module. + let ident = method.ident; + let (method_name_bindings, _) = + self.add_child(ident, + new_parent, + ForbidDuplicateValues, + method.span); + let def = def_fn(local_def(method.id), + method.purity); + method_name_bindings.define_value( + Public, def, method.span); + } + _ => {} + } + } + } + _ => {} + } + visit_item(item, parent, visitor); } item_trait(_, _, methods) => { - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[TypeNS], sp); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); // Add the names of all the methods to the trait info. let method_names = @HashMap(); @@ -1123,9 +1274,10 @@ impl Resolver { sty_static => { // which parent to use?? let (method_name_bindings, _) = - self.add_child(ident, new_parent, ~[ValueNS], - ty_m.span); + self.add_child(ident, new_parent, + ForbidDuplicateValues, ty_m.span); let def = def_static_method(local_def(ty_m.id), + Some(local_def(item.id)), ty_m.purity); (*method_name_bindings).define_value (Public, def, ty_m.span); @@ -1161,7 +1313,7 @@ impl Resolver { &&visitor: vt<ReducedGraphParent>) { let ident = variant.node.name; - let (child, _) = self.add_child(ident, parent, ~[ValueNS], + let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues, variant.span); let privacy; @@ -1183,7 +1335,7 @@ impl Resolver { def_variant(item_id, local_def(variant.node.id)), variant.span); - self.structs.insert(local_def(variant.node.id), false); + self.structs.insert(local_def(variant.node.id), ()); } enum_variant_kind(enum_definition) => { (*child).define_type(privacy, @@ -1243,7 +1395,7 @@ impl Resolver { match view_path.node { view_path_simple(binding, full_path, ns, _) => { let ns = match ns { - module_ns => ModuleNSOnly, + module_ns => TypeNSOnly, type_value_ns => AnyNS }; @@ -1343,8 +1495,7 @@ impl Resolver { match find_use_stmt_cnum(self.session.cstore, node_id) { Some(crate_id) => { let (child_name_bindings, new_parent) = - // should this be in ModuleNS? --tjc - self.add_child(name, parent, ~[ModuleNS], + self.add_child(name, parent, ForbidDuplicateTypes, view_item.span); let def_id = { crate: crate_id, node: 0 }; @@ -1375,7 +1526,8 @@ impl Resolver { let name = foreign_item.ident; let (name_bindings, new_parent) = - self.add_child(name, parent, ~[ValueNS], foreign_item.span); + self.add_child(name, parent, ForbidDuplicateValues, + foreign_item.span); match foreign_item.node { foreign_item_fn(_, purity, type_parameters) => { @@ -1427,8 +1579,14 @@ impl Resolver { ident: ident, new_parent: ReducedGraphParent) { match def { def_mod(def_id) | def_foreign_mod(def_id) => { - match copy child_name_bindings.module_def { - NoModuleDef => { + match copy child_name_bindings.type_def { + Some(TypeNsDef { module_def: Some(copy module_def), _ }) => { + debug!("(building reduced graph for external crate) \ + already created module"); + module_def.def_id = Some(def_id); + modules.insert(def_id, module_def); + } + Some(_) | None => { debug!("(building reduced graph for \ external crate) building module \ %s", final_ident); @@ -1458,10 +1616,8 @@ impl Resolver { fail ~"can't happen"; } ModuleParentLink(parent_module, ident) => { - let name_bindings = parent_module.children.get(ident); - - resolution.module_target = + resolution.type_target = Some(Target(parent_module, name_bindings)); } } @@ -1473,13 +1629,6 @@ impl Resolver { } } } - ModuleDef(_priv, module_) => { - debug!("(building reduced graph for \ - external crate) already created \ - module"); - module_.def_id = Some(def_id); - modules.insert(def_id, module_); - } } } def_fn(*) | def_static_method(*) | def_const(*) | @@ -1495,8 +1644,7 @@ impl Resolver { // If this is a trait, add all the method names // to the trait info. - match get_method_names_if_trait(self.session.cstore, - def_id) { + match get_method_names_if_trait(self.session.cstore, def_id) { None => { // Nothing to do. } @@ -1520,18 +1668,12 @@ impl Resolver { child_name_bindings.define_type(Public, def, dummy_sp()); } - def_class(def_id, has_constructor) => { + def_class(def_id) => { debug!("(building reduced graph for external \ - crate) building type %s (value? %d)", - final_ident, - if has_constructor { 1 } else { 0 }); + crate) building type %s", + final_ident); child_name_bindings.define_type(Public, def, dummy_sp()); - - if has_constructor { - child_name_bindings.define_value(Public, def, dummy_sp()); - } - - self.structs.insert(def_id, has_constructor); + self.structs.insert(def_id, ()); } def_self(*) | def_arg(*) | def_local(*) | def_prim_ty(*) | def_ty_param(*) | def_binding(*) | @@ -1572,12 +1714,12 @@ impl Resolver { let (child_name_bindings, new_parent) = self.add_child(ident, ModuleReducedGraphParent(current_module), - // May want a better span - ~[], dummy_sp()); + OverwriteDuplicates, + dummy_sp()); // Define or reuse the module node. - match child_name_bindings.module_def { - NoModuleDef => { + match child_name_bindings.type_def { + None => { debug!("(building reduced graph for external crate) \ autovivifying %s", *ident_str); let parent_link = self.get_parent_link(new_parent, @@ -1587,32 +1729,111 @@ impl Resolver { None, false, dummy_sp()); } - ModuleDef(*) => { /* Fall through. */ } + Some(_) => { /* Fall through. */ } } current_module = (*child_name_bindings).get_module(); } - // Add the new child item. - let (child_name_bindings, new_parent) = - self.add_child(final_ident, - ModuleReducedGraphParent(current_module), - ~[], dummy_sp()); - match path_entry.def_like { dl_def(def) => { + // Add the new child item. + let (child_name_bindings, new_parent) = + self.add_child(final_ident, + ModuleReducedGraphParent( + current_module), + OverwriteDuplicates, + dummy_sp()); + self.handle_external_def(def, modules, child_name_bindings, self.session.str_of(final_ident), final_ident, new_parent); } - dl_impl(_) => { - // Because of the infelicitous way the metadata is - // written, we can't process this impl now. We'll get it - // later. - + dl_impl(def) => { + // We only process static methods of impls here. debug!("(building reduced graph for external crate) \ - ignoring impl %s", final_ident_str); + processing impl %s", final_ident_str); + + match get_type_name_if_impl(self.session.cstore, def) { + None => {} + Some(final_ident) => { + let static_methods_opt = + get_static_methods_if_impl( + self.session.cstore, def); + match static_methods_opt { + Some(static_methods) if + static_methods.len() >= 1 => { + debug!("(building reduced graph for \ + external crate) processing \ + static methods for type name %s", + self.session.str_of(final_ident)); + + let (child_name_bindings, new_parent) = + self.add_child(final_ident, + ModuleReducedGraphParent( + current_module), + OverwriteDuplicates, + dummy_sp()); + + // Process the static methods. First, + // create the module. + let type_module; + match copy child_name_bindings.type_def { + Some(TypeNsDef { + module_def: Some(copy module_def), + _ + }) => { + // We already have a module. This + // is OK. + type_module = module_def; + } + Some(_) | None => { + let parent_link = + self.get_parent_link( + new_parent, final_ident); + child_name_bindings.define_module( + Public, + parent_link, + Some(def), + false, + dummy_sp()); + type_module = + child_name_bindings. + get_module(); + } + } + + // Add each static method to the module. + let new_parent = ModuleReducedGraphParent( + type_module); + for static_methods.each + |static_method_info| { + let ident = static_method_info.ident; + debug!("(building reduced graph for \ + external crate) creating \ + static method '%s'", + self.session.str_of(ident)); + + let (method_name_bindings, _) = + self.add_child( + ident, + new_parent, + OverwriteDuplicates, + dummy_sp()); + let def = def_fn( + static_method_info.def_id, + static_method_info.purity); + method_name_bindings.define_value( + Public, def, dummy_sp()); + } + } + + // Otherwise, do nothing. + Some(_) | None => {} + } + } + } } dl_field => { debug!("(building reduced graph for external crate) \ @@ -1628,7 +1849,6 @@ impl Resolver { module_path: @DVec<ident>, subclass: @ImportDirectiveSubclass, span: span) { - let directive = @ImportDirective(privacy, module_path, subclass, span); module_.imports.push(directive); @@ -1830,7 +2050,7 @@ impl Resolver { target, source); } - SingleImport(target, source, ModuleNSOnly) => { + SingleImport(target, source, TypeNSOnly) => { resolution_result = self.resolve_single_module_import (module_, containing_module, target, @@ -1899,12 +2119,11 @@ impl Resolver { return Failed; } - // We need to resolve all four namespaces for this to succeed. + // We need to resolve both namespaces for this to succeed. // // XXX: See if there's some way of handling namespaces in a more - // generic way. We have four of them; it seems worth doing... + // generic way. We have two of them; it seems worth doing... - let mut module_result = UnknownResult; let mut value_result = UnknownResult; let mut type_result = UnknownResult; @@ -1914,10 +2133,6 @@ impl Resolver { // Continue. } Some(child_name_bindings) => { - if (*child_name_bindings).defined_in_namespace(ModuleNS) { - module_result = BoundResult(containing_module, - child_name_bindings); - } if (*child_name_bindings).defined_in_namespace(ValueNS) { value_result = BoundResult(containing_module, child_name_bindings); @@ -1929,11 +2144,10 @@ impl Resolver { } } - // Unless we managed to find a result in all four namespaces - // (exceedingly unlikely), search imports as well. - - match (module_result, value_result, type_result) { - (BoundResult(*), BoundResult(*), BoundResult(*)) => { + // Unless we managed to find a result in both namespaces (unlikely), + // search imports as well. + match (value_result, type_result) { + (BoundResult(*), BoundResult(*)) => { // Continue. } _ => { @@ -1957,9 +2171,6 @@ impl Resolver { // therefore accurately report that the names are // unbound. - if module_result.is_unknown() { - module_result = UnboundResult; - } if value_result.is_unknown() { value_result = UnboundResult; } @@ -1996,11 +2207,6 @@ impl Resolver { // The name is an import which has been fully // resolved. We can, therefore, just follow it. - - if module_result.is_unknown() { - module_result = get_binding(import_resolution, - ModuleNS); - } if value_result.is_unknown() { value_result = get_binding(import_resolution, ValueNS); @@ -2024,20 +2230,6 @@ impl Resolver { assert module_.import_resolutions.contains_key(target); let import_resolution = module_.import_resolutions.get(target); - match module_result { - BoundResult(target_module, name_bindings) => { - debug!("(resolving single import) found module binding"); - import_resolution.module_target = - Some(Target(target_module, name_bindings)); - } - UnboundResult => { - debug!("(resolving single import) didn't find module \ - binding"); - } - UnknownResult => { - fail ~"module result should be known at this point"; - } - } match value_result { BoundResult(target_module, name_bindings) => { import_resolution.value_target = @@ -2060,12 +2252,10 @@ impl Resolver { } let i = import_resolution; - match (i.module_target, i.value_target, i.type_target) { - /* - If this name wasn't found in any of the four namespaces, it's - definitely unresolved - */ - (None, None, None) => { return Failed; } + match (i.value_target, i.type_target) { + // If this name wasn't found in either namespace, it's definitely + // unresolved. + (None, None) => { return Failed; } _ => {} } @@ -2104,7 +2294,7 @@ impl Resolver { // Continue. } Some(child_name_bindings) => { - if (*child_name_bindings).defined_in_namespace(ModuleNS) { + if (*child_name_bindings).defined_in_namespace(TypeNS) { module_result = BoundResult(containing_module, child_name_bindings); } @@ -2148,8 +2338,8 @@ impl Resolver { // resolved. We can, therefore, just follow it. if module_result.is_unknown() { - match (*import_resolution). - target_for_namespace(ModuleNS) { + match (*import_resolution).target_for_namespace( + TypeNS) { None => { module_result = UnboundResult; } @@ -2179,7 +2369,7 @@ impl Resolver { match module_result { BoundResult(target_module, name_bindings) => { debug!("(resolving single import) found module binding"); - import_resolution.module_target = + import_resolution.type_target = Some(Target(target_module, name_bindings)); } UnboundResult => { @@ -2192,8 +2382,8 @@ impl Resolver { } let i = import_resolution; - if i.module_target.is_none() { - // If this name wasn't found in the module namespace, it's + if i.type_target.is_none() { + // If this name wasn't found in the type namespace, it's // definitely unresolved. return Failed; } @@ -2245,7 +2435,7 @@ impl Resolver { debug!("(resolving glob import) writing module resolution \ %? into `%s`", - is_none(target_import_resolution.module_target), + is_none(target_import_resolution.type_target), self.module_to_str(module_)); // Here we merge two import resolutions. @@ -2255,8 +2445,6 @@ impl Resolver { let new_import_resolution = @ImportResolution(privacy, target_import_resolution.span); - new_import_resolution.module_target = - copy target_import_resolution.module_target; new_import_resolution.value_target = copy target_import_resolution.value_target; new_import_resolution.type_target = @@ -2269,15 +2457,6 @@ impl Resolver { // Merge the two import resolutions at a finer-grained // level. - match copy target_import_resolution.module_target { - None => { - // Continue. - } - Some(module_target) => { - dest_import_resolution.module_target = - Some(copy module_target); - } - } match copy target_import_resolution.value_target { None => { // Continue. @@ -2330,11 +2509,6 @@ impl Resolver { self.module_to_str(module_)); // Merge the child item into the import resolution. - if (*name_bindings).defined_in_namespace(ModuleNS) { - debug!("(resolving glob import) ... for module target"); - dest_import_resolution.module_target = - Some(Target(containing_module, name_bindings)); - } if (*name_bindings).defined_in_namespace(ValueNS) { debug!("(resolving glob import) ... for value target"); dest_import_resolution.value_target = @@ -2357,7 +2531,6 @@ impl Resolver { xray: XrayFlag, span: span) -> ResolveResult<@Module> { - let mut search_module = module_; let mut index = index; let module_path_len = (*module_path).len(); @@ -2368,9 +2541,8 @@ impl Resolver { while index < module_path_len { let name = (*module_path).get_elt(index); - match self.resolve_name_in_module(search_module, name, ModuleNS, - xray) { - + match self.resolve_name_in_module(search_module, name, TypeNS, + xray) { Failed => { self.session.span_err(span, ~"unresolved name"); return Failed; @@ -2382,18 +2554,34 @@ impl Resolver { return Indeterminate; } Success(target) => { - match target.bindings.module_def { - NoModuleDef => { - // Not a module. + // Check to see whether there are type bindings, and, if + // so, whether there is a module within. + match target.bindings.type_def { + Some(copy type_def) => { + match type_def.module_def { + None => { + // Not a module. + self.session.span_err(span, + fmt!("not a \ + module: %s", + self.session. + str_of( + name))); + return Failed; + } + Some(copy module_def) => { + search_module = module_def; + } + } + } + None => { + // There are no type bindings at all. self.session.span_err(span, fmt!("not a module: %s", - self.session. - str_of(name))); + self.session.str_of( + name))); return Failed; } - ModuleDef(_, copy module_) => { - search_module = module_; - } } } } @@ -2466,7 +2654,6 @@ impl Resolver { match module_.children.find(name) { Some(name_bindings) if (*name_bindings).defined_in_namespace(namespace) => { - return Success(Target(module_, name_bindings)); } Some(_) | None => { /* Not found; continue. */ } @@ -2538,18 +2725,27 @@ impl Resolver { fn resolve_module_in_lexical_scope(module_: @Module, name: ident) -> ResolveResult<@Module> { - - match self.resolve_item_in_lexical_scope(module_, name, ModuleNS) { + match self.resolve_item_in_lexical_scope(module_, name, TypeNS) { Success(target) => { - match target.bindings.module_def { - NoModuleDef => { + match target.bindings.type_def { + Some(type_def) => { + match type_def.module_def { + None => { + error!("!!! (resolving module in lexical \ + scope) module wasn't actually a \ + module!"); + return Failed; + } + Some(module_def) => { + return Success(module_def); + } + } + } + None => { error!("!!! (resolving module in lexical scope) module wasn't actually a module!"); return Failed; } - ModuleDef(_, module_) => { - return Success(module_); - } } } Indeterminate => { @@ -2684,8 +2880,7 @@ impl Resolver { debug!("(resolving one-level naming result) searching for module"); match self.resolve_item_in_lexical_scope(module_, source_name, - ModuleNS) { - + TypeNS) { Failed => { debug!("(resolving one-level renaming import) didn't find \ module result"); @@ -2705,7 +2900,7 @@ impl Resolver { let mut value_result; let mut type_result; - if allowable_namespaces == ModuleNSOnly { + if allowable_namespaces == TypeNSOnly { value_result = None; type_result = None; } else { @@ -2795,7 +2990,6 @@ impl Resolver { self.session.str_of(target_name), self.module_to_str(module_)); - import_resolution.module_target = module_result; import_resolution.value_target = value_result; import_resolution.type_target = type_result; @@ -2908,18 +3102,19 @@ impl Resolver { ident: ident, namebindings: @NameBindings, reexport: bool) { - for [ModuleNS, TypeNS, ValueNS].each |ns| { - match namebindings.def_for_namespace(*ns) { - Some(d) if d.privacy == Public => { + for [ TypeNS, ValueNS ].each |ns| { + match (namebindings.def_for_namespace(*ns), + namebindings.privacy_for_namespace(*ns)) { + (Some(d), Some(Public)) => { debug!("(computing exports) YES: %s '%s' \ => %?", if reexport { ~"reexport" } else { ~"export"}, self.session.str_of(ident), - def_id_of_def(d.def)); + def_id_of_def(d)); exports2.push(Export2 { reexport: reexport, name: self.session.str_of(ident), - def_id: def_id_of_def(d.def) + def_id: def_id_of_def(d) }); } _ => () @@ -2937,12 +3132,13 @@ impl Resolver { } for module_.import_resolutions.each_ref |ident, importresolution| { - for [ModuleNS, TypeNS, ValueNS].each |ns| { + for [ TypeNS, ValueNS ].each |ns| { match importresolution.target_for_namespace(*ns) { Some(target) => { debug!("(computing exports) maybe reexport '%s'", self.session.str_of(*ident)); - self.add_exports_of_namebindings(exports2, *ident, + self.add_exports_of_namebindings(exports2, + *ident, target.bindings, true) } @@ -3140,9 +3336,16 @@ impl Resolver { return None; } + ConstantItemRibKind => { + // Still doesn't deal with upvars + self.session.span_err(span, + ~"attempt to use a non-constant \ + value in a constant"); + + } } - rib_index += 1u; + rib_index += 1; } return Some(dl_def(def)); @@ -3156,8 +3359,8 @@ impl Resolver { // XXX: Try caching? let mut i = (*ribs).len(); - while i != 0u { - i -= 1u; + while i != 0 { + i -= 1; let rib = (*ribs).get_elt(i); match rib.bindings.find(name) { Some(def_like) => { @@ -3205,7 +3408,33 @@ impl Resolver { } match item.node { - item_enum(_, type_parameters) | + + // enum item: resolve all the variants' discrs, + // then resolve the ty params + item_enum(enum_def, type_parameters) => { + + for enum_def.variants.each() |variant| { + do variant.node.disr_expr.iter() |dis_expr| { + // resolve the discriminator expr + // as a constant + self.with_constant_rib(|| { + self.resolve_expr(*dis_expr, visitor); + }); + } + } + + // n.b. the discr expr gets visted twice. + // but maybe it's okay since the first time will signal an + // error if there is one? -- tjc + do self.with_type_parameter_rib + (HasTypeParameters(&type_parameters, item.id, 0, + NormalRibKind)) + || { + + visit_item(item, (), visitor); + } + } + item_ty(_, type_parameters) => { do self.with_type_parameter_rib (HasTypeParameters(&type_parameters, item.id, 0u, @@ -3306,7 +3535,6 @@ impl Resolver { struct_def.traits, struct_def.fields, struct_def.methods, - struct_def.ctor, struct_def.dtor, visitor); } @@ -3371,7 +3599,9 @@ impl Resolver { } item_const(*) => { - visit_item(item, (), visitor); + self.with_constant_rib(|| { + visit_item(item, (), visitor); + }); } item_mac(*) => { @@ -3428,6 +3658,12 @@ impl Resolver { f(); (*self.label_ribs).pop(); } + fn with_constant_rib(f: fn()) { + (*self.value_ribs).push(@Rib(ConstantItemRibKind)); + f(); + (*self.value_ribs).pop(); + } + fn resolve_function(rib_kind: RibKind, optional_declaration: Option<@fn_decl>, @@ -3436,7 +3672,6 @@ impl Resolver { self_binding: SelfBinding, capture_clause: CaptureClause, visitor: ResolveVisitor) { - // Check each element of the capture clause. match capture_clause { NoCaptureClause => { @@ -3528,17 +3763,9 @@ impl Resolver { fn resolve_type_parameters(type_parameters: ~[ty_param], visitor: ResolveVisitor) { - for type_parameters.each |type_parameter| { for type_parameter.bounds.each |bound| { - match *bound { - bound_copy | bound_send | bound_const | bound_owned => { - // Nothing to do. - } - bound_trait(trait_type) => { - self.resolve_type(trait_type, visitor); - } - } + self.resolve_type(**bound, visitor); } } } @@ -3548,16 +3775,14 @@ impl Resolver { traits: ~[@trait_ref], fields: ~[@struct_field], methods: ~[@method], - optional_constructor: Option<class_ctor>, optional_destructor: Option<class_dtor>, visitor: ResolveVisitor) { - // If applicable, create a rib for the type parameters. let outer_type_parameter_count = (*type_parameters).len(); let borrowed_type_parameters: &~[ty_param] = &*type_parameters; do self.with_type_parameter_rib(HasTypeParameters - (borrowed_type_parameters, id, 0u, - NormalRibKind)) { + (borrowed_type_parameters, id, 0, + OpaqueFunctionRibKind)) { // Resolve the type parameters. self.resolve_type_parameters(*type_parameters, visitor); @@ -3600,23 +3825,6 @@ impl Resolver { self.resolve_type(field.node.ty, visitor); } - // Resolve the constructor, if applicable. - match optional_constructor { - None => { - // Nothing to do. - } - Some(constructor) => { - self.resolve_function(NormalRibKind, - Some(@constructor.node.dec), - NoTypeParameters, - constructor.node.body, - HasSelfBinding(constructor.node. - self_id), - NoCaptureClause, - visitor); - } - } - // Resolve the destructor, if applicable. match optional_destructor { None => { @@ -3667,26 +3875,24 @@ impl Resolver { span: span, type_parameters: ~[ty_param], opt_trait_reference: Option<@trait_ref>, - self_type: @ty, + self_type: @Ty, methods: ~[@method], visitor: ResolveVisitor) { - // If applicable, create a rib for the type parameters. let outer_type_parameter_count = type_parameters.len(); let borrowed_type_parameters: &~[ty_param] = &type_parameters; do self.with_type_parameter_rib(HasTypeParameters (borrowed_type_parameters, id, 0u, NormalRibKind)) { - // Resolve the type parameters. self.resolve_type_parameters(type_parameters, visitor); // Resolve the trait reference, if necessary. let original_trait_refs = self.current_trait_refs; match opt_trait_reference { - Some(trait_reference) => { - let new_trait_refs = @DVec(); - match self.resolve_path( + Some(trait_reference) => { + let new_trait_refs = @DVec(); + match self.resolve_path( trait_reference.path, TypeNS, true, visitor) { None => { self.session.span_err(span, @@ -3700,10 +3906,10 @@ impl Resolver { (*new_trait_refs).push(def_id_of_def(def)); } } - // Record the current set of trait references. - self.current_trait_refs = Some(new_trait_refs); - } - None => () + // Record the current set of trait references. + self.current_trait_refs = Some(new_trait_refs); + } + None => () } // Resolve the self type. @@ -3865,7 +4071,7 @@ impl Resolver { debug!("(resolving block) leaving block"); } - fn resolve_type(ty: @ty, visitor: ResolveVisitor) { + fn resolve_type(ty: @Ty, visitor: ResolveVisitor) { match ty.node { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. @@ -3873,42 +4079,45 @@ impl Resolver { ty_path(path, path_id) => { // This is a path in the type namespace. Walk through scopes // scopes looking for it. + let mut result_def = None; - let mut result_def; - match self.resolve_path(path, TypeNS, true, visitor) { - Some(def) => { - debug!("(resolving type) resolved `%s` to type", - self.session.str_of(path.idents.last())); - result_def = Some(def); - } - None => { - result_def = None; + // First, check to see whether the name is a primitive type. + if path.idents.len() == 1 { + let name = path.idents.last(); + + match self.primitive_type_table + .primitive_types + .find(name) { + + Some(primitive_type) => { + result_def = + Some(def_prim_ty(primitive_type)); + } + None => { + // Continue. + } } } match result_def { - Some(_) => { - // Continue. - } None => { - // Check to see whether the name is a primitive type. - if path.idents.len() == 1u { - let name = path.idents.last(); - - match self.primitive_type_table - .primitive_types - .find(name) { - - Some(primitive_type) => { - result_def = - Some(def_prim_ty(primitive_type)); - } - None => { - // Continue. - } + match self.resolve_path(path, TypeNS, true, visitor) { + Some(def) => { + debug!("(resolving type) resolved `%s` to \ + type %?", + self.session.str_of( + path.idents.last()), + def); + result_def = Some(def); + } + None => { + result_def = None; } } } + Some(_) => { + // Continue. + } } match copy result_def { @@ -4089,9 +4298,7 @@ impl Resolver { match self.resolve_path(path, TypeNS, false, visitor) { Some(def_ty(class_id)) if self.structs.contains_key(class_id) => { - let has_constructor = self.structs.get(class_id); - let class_def = def_class(class_id, - has_constructor); + let class_def = def_class(class_id); self.record_def(pattern.id, class_def); } Some(definition @ def_variant(_, variant_id)) @@ -4174,7 +4381,7 @@ impl Resolver { namespace); } - if path.idents.len() > 1u { + if path.idents.len() > 1 { return self.resolve_module_relative_path(path, self.xray_context, namespace); @@ -4226,12 +4433,17 @@ impl Resolver { // First, search children. match containing_module.children.find(name) { Some(child_name_bindings) => { - match (*child_name_bindings).def_for_namespace(namespace) { - Some(def) if def.privacy == Public || xray == Xray => { + match (child_name_bindings.def_for_namespace(namespace), + child_name_bindings.privacy_for_namespace(namespace)) { + (Some(def), Some(Public)) => { + // Found it. Stop the search here. + return ChildNameDefinition(def); + } + (Some(def), _) if xray == Xray => { // Found it. Stop the search here. - return ChildNameDefinition(def.def); + return ChildNameDefinition(def); } - Some(_) | None => { + (Some(_), _) | (None, _) => { // Continue. } } @@ -4247,14 +4459,15 @@ impl Resolver { xray == Xray => { match (*import_resolution).target_for_namespace(namespace) { Some(target) => { - match (*target.bindings) - .def_for_namespace(namespace) { - Some(def) if def.privacy == Public => { + match (target.bindings.def_for_namespace(namespace), + target.bindings.privacy_for_namespace( + namespace)) { + (Some(def), Some(Public)) => { // Found it. import_resolution.used = true; - return ImportNameDefinition(def.def); + return ImportNameDefinition(def); } - Some(_) | None => { + (Some(_), _) | (None, _) => { // This can happen with external impls, due to // the imperfect way we read the metadata. @@ -4394,9 +4607,6 @@ impl Resolver { search_result = self.search_ribs(self.type_ribs, ident, span, AllowCapturingSelf); } - ModuleNS => { - fail ~"module namespaces do not have local ribs"; - } } match copy search_result { @@ -4416,23 +4626,22 @@ impl Resolver { fn resolve_item_by_identifier_in_lexical_scope(ident: ident, namespace: Namespace) -> Option<def> { - // Check the items. match self.resolve_item_in_lexical_scope(self.current_module, ident, namespace) { - Success(target) => { match (*target.bindings).def_for_namespace(namespace) { None => { - fail ~"resolved name in a namespace to a set of name \ - bindings with no def for that namespace?!"; + // This can happen if we were looking for a type and + // found a module instead. Modules don't have defs. + return None; } Some(def) => { debug!("(resolving item path in lexical scope) \ resolved `%s` to item", self.session.str_of(ident)); - return Some(def.def); + return Some(def); } } } @@ -4559,10 +4768,9 @@ impl Resolver { // let bar = Bar { ... } // no type parameters match self.resolve_path(path, TypeNS, false, visitor) { - Some(def_ty(class_id)) | Some(def_class(class_id, _)) + Some(def_ty(class_id)) | Some(def_class(class_id)) if self.structs.contains_key(class_id) => { - let has_constructor = self.structs.get(class_id); - let class_def = def_class(class_id, has_constructor); + let class_def = def_class(class_id); self.record_def(expr.id, class_def); } Some(definition @ def_variant(_, class_id)) @@ -4684,6 +4892,9 @@ impl Resolver { } fn search_for_traits_containing_method(name: ident) -> @DVec<def_id> { + debug!("(searching for traits containing method) looking for '%s'", + self.session.str_of(name)); + let found_traits = @DVec(); let mut search_module = self.current_module; loop { @@ -4691,8 +4902,8 @@ impl Resolver { match copy self.current_trait_refs { Some(trait_def_ids) => { for trait_def_ids.each |trait_def_id| { - self.add_trait_info_if_containing_method - (found_traits, *trait_def_id, name); + self.add_trait_info_if_containing_method( + found_traits, *trait_def_id, name); } } None => { @@ -4704,10 +4915,10 @@ impl Resolver { for search_module.children.each |_name, child_name_bindings| { match child_name_bindings.def_for_namespace(TypeNS) { Some(def) => { - match def.def { + match def { def_ty(trait_def_id) => { - self.add_trait_info_if_containing_method - (found_traits, trait_def_id, name); + self.add_trait_info_if_containing_method( + found_traits, trait_def_id, name); } _ => { // Continue. @@ -4731,11 +4942,11 @@ impl Resolver { Some(target) => { match target.bindings.def_for_namespace(TypeNS) { Some(def) => { - match def.def { + match def { def_ty(trait_def_id) => { self. - add_trait_info_if_containing_method - (found_traits, trait_def_id, name); + add_trait_info_if_containing_method( + found_traits, trait_def_id, name); } _ => { // Continue. @@ -4770,6 +4981,12 @@ impl Resolver { trait_def_id: def_id, name: ident) { + debug!("(adding trait info if containing method) trying trait %d:%d \ + for method '%s'", + trait_def_id.crate, + trait_def_id.node, + self.session.str_of(name)); + match self.trait_info.find(trait_def_id) { Some(trait_info) if trait_info.contains_key(name) => { debug!("(adding trait info if containing method) found trait \ @@ -4932,15 +5149,6 @@ impl Resolver { debug!("Import resolutions:"); for module_.import_resolutions.each |name, import_resolution| { - let mut module_repr; - match (*import_resolution).target_for_namespace(ModuleNS) { - None => { module_repr = ~""; } - Some(_) => { - module_repr = ~" module:?"; - // XXX - } - } - let mut value_repr; match (*import_resolution).target_for_namespace(ValueNS) { None => { value_repr = ~""; } @@ -4959,15 +5167,14 @@ impl Resolver { } } - debug!("* %s:%s%s%s", - self.session.str_of(name), - module_repr, value_repr, type_repr); + debug!("* %s:%s%s", self.session.str_of(name), + value_repr, type_repr); } } } /// Entry point to crate resolution. -fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate) +fn resolve_crate(session: Session, lang_items: LanguageItems, crate: @crate) -> { def_map: DefMap, exp_map2: ExportMap2, trait_map: TraitMap } { diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index 73f1e9bd119..6de9ad977c9 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -99,7 +99,6 @@ * */ -use driver::session::session; use lib::llvm::llvm; use lib::llvm::{ValueRef, BasicBlockRef}; use pat_util::*; @@ -354,7 +353,7 @@ fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint, match p.node { ast::pat_enum(_, subpats) => { if opt_eq(tcx, &variant_opt(tcx, p.id), opt) { - Some(option::get_default(&subpats, + Some(option::get_default(subpats, vec::from_elem(variant_size, dummy))) } else { @@ -1202,7 +1201,7 @@ fn trans_alt_inner(scope_cx: block, arm_cxs.push(bcx); } - return controlflow::join_blocks(scope_cx, dvec::unwrap(arm_cxs)); + return controlflow::join_blocks(scope_cx, dvec::unwrap(move arm_cxs)); fn mk_fail(bcx: block, sp: span, msg: ~str, done: @mut Option<BasicBlockRef>) -> BasicBlockRef { diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 95711f8da36..bf66ccbfeb5 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -17,7 +17,7 @@ use libc::{c_uint, c_ulonglong}; use std::{map, time, list}; use std::map::HashMap; use driver::session; -use session::session; +use session::Session; use syntax::attr; use back::{link, abi, upcall}; use syntax::{ast, ast_util, codemap, ast_map}; @@ -206,7 +206,7 @@ fn GEP_enum(bcx: block, llblobptr: ValueRef, enum_id: ast::def_id, assert ix < variant.args.len(); let arg_lltys = vec::map(variant.args, |aty| { - type_of(ccx, ty::subst_tps(ccx.tcx, ty_substs, *aty)) + type_of(ccx, ty::subst_tps(ccx.tcx, ty_substs, None, *aty)) }); let typed_blobptr = PointerCast(bcx, llblobptr, T_ptr(T_struct(arg_lltys))); @@ -267,7 +267,8 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef { debug!("non_gc_box_cast"); add_comment(bcx, ~"non_gc_box_cast"); - assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace); + assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace + || bcx.unreachable); let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val))); PointerCast(bcx, val, non_gc_t) } @@ -385,16 +386,16 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, let _icx = ccx.insn_ctxt("trans_res_dtor"); if (substs.is_not_empty()) { let did = if did.crate != ast::local_crate { - inline::maybe_instantiate_inline(ccx, did) + inline::maybe_instantiate_inline(ccx, did, true) } else { did }; assert did.crate == ast::local_crate; - monomorphize::monomorphic_fn(ccx, did, substs, None, None).val + monomorphize::monomorphic_fn(ccx, did, substs, None, None, None).val } else if did.crate == ast::local_crate { get_item_val(ccx, did.node) } else { let tcx = ccx.tcx; let name = csearch::get_symbol(ccx.sess.cstore, did); - let class_ty = ty::subst_tps(tcx, substs, + let class_ty = ty::subst_tps(tcx, substs, None, ty::lookup_item_type(tcx, parent_id).ty); let llty = type_of_dtor(ccx, class_ty); get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv, @@ -529,7 +530,8 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, let v_id = variant.id; for vec::each(fn_ty.sig.inputs) |a| { let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j); - let ty_subst = ty::subst_tps(ccx.tcx, tps, a.ty); + // XXX: Is "None" right here? + let ty_subst = ty::subst_tps(ccx.tcx, tps, None, a.ty); cx = f(cx, llfldp_a, ty_subst); j += 1u; } @@ -632,7 +634,7 @@ fn cast_shift_rhs(op: ast::binop, if lhs_sz < rhs_sz { trunc(rhs, lhs_llty) } else if lhs_sz > rhs_sz { - // FIXME (See discussion at #1570): If shifting by negative + // FIXME (#1877: If shifting by negative // values becomes not undefined then this is wrong. zext(rhs, lhs_llty) } else { @@ -1049,7 +1051,7 @@ fn new_block(cx: fn_ctxt, parent: Option<block>, +kind: block_kind, } fn simple_block_scope() -> block_kind { - block_scope({loop_break: None, mut cleanups: ~[], + block_scope({loop_break: None, loop_label: None, mut cleanups: ~[], mut cleanup_paths: ~[], mut landing_pad: None}) } @@ -1066,10 +1068,11 @@ fn scope_block(bcx: block, n, opt_node_info); } -fn loop_scope_block(bcx: block, loop_break: block, n: ~str, - opt_node_info: Option<node_info>) -> block { +fn loop_scope_block(bcx: block, loop_break: block, loop_label: Option<ident>, + n: ~str, opt_node_info: Option<node_info>) -> block { return new_block(bcx.fcx, Some(bcx), block_scope({ loop_break: Some(loop_break), + loop_label: loop_label, mut cleanups: ~[], mut cleanup_paths: ~[], mut landing_pad: None @@ -1392,8 +1395,11 @@ fn mk_standard_basic_blocks(llfn: ValueRef) -> // - create_llargs_for_fn_args. // - new_fn_ctxt // - trans_args -fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path, - llfndecl: ValueRef, id: ast::node_id, +fn new_fn_ctxt_w_id(ccx: @crate_ctxt, + path: path, + llfndecl: ValueRef, + id: ast::node_id, + impl_id: Option<ast::def_id>, param_substs: Option<param_substs>, sp: Option<span>) -> fn_ctxt { let llbbs = mk_standard_basic_blocks(llfndecl); @@ -1410,6 +1416,7 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path, lllocals: HashMap(), llupvars: HashMap(), id: id, + impl_id: impl_id, param_substs: param_substs, span: sp, path: path, @@ -1418,7 +1425,7 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path, fn new_fn_ctxt(ccx: @crate_ctxt, path: path, llfndecl: ValueRef, sp: Option<span>) -> fn_ctxt { - return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, sp); + return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp); } // NB: must keep 4 fns in sync: @@ -1561,6 +1568,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, ty_self: self_arg, param_substs: Option<param_substs>, id: ast::node_id, + impl_id: Option<ast::def_id>, maybe_load_env: fn(fn_ctxt), finish: fn(block)) { ccx.stats.n_closures += 1; @@ -1568,7 +1576,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, set_uwtable(llfndecl); // Set up arguments to the function. - let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, param_substs, + let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs, Some(body.span)); let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs); @@ -1596,18 +1604,14 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). - - if !ccx.class_ctors.contains_key(id) // hack -- - /* avoids the need for special cases to assign a type to - the constructor body (since it has no explicit return) */ - && - (body.node.expr.is_none() || - ty::type_is_bot(block_ty) || - ty::type_is_nil(block_ty)) { + if body.node.expr.is_none() || ty::type_is_bot(block_ty) || + ty::type_is_nil(block_ty) + { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr)); } + finish(bcx); cleanup_and_Br(bcx, bcx_top, fcx.llreturn); @@ -1624,14 +1628,15 @@ fn trans_fn(ccx: @crate_ctxt, llfndecl: ValueRef, ty_self: self_arg, param_substs: Option<param_substs>, - id: ast::node_id) { + id: ast::node_id, + impl_id: Option<ast::def_id>) { let do_time = ccx.sess.trans_stats(); let start = if do_time { time::get_time() } else { {sec: 0i64, nsec: 0i32} }; let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; trans_closure(ccx, path, decl, body, llfndecl, ty_self, - param_substs, id, + param_substs, id, impl_id, |fcx| { if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); @@ -1658,7 +1663,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, ty: varg.ty, ident: special_idents::arg, id: varg.id}); - let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, + let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None, param_substs, None); let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); let ty_param_substs = match param_substs { @@ -1698,60 +1703,6 @@ fn trans_enum_variant(ccx: @crate_ctxt, finish_fn(fcx, lltop); } -fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, - body: ast::blk, llctor_decl: ValueRef, - psubsts: param_substs, ctor_id: ast::node_id, - parent_id: ast::def_id, sp: span) { - // Add ctor to the ctor map - ccx.class_ctors.insert(ctor_id, parent_id); - - // Translate the ctor - - // Set up the type for the result of the ctor - // kludgy -- this wouldn't be necessary if the typechecker - // special-cased constructors, then we could just look up - // the ctor's return type. - let rslt_ty = ty::mk_class(ccx.tcx, parent_id, - dummy_substs(psubsts.tys)); - - // Make the fn context - let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, - Some(psubsts), Some(sp)); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, decl.inputs); - let mut bcx_top = top_scope_block(fcx, body.info()); - let lltop = bcx_top.llbb; - let arg_tys = ty::ty_fn_args(node_id_type(bcx_top, ctor_id)); - bcx_top = copy_args_to_allocas(fcx, bcx_top, decl.inputs, - raw_llargs, arg_tys); - - // Create a temporary for `self` that we will return at the end - let selfdatum = datum::scratch_datum(bcx_top, rslt_ty, true); - - // Initialize dtor flag (if any) to 1 - if ty::ty_dtor(bcx_top.tcx(), parent_id).is_some() { - let flag = GEPi(bcx_top, selfdatum.val, [0, 1]); - Store(bcx_top, C_u8(1), flag); - } - - // initialize fields to zero - let mut bcx = bcx_top; - - // note we don't want to take *or* drop self. - fcx.llself = Some(ValSelfData {v: selfdatum.val, - t: rslt_ty, - is_owned: false}); - - // Translate the body of the ctor - bcx = controlflow::trans_block(bcx, body, expr::Ignore); - - // Generate the return expression - bcx = selfdatum.move_to(bcx, datum::INIT, fcx.llretptr); - - cleanup_and_leave(bcx, None, Some(fcx.llreturn)); - Unreachable(bcx); - finish_fn(fcx, lltop); -} - fn trans_class_dtor(ccx: @crate_ctxt, path: path, body: ast::blk, dtor_id: ast::node_id, psubsts: Option<param_substs>, @@ -1762,7 +1713,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path, let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty; /* Substitute in the class type if necessary */ do option::iter(&psubsts) |ss| { - class_ty = ty::subst_tps(tcx, ss.tys, class_ty); + class_ty = ty::subst_tps(tcx, ss.tys, ss.self_ty, class_ty); } /* The dtor takes a (null) output pointer, and a self argument, @@ -1782,7 +1733,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path, } /* Translate the dtor body */ trans_fn(ccx, path, ast_util::dtor_dec(), - body, lldecl, impl_self(class_ty), psubsts, dtor_id); + body, lldecl, impl_self(class_ty), psubsts, dtor_id, None); lldecl } @@ -1835,7 +1786,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, vec::append(*path, ~[path_name(item.ident)]), - decl, body, llfndecl, no_self, None, item.id); + decl, body, llfndecl, no_self, None, item.id, None); } else { for vec::each(body.node.stmts) |stmt| { match stmt.node { @@ -1847,48 +1798,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { } } } - ast::item_impl(tps, trait_refs, self_ast_ty, ms) => { - meth::trans_impl(ccx, *path, item.ident, ms, tps, None); - - // Translate any methods that have provided implementations. - for trait_refs.each |trait_ref_ptr| { - let trait_def = ccx.tcx.def_map.get(trait_ref_ptr.ref_id); - - // XXX: Cross-crate default methods. - let trait_id = def_id_of_def(trait_def); - if trait_id.crate != ast::local_crate { - loop; - } - - // Get the self type. - let self_ty; - match ccx.tcx.ast_ty_to_ty_cache.get(self_ast_ty) { - ty::atttce_resolved(self_type) => self_ty = self_type, - ty::atttce_unresolved => { - ccx.tcx.sess.impossible_case(item.span, - ~"didn't cache self ast ty"); - } - } - - match ccx.tcx.items.get(trait_id.node) { - ast_map::node_item(trait_item, _) => { - match trait_item.node { - ast::item_trait(tps, _, trait_methods) => { - trans_trait(ccx, tps, trait_methods, path, - item.ident, self_ty); - } - _ => { - ccx.tcx.sess.impossible_case(item.span, - ~"trait item not a \ - trait"); - } - } - } - _ => { - ccx.tcx.sess.impossible_case(item.span, ~"no trait item"); - } - } - } + ast::item_impl(tps, _, _, ms) => { + meth::trans_impl(ccx, *path, item.ident, ms, tps, None, item.id); } ast::item_mod(m) => { trans_mod(ccx, m); @@ -1921,14 +1832,6 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, tps: ~[ast::ty_param], path: @ast_map::path, ident: ast::ident, id: ast::node_id) { if tps.len() == 0u { - let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), - vtables: None, - bounds: @~[]}; - do option::iter(&struct_def.ctor) |ctor| { - trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, - get_item_val(ccx, ctor.node.id), psubsts, - ctor.node.id, local_def(id), ctor.span); - } do option::iter(&struct_def.dtor) |dtor| { trans_class_dtor(ccx, *path, dtor.node.body, dtor.node.id, None, None, local_def(id)); @@ -1937,16 +1840,7 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, // If there are ty params, the ctor will get monomorphized // Translate methods - meth::trans_impl(ccx, *path, ident, struct_def.methods, tps, None); -} - -fn trans_trait(ccx: @crate_ctxt, tps: ~[ast::ty_param], - trait_methods: ~[ast::trait_method], - path: @ast_map::path, ident: ast::ident, - self_ty: ty::t) { - // Translate any methods that have provided implementations - let (_, provided_methods) = ast_util::split_trait_methods(trait_methods); - meth::trans_impl(ccx, *path, ident, provided_methods, tps, Some(self_ty)); + meth::trans_impl(ccx, *path, ident, struct_def.methods, tps, None, id); } // Translate a module. Doing this amounts to translating the items in the @@ -2101,7 +1995,7 @@ fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id, // this to item_symbols match substs { Some(ss) => { - let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, t); + let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, ss.self_ty, t); mangle_exported_name( ccx, vec::append(path, @@ -2184,10 +2078,6 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } } } - ast_map::node_ctor(nm, _, ctor, _, pt) => { - let my_path = vec::append(*pt, ~[path_name(nm)]); - register_fn(ccx, ctor.span, my_path, ctor.node.id) - } ast_map::node_dtor(_, dt, parent_id, pt) => { /* Don't just call register_fn, since we don't want to add @@ -2489,7 +2379,7 @@ fn create_module_map(ccx: @crate_ctxt) -> ValueRef { } -fn decl_crate_map(sess: session::session, mapmeta: link_meta, +fn decl_crate_map(sess: session::Session, mapmeta: link_meta, llmod: ModuleRef) -> ValueRef { let targ_cfg = sess.targ_cfg; let int_type = T_int(targ_cfg); @@ -2594,7 +2484,7 @@ fn write_abi_version(ccx: @crate_ctxt) { false); } -fn trans_crate(sess: session::session, +fn trans_crate(sess: session::Session, crate: @ast::crate, tcx: ty::ctxt, output: &Path, @@ -2712,7 +2602,6 @@ fn trans_crate(sess: session::session, crate_map: crate_map, mut uses_gc: false, dbg_cx: dbg_cx, - class_ctors: HashMap(), mut do_not_commit_warning_issued: false}; diff --git a/src/rustc/middle/trans/build.rs b/src/rustc/middle/trans/build.rs index 69de8a2cca3..ea992600ae1 100644 --- a/src/rustc/middle/trans/build.rs +++ b/src/rustc/middle/trans/build.rs @@ -6,7 +6,6 @@ use codemap::span; use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef}; use lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False, CallConv, TypeKind, AtomicBinOp, AtomicOrdering}; -use driver::session::session; use common::*; fn B(cx: block) -> BuilderRef { @@ -434,8 +433,7 @@ fn GEP(cx: block, Pointer: ValueRef, Indices: ~[ValueRef]) -> ValueRef { // // XXX: Use a small-vector optimization to avoid allocations here. fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef { - let mut v: ~[ValueRef] = ~[]; - for vec::each(ixs) |i| { v.push(C_i32(*i as i32)); } + let v = do vec::map(ixs) |i| { C_i32(*i as i32) }; count_insn(cx, "gepi"); return InBoundsGEP(cx, base, v); } diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs index c851c5bc725..175381a7bd1 100644 --- a/src/rustc/middle/trans/callee.rs +++ b/src/rustc/middle/trans/callee.rs @@ -75,11 +75,12 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee { fn trans_def(bcx: block, def: ast::def, ref_expr: @ast::expr) -> Callee { match def { - ast::def_fn(did, _) => { + ast::def_fn(did, _) | ast::def_static_method(did, None, _) => { fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id)) } - ast::def_static_method(did, _) => { - fn_callee(bcx, meth::trans_static_method_callee(bcx, did, + ast::def_static_method(impl_did, Some(trait_did), _) => { + fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did, + trait_did, ref_expr.id)) } ast::def_variant(tid, vid) => { @@ -183,21 +184,31 @@ fn trans_fn_ref_with_vtables( // Polytype of the function item (may have type params) let fn_tpt = ty::lookup_item_type(tcx, def_id); + // Modify the def_id if this is a default method; we want to be + // monomorphizing the trait's code. + let (def_id, opt_impl_did) = + match tcx.provided_method_sources.find(def_id) { + None => (def_id, None), + Some(source) => (source.method_id, Some(source.impl_id)) + }; + // Check whether this fn has an inlined copy and, if so, redirect // def_id to the local id of the inlined copy. let def_id = { if def_id.crate != ast::local_crate { - inline::maybe_instantiate_inline(ccx, def_id) + let may_translate = opt_impl_did.is_none(); + inline::maybe_instantiate_inline(ccx, def_id, may_translate) } else { def_id } }; - // We must monomorphise if the fn has type parameters or is a rust - // intrinsic. In particular, if we see an intrinsic that is - // inlined from a different crate, we want to reemit the intrinsic - // instead of trying to call it in the other crate. - let must_monomorphise = type_params.len() > 0 || { + // We must monomorphise if the fn has type parameters, is a rust + // intrinsic, or is a default method. In particular, if we see an + // intrinsic that is inlined from a different crate, we want to reemit the + // intrinsic instead of trying to call it in the other crate. + let must_monomorphise = type_params.len() > 0 || + opt_impl_did.is_some() || { if def_id.crate == ast::local_crate { let map_node = session::expect( ccx.sess, @@ -221,7 +232,7 @@ fn trans_fn_ref_with_vtables( let mut {val, must_cast} = monomorphize::monomorphic_fn(ccx, def_id, type_params, - vtables, Some(ref_id)); + vtables, opt_impl_did, Some(ref_id)); if must_cast && ref_id != 0 { // Monotype of the REFERENCE to the function (type params // are subst'd) @@ -316,7 +327,9 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block, match callee.data { Fn(fn_data) => { let substituted = ty::subst_tps(callee.bcx.tcx(), - type_params, fty); + type_params, + None, + fty); let mut llfnty = type_of::type_of(callee.bcx.ccx(), substituted); llfnty = T_ptr(struct_elt(llfnty, 0)); diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 1ab25a18329..3997076f987 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -244,7 +244,6 @@ fn store_environment(bcx: block, fn build_closure(bcx0: block, cap_vars: ~[capture::capture_var], ck: ty::closure_kind, - id: ast::node_id, include_ret_handle: Option<ValueRef>) -> closure_result { let _icx = bcx0.insn_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call @@ -255,7 +254,7 @@ fn build_closure(bcx0: block, let mut env_vals = ~[]; for vec::each(cap_vars) |cap_var| { debug!("Building closure: captured variable %?", *cap_var); - let datum = expr::trans_local_var(bcx, id, cap_var.def); + let datum = expr::trans_local_var(bcx, cap_var.def); match cap_var.mode { capture::cap_ref => { assert ck == ty::ck_block; @@ -370,10 +369,10 @@ fn trans_expr_fn(bcx: block, let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto, cap_clause); let ret_handle = match is_loop_body { Some(x) => x, None => None }; - let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, id, + let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, ret_handle); trans_closure(ccx, sub_path, decl, body, llfn, no_self, - bcx.fcx.param_substs, id, |fcx| { + bcx.fcx.param_substs, id, None, |fcx| { load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), ck); }, |bcx| { @@ -396,7 +395,7 @@ fn trans_expr_fn(bcx: block, } ty::proto_bare => { trans_closure(ccx, sub_path, decl, body, llfn, no_self, None, - id, |_fcx| { }, |_bcx| { }); + id, None, |_fcx| { }, |_bcx| { }); rslt(bcx, C_null(T_opaque_box_ptr(ccx))) } ty::proto_vstore(ty::vstore_fixed(_)) => { diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 68e957bfe70..7f234349d71 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -8,7 +8,7 @@ use vec::raw::to_ptr; use std::map::{HashMap,Set}; use syntax::{ast, ast_map}; use driver::session; -use session::session; +use session::Session; use middle::ty; use back::{link, abi, upcall}; use syntax::codemap::span; @@ -110,7 +110,7 @@ fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res { // Crate context. Every crate we compile has one of these. type crate_ctxt = { - sess: session::session, + sess: session::Session, llmod: ModuleRef, td: target_data, tn: type_names, @@ -170,11 +170,6 @@ type crate_ctxt = { // is not emitted by LLVM's GC pass when no functions use GC. mut uses_gc: bool, dbg_cx: Option<debuginfo::debug_ctxt>, - // Mapping from class constructors to parent class -- - // used in base::trans_closure - // parent_class must be a def_id because ctors can be - // inlined, so the parent may be in a different crate - class_ctors: HashMap<ast::node_id, ast::def_id>, mut do_not_commit_warning_issued: bool}; // Types used for llself. @@ -186,9 +181,12 @@ struct ValSelfData { enum local_val { local_mem(ValueRef), local_imm(ValueRef), } +// Here `self_ty` is the real type of the self parameter to this method. It +// will only be set in the case of default methods. type param_substs = {tys: ~[ty::t], vtables: Option<typeck::vtable_res>, - bounds: @~[ty::param_bounds]}; + bounds: @~[ty::param_bounds], + self_ty: Option<ty::t>}; fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str { fmt!("param_substs {tys:%?, vtables:%?, bounds:%?}", @@ -225,6 +223,10 @@ type fn_ctxt = @{ mut llreturn: BasicBlockRef, // The 'self' value currently in use in this function, if there // is one. + // + // NB: This is the type of the self *variable*, not the self *type*. The + // self type is set only for default methods, while the self variable is + // set for all methods. mut llself: Option<ValSelfData>, // The a value alloca'd for calls to upcalls.rust_personality. Used when // outputting the resume instruction. @@ -245,6 +247,9 @@ type fn_ctxt = @{ // a user-defined function. id: ast::node_id, + // The def_id of the impl we're inside, or None if we aren't inside one. + impl_id: Option<ast::def_id>, + // If this function is being monomorphized, this contains the type // substitutions used. param_substs: Option<param_substs>, @@ -440,6 +445,7 @@ enum block_kind { type scope_info = { loop_break: Option<block>, + loop_label: Option<ident>, // A list of functions that must be run at when leaving this // block, cleaning up any variables that were introduced in the // block. @@ -516,7 +522,7 @@ fn block_(llbb: BasicBlockRef, parent: Option<block>, -kind: block_kind, terminated: false, unreachable: false, parent: parent, - kind: kind, + kind: move kind, is_lpad: is_lpad, node_info: node_info, fcx: fcx @@ -600,7 +606,7 @@ fn block_parent(cx: block) -> block { impl block { pure fn ccx() -> @crate_ctxt { self.fcx.ccx } pure fn tcx() -> ty::ctxt { self.fcx.ccx.tcx } - pure fn sess() -> session { self.fcx.ccx.sess } + pure fn sess() -> Session { self.fcx.ccx.sess } fn node_id_to_str(id: ast::node_id) -> ~str { ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr()) @@ -1115,7 +1121,11 @@ enum mono_param_id { datum::DatumMode), } -type mono_id_ = {def: ast::def_id, params: ~[mono_param_id]}; +type mono_id_ = { + def: ast::def_id, + params: ~[mono_param_id], + impl_did_opt: Option<ast::def_id> +}; type mono_id = @mono_id_; @@ -1182,7 +1192,7 @@ fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef { return build::And(cx, bumped, build::Not(cx, mask)); } -fn path_str(sess: session::session, p: path) -> ~str { +fn path_str(sess: session::Session, p: path) -> ~str { let mut r = ~"", first = true; for vec::each(p) |e| { match *e { @@ -1198,7 +1208,9 @@ fn path_str(sess: session::session, p: path) -> ~str { fn monomorphize_type(bcx: block, t: ty::t) -> ty::t { match bcx.fcx.param_substs { - Some(substs) => ty::subst_tps(bcx.tcx(), substs.tys, t), + Some(substs) => { + ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t) + } _ => { assert !ty::type_has_params(t); t } } } @@ -1218,7 +1230,9 @@ fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] { let params = ty::node_id_to_type_params(tcx, id); match bcx.fcx.param_substs { Some(substs) => { - vec::map(params, |t| ty::subst_tps(tcx, substs.tys, *t)) + do vec::map(params) |t| { + ty::subst_tps(tcx, substs.tys, substs.self_ty, *t) + } } _ => params } @@ -1246,7 +1260,9 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin) typeck::vtable_static(trait_id, tys, sub) => { let tys = match fcx.param_substs { Some(substs) => { - vec::map(tys, |t| ty::subst_tps(tcx, substs.tys, *t)) + do vec::map(tys) |t| { + ty::subst_tps(tcx, substs.tys, substs.self_ty, *t) + } } _ => tys }; @@ -1295,13 +1311,13 @@ fn dummy_substs(tps: ~[ty::t]) -> ty::substs { tps: tps} } -fn struct_field(index: uint) -> [uint]/3 { +fn struct_field(index: uint) -> [uint * 3] { //! The GEPi sequence to access a field of a record/struct. [0, 0, index] } -fn struct_dtor() -> [uint]/2 { +fn struct_dtor() -> [uint * 2] { //! The GEPi sequence to access the dtor of a struct. [0, 1] diff --git a/src/rustc/middle/trans/controlflow.rs b/src/rustc/middle/trans/controlflow.rs index ce32cd0a2dd..59a733433bf 100644 --- a/src/rustc/middle/trans/controlflow.rs +++ b/src/rustc/middle/trans/controlflow.rs @@ -113,7 +113,8 @@ fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) // | body_bcx_out --+ // next_bcx - let loop_bcx = loop_scope_block(bcx, next_bcx, ~"`while`", body.info()); + let loop_bcx = loop_scope_block(bcx, next_bcx, None, ~"`while`", + body.info()); let cond_bcx_in = scope_block(loop_bcx, cond.info(), ~"while loop cond"); let body_bcx_in = scope_block(loop_bcx, body.info(), ~"while loop body"); Br(bcx, loop_bcx.llbb); @@ -133,10 +134,11 @@ fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) return next_bcx; } -fn trans_loop(bcx:block, body: ast::blk) -> block { +fn trans_loop(bcx:block, body: ast::blk, opt_label: Option<ident>) -> block { let _icx = bcx.insn_ctxt("trans_loop"); let next_bcx = sub_block(bcx, ~"next"); - let body_bcx_in = loop_scope_block(bcx, next_bcx, ~"`loop`", body.info()); + let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, ~"`loop`", + body.info()); Br(bcx, body_bcx_in.llbb); let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore); cleanup_and_Br(body_bcx_out, body_bcx_in, body_bcx_in.llbb); @@ -201,7 +203,7 @@ fn trans_log(log_ex: @ast::expr, } } -fn trans_break_cont(bcx: block, to_end: bool) +fn trans_break_cont(bcx: block, opt_label: Option<ident>, to_end: bool) -> block { let _icx = bcx.insn_ctxt("trans_break_cont"); // Locate closest loop block, outputting cleanup as we go. @@ -209,13 +211,22 @@ fn trans_break_cont(bcx: block, to_end: bool) let mut target; loop { match unwind.kind { - block_scope({loop_break: Some(brk), _}) => { - target = if to_end { - brk - } else { - unwind - }; - break; + block_scope({loop_break: Some(brk), loop_label: l, _}) => { + // If we're looking for a labeled loop, check the label... + target = if to_end { + brk + } else { + unwind + }; + match opt_label { + Some(desired) => match l { + Some(actual) if actual == desired => break, + // If it doesn't match the one we want, + // don't break + _ => () + }, + None => break + } } _ => () } @@ -235,12 +246,12 @@ fn trans_break_cont(bcx: block, to_end: bool) return bcx; } -fn trans_break(bcx: block) -> block { - return trans_break_cont(bcx, true); +fn trans_break(bcx: block, label_opt: Option<ident>) -> block { + return trans_break_cont(bcx, label_opt, true); } -fn trans_cont(bcx: block) -> block { - return trans_break_cont(bcx, false); +fn trans_cont(bcx: block, label_opt: Option<ident>) -> block { + return trans_break_cont(bcx, label_opt, false); } fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block { diff --git a/src/rustc/middle/trans/datum.rs b/src/rustc/middle/trans/datum.rs index 241fa5e53af..84a3c81a978 100644 --- a/src/rustc/middle/trans/datum.rs +++ b/src/rustc/middle/trans/datum.rs @@ -336,9 +336,6 @@ impl Datum { // This works like copy_val, except that it deinitializes the source. // Since it needs to zero out the source, src also needs to be an lval. // - // FIXME (#839): We always zero out the source. Ideally we would - // detect the case where a variable is always deinitialized by - // block exit and thus doesn't need to be dropped. fn move_to(bcx: block, action: CopyAction, dst: ValueRef) -> block { let _icx = bcx.insn_ctxt("move_to"); let mut bcx = bcx; diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 6cd4b49fa3b..2db0dd59cf9 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -9,7 +9,7 @@ use middle::ty; use syntax::{ast, codemap, ast_util, ast_map}; use syntax::parse::token::ident_interner; use codemap::span; -use ast::ty; +use ast::Ty; use pat_util::*; use util::ppaux::ty_to_str; use driver::session::session; @@ -229,7 +229,7 @@ fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> { return mdval; } -fn line_from_span(cm: codemap::codemap, sp: span) -> uint { +fn line_from_span(cm: codemap::CodeMap, sp: span) -> uint { codemap::lookup_char_pos(cm, sp.lo).line } @@ -469,7 +469,7 @@ fn create_composite_type(type_tag: int, name: ~str, file: ValueRef, line: int, } fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, - vec_ty_span: codemap::span, elem_ty: @ast::ty) + vec_ty_span: codemap::span, elem_ty: @ast::Ty) -> @metadata<tydesc_md> { let fname = filename_from_span(cx, vec_ty_span); let file_node = create_file(cx, fname); @@ -492,7 +492,7 @@ fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, return @{node: llnode, data: {hash: ty::type_id(vec_t)}}; } -fn create_ty(_cx: @crate_ctxt, _t: ty::t, _ty: @ast::ty) +fn create_ty(_cx: @crate_ctxt, _t: ty::t, _ty: @ast::Ty) -> @metadata<tydesc_md> { /*let cache = get_cache(cx); match cached_metadata::<@metadata<tydesc_md>>( @@ -732,10 +732,6 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> { ast_map::node_method(method, _, _) => { (method.ident, method.decl.output, method.id) } - ast_map::node_ctor(nm, _, ctor, _, _) => { - // FIXME: output type may be wrong (#2194) - (nm, ctor.node.dec.output, ctor.node.id) - } ast_map::node_expr(expr) => { match expr.node { ast::expr_fn(_, decl, _, _) => { diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 57439daca2f..b0702c80b39 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -410,16 +410,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { match expr.node { ast::expr_break(label_opt) => { - if label_opt.is_some() { - bcx.tcx().sess.span_unimpl(expr.span, ~"labeled break"); - } - return controlflow::trans_break(bcx); + return controlflow::trans_break(bcx, label_opt); } ast::expr_again(label_opt) => { - if label_opt.is_some() { - bcx.tcx().sess.span_unimpl(expr.span, ~"labeled again"); - } - return controlflow::trans_cont(bcx); + return controlflow::trans_cont(bcx, label_opt); } ast::expr_ret(ex) => { return controlflow::trans_ret(bcx, ex); @@ -436,8 +430,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { ast::expr_while(cond, body) => { return controlflow::trans_while(bcx, cond, body); } - ast::expr_loop(body, _) => { - return controlflow::trans_loop(bcx, body); + ast::expr_loop(body, opt_label) => { + return controlflow::trans_loop(bcx, body, opt_label); } ast::expr_assign(dst, src) => { let src_datum = unpack_datum!(bcx, trans_to_datum(bcx, src)); @@ -637,14 +631,15 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr, }; match def { - ast::def_fn(did, _) => { + ast::def_fn(did, _) | ast::def_static_method(did, None, _) => { let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id); return fn_data_to_datum(bcx, did, fn_data, lldest); } - ast::def_static_method(did, _) => { - let fn_data = meth::trans_static_method_callee(bcx, did, + ast::def_static_method(impl_did, Some(trait_did), _) => { + let fn_data = meth::trans_static_method_callee(bcx, impl_did, + trait_did, ref_expr.id); - return fn_data_to_datum(bcx, did, fn_data, lldest); + return fn_data_to_datum(bcx, impl_did, fn_data, lldest); } ast::def_variant(tid, vid) => { if ty::enum_variant_with_id(ccx.tcx, tid, vid).args.len() > 0u { @@ -747,13 +742,13 @@ fn trans_def_lvalue(bcx: block, ref_expr: @ast::expr, _ => { DatumBlock { bcx: bcx, - datum: trans_local_var(bcx, ref_expr.id, def) + datum: trans_local_var(bcx, def) } } } } -fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { +fn trans_local_var(bcx: block, def: ast::def) -> Datum { let _icx = bcx.insn_ctxt("trans_local_var"); return match def { @@ -775,10 +770,10 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { } } ast::def_arg(nid, _) => { - take_local(bcx, ref_id, bcx.fcx.llargs, nid) + take_local(bcx, bcx.fcx.llargs, nid) } ast::def_local(nid, _) | ast::def_binding(nid, _) => { - take_local(bcx, ref_id, bcx.fcx.lllocals, nid) + take_local(bcx, bcx.fcx.lllocals, nid) } ast::def_self(nid) => { let self_info: ValSelfData = match bcx.fcx.llself { @@ -792,7 +787,9 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { // This cast should not be necessary. We should cast self *once*, // but right now this conflicts with default methods. - let llselfty = T_ptr(type_of::type_of(bcx.ccx(), self_info.t)); + let real_self_ty = monomorphize_type(bcx, self_info.t); + let llselfty = T_ptr(type_of::type_of(bcx.ccx(), real_self_ty)); + let casted_val = PointerCast(bcx, self_info.v, llselfty); Datum { val: casted_val, @@ -808,15 +805,8 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { }; fn take_local(bcx: block, - ref_id: ast::node_id, table: HashMap<ast::node_id, local_val>, nid: ast::node_id) -> Datum { - let is_last_use = match bcx.ccx().maps.last_use_map.find(ref_id) { - None => false, - Some(vars) => (*vars).contains(&nid) - }; - - let source = if is_last_use {FromLastUseLvalue} else {FromLvalue}; let (v, mode) = match table.find(nid) { Some(local_mem(v)) => (v, ByRef), @@ -828,10 +818,10 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { }; let ty = node_id_type(bcx, nid); - debug!("take_local(nid=%?, last_use=%b, v=%s, mode=%?, ty=%s)", - nid, is_last_use, bcx.val_str(v), mode, bcx.ty_to_str(ty)); + debug!("take_local(nid=%?, v=%s, mode=%?, ty=%s)", + nid, bcx.val_str(v), mode, bcx.ty_to_str(ty)); - Datum { val: v, ty: ty, mode: mode, source: source } + Datum { val: v, ty: ty, mode: mode, source: FromLvalue } } } @@ -1465,7 +1455,7 @@ fn trans_assign_op(bcx: block, // A user-defined operator method if bcx.ccx().maps.method_map.find(expr.id).is_some() { - // FIXME(#2582) evaluates the receiver twice!! + // FIXME(#2528) evaluates the receiver twice!! let scratch = scratch_datum(bcx, dst_datum.ty, false); let bcx = trans_overloaded_op(bcx, expr, dst, ~[src], SaveIn(scratch.val), DoAutorefArg); diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 74dadd2cab4..d307fcb5dca 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -1,7 +1,7 @@ // The classification code for the x86_64 ABI is taken from the clay language // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp -use driver::session::{session, arch_x86_64}; +use driver::session::arch_x86_64; use syntax::codemap::span; use libc::c_uint; use syntax::{attr, ast_map}; @@ -112,9 +112,10 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { Float => 4, Double => 8, Struct => { - do vec::foldl(0, struct_tys(ty)) |s, t| { - s + ty_size(*t) - } + let size = do vec::foldl(0, struct_tys(ty)) |s, t| { + align(s, *t) + ty_size(*t) + }; + align(size, ty) } Array => { let len = llvm::LLVMGetArrayLength(ty) as uint; @@ -794,7 +795,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, { debug!("trans_intrinsic(item.ident=%s)", ccx.sess.str_of(item.ident)); - let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, + let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, None, Some(substs), Some(item.span)); let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match ccx.sess.str_of(item.ident) { @@ -909,7 +910,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, let static_ti = get_tydesc(ccx, tp_ty); glue::lazily_emit_all_tydesc_glue(ccx, static_ti); - // FIXME (#2712): change this to T_ptr(ccx.tydesc_ty) when the + // FIXME (#3727): change this to T_ptr(ccx.tydesc_ty) when the // core::sys copy of the get_tydesc interface dies off. let td = PointerCast(bcx, static_ti.tydesc, T_ptr(T_nil())); Store(bcx, td, fcx.llretptr); @@ -1025,7 +1026,7 @@ fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, ))); let llty = type_of_fn_from_ty(ccx, t); let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty); - trans_fn(ccx, path, decl, body, llfndecl, no_self, None, id); + trans_fn(ccx, path, decl, body, llfndecl, no_self, None, id, None); return llfndecl; } diff --git a/src/rustc/middle/trans/glue.rs b/src/rustc/middle/trans/glue.rs index d60a5a0bd7d..af9f2899a54 100644 --- a/src/rustc/middle/trans/glue.rs +++ b/src/rustc/middle/trans/glue.rs @@ -745,7 +745,7 @@ fn emit_tydescs(ccx: @crate_ctxt) { // Index tydesc by addrspace. if ti.addrspace > gc_box_addrspace { let llty = T_ptr(ccx.tydesc_type); - let addrspace_name = #fmt("_gc_addrspace_metadata_%u", + let addrspace_name = fmt!("_gc_addrspace_metadata_%u", ti.addrspace as uint); let addrspace_gvar = str::as_c_str(addrspace_name, |buf| { llvm::LLVMAddGlobal(ccx.llmod, llty, buf) diff --git a/src/rustc/middle/trans/inline.rs b/src/rustc/middle/trans/inline.rs index 76888471bf9..d3cc23094ee 100644 --- a/src/rustc/middle/trans/inline.rs +++ b/src/rustc/middle/trans/inline.rs @@ -5,9 +5,12 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, self_arg, trans_fn, impl_self, get_insn_ctxt}; -fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) - -> ast::def_id -{ +// `translate` will be true if this function is allowed to translate the +// item and false otherwise. Currently, this parameter is set to false when +// translating default methods. +fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, + translate: bool) + -> ast::def_id { let _icx = ccx.insn_ctxt("maybe_instantiate_inline"); match ccx.external.find(fn_id) { Some(Some(node_id)) => { @@ -31,13 +34,9 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); ccx.stats.n_inlines += 1; - trans_item(ccx, *item); + if translate { trans_item(ccx, *item); } local_def(item.id) } - csearch::found(ast::ii_ctor(ctor, _, _, _)) => { - ccx.external.insert(fn_id, Some(ctor.node.id)); - local_def(ctor.node.id) - } csearch::found(ast::ii_foreign(item)) => { ccx.external.insert(fn_id, Some(item.id)); local_def(item.id) @@ -57,7 +56,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) _ => ccx.sess.bug(~"maybe_instantiate_inline: item has a \ non-enum parent") } - trans_item(ccx, *item); + if translate { trans_item(ccx, *item); } local_def(my_id) } csearch::found_parent(_, _) => { @@ -69,13 +68,14 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) ccx.external.insert(fn_id, Some(mth.id)); let {bounds: impl_bnds, region_param: _, ty: impl_ty} = ty::lookup_item_type(ccx.tcx, impl_did); - if (*impl_bnds).len() + mth.tps.len() == 0u { + if translate && (*impl_bnds).len() + mth.tps.len() == 0u { let llfn = get_item_val(ccx, mth.id); let path = vec::append( ty::item_path(ccx.tcx, impl_did), ~[path_name(mth.ident)]); trans_fn(ccx, path, mth.decl, mth.body, - llfn, impl_self(impl_ty), None, mth.id); + llfn, impl_self(impl_ty), None, mth.id, + Some(impl_did)); } local_def(mth.id) } @@ -87,3 +87,4 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) } } } + diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index d8a2fda4d14..20dba35b231 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -28,7 +28,7 @@ see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, methods: ~[@ast::method], tps: ~[ast::ty_param], - self_ty: Option<ty::t>) { + self_ty: Option<ty::t>, id: ast::node_id) { let _icx = ccx.insn_ctxt("impl::trans_impl"); if tps.len() > 0u { return; } let sub_path = vec::append_one(path, path_name(name)); @@ -36,7 +36,22 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, if method.tps.len() == 0u { let llfn = get_item_val(ccx, method.id); let path = vec::append_one(sub_path, path_name(method.ident)); - trans_method(ccx, path, *method, None, self_ty, llfn); + + let param_substs_opt; + match self_ty { + None => param_substs_opt = None, + Some(self_ty) => { + param_substs_opt = Some({ + tys: ~[], + vtables: None, + bounds: @~[], + self_ty: Some(self_ty) + }); + } + } + + trans_method(ccx, path, *method, param_substs_opt, self_ty, llfn, + ast_util::local_def(id)); } } } @@ -54,13 +69,15 @@ Translates a (possibly monomorphized) method body. will be none if this is not a default method and must always be present if this is a default method. - `llfn`: the LLVM ValueRef for the method +- `impl_id`: the node ID of the impl this method is inside */ fn trans_method(ccx: @crate_ctxt, path: path, method: &ast::method, param_substs: Option<param_substs>, base_self_ty: Option<ty::t>, - llfn: ValueRef) { + llfn: ValueRef, + impl_id: ast::def_id) { // figure out how self is being passed let self_arg = match method.self_ty.node { @@ -76,8 +93,10 @@ fn trans_method(ccx: @crate_ctxt, Some(provided_self_ty) => self_ty = provided_self_ty } let self_ty = match param_substs { - None => self_ty, - Some({tys: ref tys, _}) => ty::subst_tps(ccx.tcx, *tys, self_ty) + None => self_ty, + Some({tys: ref tys, _}) => { + ty::subst_tps(ccx.tcx, *tys, None, self_ty) + } }; match method.self_ty.node { ast::sty_value => { @@ -98,15 +117,20 @@ fn trans_method(ccx: @crate_ctxt, llfn, self_arg, param_substs, - method.id); + method.id, + Some(impl_id)); } -fn trans_self_arg(bcx: block, base: @ast::expr, +fn trans_self_arg(bcx: block, + base: @ast::expr, mentry: typeck::method_map_entry) -> Result { let _icx = bcx.insn_ctxt("impl::trans_self_arg"); let mut temp_cleanups = ~[]; + + // Compute the mode and type of self. let self_arg = {mode: mentry.self_arg.mode, ty: monomorphize_type(bcx, mentry.self_arg.ty)}; + let result = trans_arg_expr(bcx, self_arg, base, &mut temp_cleanups, None, DontAutorefArg); @@ -120,11 +144,31 @@ fn trans_self_arg(bcx: block, base: @ast::expr, } fn trans_method_callee(bcx: block, callee_id: ast::node_id, - self: @ast::expr, mentry: typeck::method_map_entry) - -> Callee -{ + self: @ast::expr, mentry: typeck::method_map_entry) -> + Callee { let _icx = bcx.insn_ctxt("impl::trans_method_callee"); - match mentry.origin { + + // Replace method_self with method_static here. + let mut origin = mentry.origin; + match origin { + typeck::method_self(copy trait_id, copy method_index) => { + // Get the ID of the impl we're inside. + let impl_def_id = bcx.fcx.impl_id.get(); + + debug!("impl_def_id is %?", impl_def_id); + + // Get the ID of the method we're calling. + let method_name = + ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident; + let method_id = method_with_name(bcx.ccx(), impl_def_id, + method_name); + origin = typeck::method_static(method_id); + } + typeck::method_static(*) | typeck::method_param(*) | + typeck::method_trait(*) => {} + } + + match origin { typeck::method_static(did) => { let callee_fn = callee::trans_fn_ref(bcx, did, callee_id); let Result {bcx, val} = trans_self_arg(bcx, self, mentry); @@ -155,18 +199,57 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id, trans_trait_callee(bcx, callee_id, off, self, vstore) } typeck::method_self(*) => { - bcx.tcx().sess.span_bug(self.span, ~"self method call"); + fail ~"method_self should have been handled above" } } } fn trans_static_method_callee(bcx: block, method_id: ast::def_id, + trait_id: ast::def_id, callee_id: ast::node_id) -> FnData { let _icx = bcx.insn_ctxt("impl::trans_static_method_callee"); let ccx = bcx.ccx(); + debug!("trans_static_method_callee(method_id=%?, trait_id=%s, \ + callee_id=%?)", + method_id, + ty::item_path_str(bcx.tcx(), trait_id), + callee_id); + let _indenter = indenter(); + + // When we translate a static fn defined in a trait like: + // + // trait<T1...Tn> Trait { + // static fn foo<M1...Mn>(...) {...} + // } + // + // this winds up being translated as something like: + // + // fn foo<T1...Tn,self: Trait<T1...Tn>,M1...Mn>(...) {...} + // + // So when we see a call to this function foo, we have to figure + // out which impl the `Trait<T1...Tn>` bound on the type `self` was + // bound to. Due to the fact that we use a flattened list of + // impls, one per bound, this means we have to total up the bounds + // found on the type parametesr T1...Tn to find the index of the + // one we are interested in. + let bound_index = { + let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id); + let mut index = 0; + for trait_polyty.bounds.each |param_bounds| { + for param_bounds.each |param_bound| { + match *param_bound { + ty::bound_trait(_) => { index += 1; } + ty::bound_copy | ty::bound_owned | + ty::bound_send | ty::bound_const => {} + } + } + } + index + }; + let mname = if method_id.crate == ast::local_crate { match bcx.tcx().items.get(method_id.node) { ast_map::node_trait_method(trait_method, _, _) => { @@ -187,9 +270,7 @@ fn trans_static_method_callee(bcx: block, let vtbls = resolve_vtables_in_fn_ctxt( bcx.fcx, ccx.maps.vtable_map.get(callee_id)); - // FIXME(#3446) -- I am pretty sure index 0 is not the right one, - // if the static method is implemented on a generic type. (NDM) - match vtbls[0] { + match vtbls[bound_index] { typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => { let mth_id = method_with_name(bcx.ccx(), impl_did, mname); @@ -218,7 +299,7 @@ fn trans_static_method_callee(bcx: block, fn method_from_methods(ms: ~[@ast::method], name: ast::ident) -> ast::def_id { - local_def(option::get(&vec::find(ms, |m| m.ident == name)).id) + local_def(option::get(vec::find(ms, |m| m.ident == name)).id) } fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id, @@ -482,13 +563,21 @@ fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id { match origin { typeck::vtable_static(impl_id, substs, sub_vtables) => { monomorphize::make_mono_id( - ccx, impl_id, substs, - if (*sub_vtables).len() == 0u { None } - else { Some(sub_vtables) }, None) + ccx, + impl_id, + substs, + if (*sub_vtables).len() == 0u { + None + } else { + Some(sub_vtables) + }, + None, + None) } typeck::vtable_trait(trait_id, substs) => { @{def: trait_id, - params: vec::map(substs, |t| mono_precise(*t, None))} + params: vec::map(substs, |t| mono_precise(*t, None)), + impl_did_opt: None} } // can't this be checked at the callee? _ => fail ~"vtable_id" @@ -534,7 +623,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t], let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| { - let fty = ty::subst_tps(tcx, substs, ty::mk_fn(tcx, im.fty)); + let fty = ty::subst_tps(tcx, substs, None, ty::mk_fn(tcx, im.fty)); if (*im.tps).len() > 0u || ty::type_has_self(fty) { C_null(T_ptr(T_nil())) } else { @@ -543,10 +632,11 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t], // If the method is in another crate, need to make an inlined // copy first if m_id.crate != ast::local_crate { - m_id = inline::maybe_instantiate_inline(ccx, m_id); + // XXX: Set impl ID here? + m_id = inline::maybe_instantiate_inline(ccx, m_id, true); } monomorphize::monomorphic_fn(ccx, m_id, substs, - Some(vtables), None).val + Some(vtables), None, None).val } else if m_id.crate == ast::local_crate { get_item_val(ccx, m_id.node) } else { diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 17eaf591c9f..c2f106f631b 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -5,7 +5,7 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, no_self, self_arg, trans_fn, impl_self, decl_internal_cdecl_fn, set_inline_hint_if_appr, set_inline_hint, - trans_enum_variant, trans_class_ctor, trans_class_dtor, + trans_enum_variant, trans_class_dtor, get_insn_ctxt}; use syntax::parse::token::special_idents; use type_of::type_of_fn_from_ty; @@ -16,9 +16,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: ~[ty::t], vtables: Option<typeck::vtable_res>, - ref_id: Option<ast::node_id>) - -> {val: ValueRef, must_cast: bool} -{ + impl_did_opt: Option<ast::def_id>, + ref_id: Option<ast::node_id>) -> + {val: ValueRef, must_cast: bool} { let _icx = ccx.insn_ctxt("monomorphic_fn"); let mut must_cast = false; let substs = vec::map(real_substs, |t| { @@ -31,17 +31,18 @@ fn monomorphic_fn(ccx: @crate_ctxt, for real_substs.each() |s| { assert !ty::type_has_params(*s); } for substs.each() |s| { assert !ty::type_has_params(*s); } let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len()); - let hash_id = make_mono_id(ccx, fn_id, substs, vtables, Some(param_uses)); + let hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt, + Some(param_uses)); if vec::any(hash_id.params, |p| match *p { mono_precise(_, _) => false, _ => true }) { must_cast = true; } - #debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \ + debug!("monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \ hash_id = %?", fn_id, ty::item_path_str(ccx.tcx, fn_id), real_substs.map(|s| ty_to_str(ccx.tcx, *s)), - substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id]; + substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id); match ccx.monomorphized.find(hash_id) { Some(val) => { @@ -71,11 +72,13 @@ fn monomorphic_fn(ccx: @crate_ctxt, return {val: get_item_val(ccx, fn_id.node), must_cast: true}; } - ast_map::node_ctor(nm, _, ct, _, pt) => (pt, nm, ct.span), ast_map::node_dtor(_, dtor, _, pt) => (pt, special_idents::dtor, dtor.span), - ast_map::node_trait_method(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a trait method") + ast_map::node_trait_method(@ast::provided(m), _, pt) => { + (pt, m.ident, m.span) + } + ast_map::node_trait_method(@ast::required(_), _, _) => { + ccx.tcx.sess.bug(~"Can't monomorphize a required trait method") } ast_map::node_expr(*) => { ccx.tcx.sess.bug(~"Can't monomorphize an expr") @@ -94,12 +97,23 @@ fn monomorphic_fn(ccx: @crate_ctxt, ccx.tcx.sess.bug(~"Can't monomorphize a local") } }; - let mono_ty = ty::subst_tps(ccx.tcx, substs, llitem_ty); + + // Look up the impl type if we're translating a default method. + // XXX: Generics. + let impl_ty_opt; + match impl_did_opt { + None => impl_ty_opt = None, + Some(impl_did) => { + impl_ty_opt = Some(ty::lookup_item_type(ccx.tcx, impl_did).ty); + } + } + + let mono_ty = ty::subst_tps(ccx.tcx, substs, impl_ty_opt, llitem_ty); let llfty = type_of_fn_from_ty(ccx, mono_ty); ccx.stats.n_monos += 1; - let depth = option::get_default(&ccx.monomorphizing.find(fn_id), 0u); + let depth = option::get_default(ccx.monomorphizing.find(fn_id), 0u); // Random cut-off -- code that needs to instantiate the same function // recursively more than ten times can probably safely be assumed to be // causing an infinite expansion. @@ -119,12 +133,18 @@ fn monomorphic_fn(ccx: @crate_ctxt, lldecl }; - let psubsts = Some({tys: substs, vtables: vtables, bounds: tpt.bounds}); + let psubsts = Some({ + tys: substs, + vtables: vtables, + bounds: tpt.bounds, + self_ty: impl_ty_opt + }); + let lldecl = match map_node { ast_map::node_item(i@@{node: ast::item_fn(decl, _, _, body), _}, _) => { let d = mk_lldecl(); set_inline_hint_if_appr(i.attrs, d); - trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node); + trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None); d } ast_map::node_item(*) => { @@ -138,7 +158,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, } ast_map::node_variant(v, enum_item, _) => { let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id)); - let this_tv = option::get(&vec::find(*tvs, |tv| { + let this_tv = option::get(vec::find(*tvs, |tv| { tv.id.node == fn_id.node})); let d = mk_lldecl(); set_inline_hint(d); @@ -155,21 +175,19 @@ fn monomorphic_fn(ccx: @crate_ctxt, } d } - ast_map::node_method(mth, _, _) => { + ast_map::node_method(mth, supplied_impl_did, _) => { // XXX: What should the self type be here? let d = mk_lldecl(); set_inline_hint_if_appr(mth.attrs, d); - meth::trans_method(ccx, pt, mth, psubsts, None, d); - d - } - ast_map::node_ctor(_, tps, ctor, parent_id, _) => { - // ctors don't have attrs, at least not right now - let d = mk_lldecl(); - let tp_tys = ty::ty_params_to_tys(ccx.tcx, tps); - trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, d, - option::get_default(&psubsts, - {tys:tp_tys, vtables: None, bounds: @~[]}), - fn_id.node, parent_id, ctor.span); + + // Override the impl def ID if necessary. + let impl_did; + match impl_did_opt { + None => impl_did = supplied_impl_did, + Some(override_impl_did) => impl_did = override_impl_did + } + + meth::trans_method(ccx, pt, mth, psubsts, None, d, impl_did); d } ast_map::node_dtor(_, dtor, _, pt) => { @@ -182,6 +200,15 @@ fn monomorphic_fn(ccx: @crate_ctxt, trans_class_dtor(ccx, *pt, dtor.node.body, dtor.node.id, psubsts, Some(hash_id), parent_id) } + ast_map::node_trait_method(@ast::provided(mth), _, pt) => { + let d = mk_lldecl(); + set_inline_hint_if_appr(mth.attrs, d); + debug!("monomorphic_fn impl_did_opt is %?", impl_did_opt); + meth::trans_method(ccx, *pt, mth, psubsts, None, d, + impl_did_opt.get()); + d + } + // Ugh -- but this ensures any new variants won't be forgotten ast_map::node_expr(*) | ast_map::node_stmt(*) | @@ -237,6 +264,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> { fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], vtables: Option<typeck::vtable_res>, + impl_did_opt: Option<ast::def_id>, param_uses: Option<~[type_use::type_uses]>) -> mono_id { let precise_param_ids = match vtables { Some(vts) => { @@ -306,5 +334,5 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], }) } }; - @{def: item, params: param_ids} + @{def: item, params: param_ids, impl_did_opt: impl_did_opt} } diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index 3c4439c918f..a99ef96b254 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -59,10 +59,6 @@ fn traverse_def_id(cx: ctx, did: def_id) { cx.rmap.insert(item.id, ()); } ast_map::node_variant(v, _, _) => { cx.rmap.insert(v.node.id, ()); } - // If it's a ctor, consider the parent reachable - ast_map::node_ctor(_, _, _, parent_id, _) => { - traverse_def_id(cx, parent_id); - } _ => () } } @@ -104,13 +100,6 @@ fn traverse_public_item(cx: ctx, item: @item) { } } item_class(struct_def, tps) => { - do option::iter(&struct_def.ctor) |ctor| { - cx.rmap.insert(ctor.node.id, ()); - if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs) - != attr::ia_none { - traverse_inline_body(cx, ctor.node.body); - } - } do option::iter(&struct_def.dtor) |dtor| { cx.rmap.insert(dtor.node.id, ()); if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs) @@ -139,7 +128,7 @@ fn mk_ty_visitor() -> visit::vt<ctx> { visit::mk_vt(@{visit_ty: traverse_ty, ..*visit::default_visitor()}) } -fn traverse_ty(ty: @ty, cx: ctx, v: visit::vt<ctx>) { +fn traverse_ty(ty: @Ty, cx: ctx, v: visit::vt<ctx>) { if cx.rmap.contains_key(ty.id) { return; } cx.rmap.insert(ty.id, ()); diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index c105caecaeb..c52b653d536 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -1,5 +1,4 @@ use std::map::HashMap; -use driver::session::session; use lib::llvm::{TypeRef, ValueRef}; use syntax::ast; use back::abi; @@ -58,7 +57,7 @@ impl reflector { fn visit(ty_name: ~str, args: ~[ValueRef]) { let tcx = self.bcx.tcx(); - let mth_idx = option::get(&ty::method_idx( + let mth_idx = option::get(ty::method_idx( tcx.sess.ident_of(~"visit_" + ty_name), *self.visitor_methods)); let mth_ty = ty::mk_fn(tcx, self.visitor_methods[mth_idx].fty); diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index e1eae115694..bfc172db314 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -1,5 +1,4 @@ use syntax::ast; -use driver::session::session; use lib::llvm::{ValueRef, TypeRef}; use back::abi; use syntax::codemap::span; @@ -141,7 +140,7 @@ fn trans_fixed_vstore(bcx: block, { //! // - // [...]/_ allocates a fixed-size array and moves it around "by value". + // [...] allocates a fixed-size array and moves it around "by value". // In this case, it means that the caller has already given us a location // to store the array of the suitable size, so all we have to do is // generate the content. @@ -466,7 +465,7 @@ fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t, let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); // Calculate the last pointer address we want to handle. - // FIXME (#2536): Optimize this when the size of the unit type is + // FIXME (#3729): Optimize this when the size of the unit type is // statically known to not use pointer casts, which tend to confuse // LLVM. let data_end_ptr = pointer_add(bcx, data_ptr, fill); diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index ee247eb5db7..8b2efacd4d1 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -20,7 +20,6 @@ use std::map::HashMap; use std::list; use std::list::{List, Cons, Nil}; -use driver::session::session; use metadata::csearch; use syntax::ast::*, syntax::ast_util, syntax::visit; use syntax::ast_map; @@ -40,8 +39,13 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) Some(uses) => return uses, None => () } - let fn_id_loc = if fn_id.crate == local_crate { fn_id } - else { inline::maybe_instantiate_inline(ccx, fn_id) }; + + let fn_id_loc = if fn_id.crate == local_crate { + fn_id + } else { + inline::maybe_instantiate_inline(ccx, fn_id, true) + }; + // Conservatively assume full use for recursive loops ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u)); @@ -109,9 +113,6 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;} } } - ast_map::node_ctor(_, _, ctor, _, _) => { - handle_body(cx, ctor.node.body); - } ast_map::node_dtor(_, dtor, _, _) => { handle_body(cx, dtor.node.body); } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index f2f7b32b670..90527e88bc8 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -5,7 +5,7 @@ use std::{map, smallintmap}; use result::Result; use std::map::HashMap; use driver::session; -use session::session; +use session::Session; use syntax::{ast, ast_map}; use syntax::ast_util; use syntax::ast_util::{is_local, local_def}; @@ -18,11 +18,8 @@ use middle::lint::{get_lint_level, allow}; use syntax::ast::*; use syntax::print::pprust::*; use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str}; -use std::serialization::{serialize_Option, - deserialize_Option, - serialize_uint, - deserialize_uint}; +export ProvidedMethodSource; export TyVid, IntVid, FnVid, RegionVid, vid; export br_hashmap; export is_instantiable; @@ -106,7 +103,7 @@ export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var; export InferTy, TyVar, IntVar; export ty_self, mk_self, type_has_self; export ty_class; -export region, bound_region, encl_region; +export Region, bound_region, encl_region; export re_bound, re_free, re_scope, re_static, re_var; export br_self, br_anon, br_named, br_cap_avoid; export get, type_has_params, type_needs_infer, type_has_regions; @@ -117,7 +114,7 @@ export ty_var_id; export ty_to_def_id; export ty_fn_args; export ty_region; -export kind, kind_implicitly_copyable, kind_send_copy, kind_copyable; +export Kind, kind_implicitly_copyable, kind_send_copy, kind_copyable; export kind_noncopyable, kind_const; export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied; export kind_is_safe_for_default_mode; @@ -173,7 +170,6 @@ export mach_sty; export ty_sort_str; export normalize_ty; export to_str; -export borrow, serialize_borrow, deserialize_borrow; export bound_const; export terr_no_integral_type, terr_ty_param_size, terr_self_substs; export terr_in_field, terr_record_fields, terr_vstores_differ, terr_arg_count; @@ -192,12 +188,10 @@ export is_blockish; export method_call_bounds; export hash_region; export region_variance, rv_covariant, rv_invariant, rv_contravariant; -export serialize_region_variance, deserialize_region_variance; export opt_region_variance; -export serialize_opt_region_variance, deserialize_opt_region_variance; export determine_inherited_purity; export provided_trait_methods; -export AutoAdjustment, serialize_AutoAdjustment, deserialize_AutoAdjustment; +export AutoAdjustment; export AutoRef, AutoRefKind, AutoSlice, AutoPtr; // Data types @@ -214,16 +208,18 @@ type method = {ident: ast::ident, tps: @~[param_bounds], fty: FnTy, self_ty: ast::self_ty_, - vis: ast::visibility}; + vis: ast::visibility, + def_id: ast::def_id}; type mt = {ty: t, mutbl: ast::mutability}; #[auto_serialize] +#[auto_deserialize] enum vstore { vstore_fixed(uint), vstore_uniq, vstore_box, - vstore_slice(region) + vstore_slice(Region) } type field_ty = { @@ -275,10 +271,10 @@ enum ast_ty_to_ty_cache_entry { atttce_resolved(t) /* resolved to a type, irrespective of region */ } -#[auto_serialize] type opt_region_variance = Option<region_variance>; #[auto_serialize] +#[auto_deserialize] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } impl region_variance : cmp::Eq { @@ -296,19 +292,22 @@ impl region_variance : cmp::Eq { } #[auto_serialize] +#[auto_deserialize] type AutoAdjustment = { autoderefs: uint, autoref: Option<AutoRef> }; #[auto_serialize] +#[auto_deserialize] type AutoRef = { kind: AutoRefKind, - region: region, + region: Region, mutbl: ast::mutability }; #[auto_serialize] +#[auto_deserialize] enum AutoRefKind { /// Convert from @[]/~[] to &[] (or str) AutoSlice, @@ -317,14 +316,19 @@ enum AutoRefKind { AutoPtr } +struct ProvidedMethodSource { + method_id: ast::def_id, + impl_id: ast::def_id +} + type ctxt = @{diag: syntax::diagnostic::span_handler, interner: HashMap<intern_key, t_box>, mut next_id: uint, vecs_implicitly_copyable: bool, legacy_modes: bool, - cstore: metadata::cstore::cstore, - sess: session::session, + cstore: metadata::cstore::CStore, + sess: session::Session, def_map: resolve::DefMap, region_map: middle::region::region_map, @@ -350,8 +354,8 @@ type ctxt = short_names_cache: HashMap<t, @~str>, needs_drop_cache: HashMap<t, bool>, needs_unwind_cleanup_cache: HashMap<t, bool>, - kind_cache: HashMap<t, kind>, - ast_ty_to_ty_cache: HashMap<@ast::ty, ast_ty_to_ty_cache_entry>, + kind_cache: HashMap<t, Kind>, + ast_ty_to_ty_cache: HashMap<@ast::Ty, ast_ty_to_ty_cache_entry>, enum_var_cache: HashMap<def_id, @~[variant_info]>, trait_method_cache: HashMap<def_id, @~[method]>, ty_param_bounds: HashMap<ast::node_id, param_bounds>, @@ -359,7 +363,8 @@ type ctxt = adjustments: HashMap<ast::node_id, @AutoAdjustment>, normalized_cache: HashMap<t, t>, lang_items: middle::lang_items::LanguageItems, - legacy_boxed_traits: HashMap<node_id, ()>}; + legacy_boxed_traits: HashMap<node_id, ()>, + provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>}; enum tbox_flag { has_params = 1, @@ -513,7 +518,8 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: #[auto_serialize] -enum region { +#[auto_deserialize] +enum Region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions /// (analogous to type parameters, except that due to the monomorphic @@ -541,6 +547,7 @@ enum region { } #[auto_serialize] +#[auto_deserialize] enum bound_region { /// The self region for classes, impls (&T in a type defn or &self/T) br_self, @@ -563,7 +570,7 @@ enum bound_region { br_cap_avoid(ast::node_id, @bound_region), } -type opt_region = Option<region>; +type opt_region = Option<Region>; /** * The type substs represents the kinds of things that can be substituted to @@ -603,7 +610,7 @@ enum sty { ty_uniq(mt), ty_evec(mt, vstore), ty_ptr(mt), - ty_rptr(region, mt), + ty_rptr(Region, mt), ty_rec(~[field]), ty_fn(FnTy), ty_trait(def_id, substs, vstore), @@ -649,9 +656,9 @@ enum type_err { terr_record_fields(expected_found<ident>), terr_arg_count, terr_mode_mismatch(expected_found<mode>), - terr_regions_does_not_outlive(region, region), - terr_regions_not_same(region, region), - terr_regions_no_overlap(region, region), + terr_regions_does_not_outlive(Region, Region), + terr_regions_not_same(Region, Region), + terr_regions_no_overlap(Region, Region), terr_vstores_differ(terr_vstore_kind, expected_found<vstore>), terr_in_field(@type_err, ast::ident), terr_sorts(expected_found<t>), @@ -671,6 +678,7 @@ enum TyVid = uint; enum IntVid = uint; enum FnVid = uint; #[auto_serialize] +#[auto_deserialize] enum RegionVid = uint; enum InferTy { @@ -775,7 +783,7 @@ impl FnVid : to_bytes::IterBytes { } } -fn param_bounds_to_kind(bounds: param_bounds) -> kind { +fn param_bounds_to_kind(bounds: param_bounds) -> Kind { let mut kind = kind_noncopyable(); for vec::each(*bounds) |bound| { match *bound { @@ -826,7 +834,7 @@ fn new_ty_hash<V: Copy>() -> map::HashMap<t, V> { map::HashMap() } -fn mk_ctxt(s: session::session, +fn mk_ctxt(s: session::Session, dm: resolve::DefMap, amap: ast_map::map, freevars: freevars::freevar_map, @@ -879,7 +887,8 @@ fn mk_ctxt(s: session::session, adjustments: HashMap(), normalized_cache: new_ty_hash(), lang_items: move lang_items, - legacy_boxed_traits: HashMap()} + legacy_boxed_traits: HashMap(), + provided_method_sources: HashMap()} } @@ -895,7 +904,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t { _ => () } let mut flags = 0u; - fn rflags(r: region) -> uint { + fn rflags(r: Region) -> uint { (has_regions as uint) | { match r { ty::re_var(_) => needs_infer as uint, @@ -1009,12 +1018,12 @@ fn mk_imm_uniq(cx: ctxt, ty: t) -> t { mk_uniq(cx, {ty: ty, fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) } -fn mk_rptr(cx: ctxt, r: region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) } +fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) } -fn mk_mut_rptr(cx: ctxt, r: region, ty: t) -> t { +fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t { mk_rptr(cx, r, {ty: ty, mutbl: ast::m_mutbl}) } -fn mk_imm_rptr(cx: ctxt, r: region, ty: t) -> t { +fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t { mk_rptr(cx, r, {ty: ty, mutbl: ast::m_imm}) } @@ -1139,7 +1148,7 @@ fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { // Returns the narrowest lifetime enclosing the evaluation of the expression // with id `id`. -fn encl_region(cx: ctxt, id: ast::node_id) -> ty::region { +fn encl_region(cx: ctxt, id: ast::node_id) -> ty::Region { match cx.region_map.find(id) { Some(encl_scope) => ty::re_scope(encl_scope), None => ty::re_static @@ -1256,7 +1265,7 @@ fn fold_ty(cx: ctxt, t0: t, fldop: fn(t) -> t) -> t { fn walk_regions_and_ty( cx: ctxt, ty: t, - walkr: fn(r: region), + walkr: fn(r: Region), walkt: fn(t: t) -> bool) { if (walkt(ty)) { @@ -1271,13 +1280,13 @@ fn walk_regions_and_ty( fn fold_regions_and_ty( cx: ctxt, ty: t, - fldr: fn(r: region) -> region, + fldr: fn(r: Region) -> Region, fldfnt: fn(t: t) -> t, fldt: fn(t: t) -> t) -> t { fn fold_substs( substs: &substs, - fldr: fn(r: region) -> region, + fldr: fn(r: Region) -> Region, fldt: fn(t: t) -> t) -> substs { {self_r: substs.self_r.map(|r| fldr(*r)), @@ -1342,10 +1351,10 @@ fn fold_regions_and_ty( fn fold_regions( cx: ctxt, ty: t, - fldr: fn(r: region, in_fn: bool) -> region) -> t { + fldr: fn(r: Region, in_fn: bool) -> Region) -> t { fn do_fold(cx: ctxt, ty: t, in_fn: bool, - fldr: fn(region, bool) -> region) -> t { + fldr: fn(Region, bool) -> Region) -> t { if !type_has_regions(ty) { return ty; } fold_regions_and_ty( cx, ty, @@ -1356,9 +1365,9 @@ fn fold_regions( do_fold(cx, ty, false, fldr) } -fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t { +fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t { fn do_fold(cx: ctxt, t0: t, under_r: bool, - fldop: fn(region, bool) -> region) -> t { + fldop: fn(Region, bool) -> Region) -> t { let tb = get(t0); if !tbox_has_flag(tb, has_regions) { return t0; } match tb.sty { @@ -1392,13 +1401,23 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t { } // Substitute *only* type parameters. Used in trans where regions are erased. -fn subst_tps(cx: ctxt, tps: &[t], typ: t) -> t { - if tps.len() == 0u { return typ; } +fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t { + if tps.len() == 0u && self_ty_opt.is_none() { return typ; } let tb = ty::get(typ); - if !tbox_has_flag(tb, has_params) { return typ; } + if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; } match tb.sty { - ty_param(p) => tps[p.idx], - ref sty => fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, t)) + ty_param(p) => tps[p.idx], + ty_self => { + match self_ty_opt { + None => cx.sess.bug(~"ty_self unexpected here"), + Some(self_ty) => { + subst_tps(cx, tps, self_ty_opt, self_ty) + } + } + } + ref sty => { + fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t)) + } } } @@ -1454,7 +1473,10 @@ fn subst(cx: ctxt, fold_regions_and_ty( cx, typ, |r| match r { - re_bound(br_self) => substs.self_r.get(), + re_bound(br_self) => substs.self_r.expect( + #fmt("ty::subst: \ + Reference to self region when given substs with no \ + self region, ty = %s", ty_to_str(cx, typ))), _ => r }, |t| do_subst(cx, substs, t), @@ -1758,7 +1780,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t, return needs_unwind_cleanup; } -enum kind { kind_(u32) } +enum Kind { kind_(u32) } /// can be copied (implicitly or explicitly) const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32; @@ -1778,92 +1800,92 @@ const KIND_MASK_IMPLICIT : u32 = 0b000000000000000000000010000_u32; /// safe for default mode (subset of KIND_MASK_IMPLICIT) const KIND_MASK_DEFAULT_MODE : u32 = 0b000000000000000000000100000_u32; -fn kind_noncopyable() -> kind { +fn kind_noncopyable() -> Kind { kind_(0u32) } -fn kind_copyable() -> kind { +fn kind_copyable() -> Kind { kind_(KIND_MASK_COPY) } -fn kind_implicitly_copyable() -> kind { +fn kind_implicitly_copyable() -> Kind { kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY) } -fn kind_safe_for_default_mode() -> kind { +fn kind_safe_for_default_mode() -> Kind { // similar to implicit copy, but always includes vectors and strings kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY) } -fn kind_implicitly_sendable() -> kind { +fn kind_implicitly_sendable() -> Kind { kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND) } -fn kind_safe_for_default_mode_send() -> kind { +fn kind_safe_for_default_mode_send() -> Kind { // similar to implicit copy, but always includes vectors and strings kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND) } -fn kind_send_copy() -> kind { +fn kind_send_copy() -> Kind { kind_(KIND_MASK_COPY | KIND_MASK_SEND) } -fn kind_send_only() -> kind { +fn kind_send_only() -> Kind { kind_(KIND_MASK_SEND) } -fn kind_const() -> kind { +fn kind_const() -> Kind { kind_(KIND_MASK_CONST) } -fn kind_owned() -> kind { +fn kind_owned() -> Kind { kind_(KIND_MASK_OWNED) } -fn kind_top() -> kind { +fn kind_top() -> Kind { kind_(0xffffffffu32) } -fn remove_const(k: kind) -> kind { +fn remove_const(k: Kind) -> Kind { k - kind_const() } -fn remove_implicit(k: kind) -> kind { +fn remove_implicit(k: Kind) -> Kind { k - kind_(KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE) } -fn remove_send(k: kind) -> kind { +fn remove_send(k: Kind) -> Kind { k - kind_(KIND_MASK_SEND) } -fn remove_owned_send(k: kind) -> kind { +fn remove_owned_send(k: Kind) -> Kind { k - kind_(KIND_MASK_OWNED) - kind_(KIND_MASK_SEND) } -fn remove_copyable(k: kind) -> kind { +fn remove_copyable(k: Kind) -> Kind { k - kind_(KIND_MASK_COPY | KIND_MASK_DEFAULT_MODE) } -impl kind : ops::BitAnd<kind,kind> { - pure fn bitand(other: &kind) -> kind { +impl Kind : ops::BitAnd<Kind,Kind> { + pure fn bitand(other: &Kind) -> Kind { unsafe { lower_kind(self, (*other)) } } } -impl kind : ops::BitOr<kind,kind> { - pure fn bitor(other: &kind) -> kind { +impl Kind : ops::BitOr<Kind,Kind> { + pure fn bitor(other: &Kind) -> Kind { unsafe { raise_kind(self, (*other)) } } } -impl kind : ops::Sub<kind,kind> { - pure fn sub(other: &kind) -> kind { +impl Kind : ops::Sub<Kind,Kind> { + pure fn sub(other: &Kind) -> Kind { unsafe { kind_(*self & !*(*other)) } @@ -1873,27 +1895,27 @@ impl kind : ops::Sub<kind,kind> { // Using these query functions is preferable to direct comparison or matching // against the kind constants, as we may modify the kind hierarchy in the // future. -pure fn kind_can_be_implicitly_copied(k: kind) -> bool { +pure fn kind_can_be_implicitly_copied(k: Kind) -> bool { *k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT } -pure fn kind_is_safe_for_default_mode(k: kind) -> bool { +pure fn kind_is_safe_for_default_mode(k: Kind) -> bool { *k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE } -pure fn kind_can_be_copied(k: kind) -> bool { +pure fn kind_can_be_copied(k: Kind) -> bool { *k & KIND_MASK_COPY == KIND_MASK_COPY } -pure fn kind_can_be_sent(k: kind) -> bool { +pure fn kind_can_be_sent(k: Kind) -> bool { *k & KIND_MASK_SEND == KIND_MASK_SEND } -pure fn kind_is_owned(k: kind) -> bool { +pure fn kind_is_owned(k: Kind) -> bool { *k & KIND_MASK_OWNED == KIND_MASK_OWNED } -fn meta_kind(p: FnMeta) -> kind { +fn meta_kind(p: FnMeta) -> Kind { match p.proto { // XXX consider the kind bounds! proto_vstore(vstore_slice(_)) => kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE), @@ -1908,15 +1930,15 @@ fn meta_kind(p: FnMeta) -> kind { } } -fn kind_lteq(a: kind, b: kind) -> bool { +fn kind_lteq(a: Kind, b: Kind) -> bool { *a & *b == *a } -fn lower_kind(a: kind, b: kind) -> kind { +fn lower_kind(a: Kind, b: Kind) -> Kind { kind_(*a & *b) } -fn raise_kind(a: kind, b: kind) -> kind { +fn raise_kind(a: Kind, b: Kind) -> Kind { kind_(*a | *b) } @@ -1941,7 +1963,7 @@ fn test_kinds() { // with the given mutability can have. // This is used to prevent objects containing mutable state from being // implicitly copied and to compute whether things have const kind. -fn mutability_kind(m: mutability) -> kind { +fn mutability_kind(m: mutability) -> Kind { match (m) { m_mutbl => remove_const(remove_implicit(kind_top())), m_const => remove_implicit(kind_top()), @@ -1949,11 +1971,11 @@ fn mutability_kind(m: mutability) -> kind { } } -fn mutable_type_kind(cx: ctxt, ty: mt) -> kind { +fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind { lower_kind(mutability_kind(ty.mutbl), type_kind(cx, ty.ty)) } -fn type_kind(cx: ctxt, ty: t) -> kind { +fn type_kind(cx: ctxt, ty: t) -> Kind { match cx.kind_cache.find(ty) { Some(result) => return result, None => {/* fall through */ } @@ -2531,7 +2553,7 @@ impl bound_region : to_bytes::IterBytes { } } -impl region : to_bytes::IterBytes { +impl Region : to_bytes::IterBytes { pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { match self { re_bound(ref br) => @@ -2744,7 +2766,7 @@ fn is_fn_ty(fty: t) -> bool { } } -fn ty_region(ty: t) -> region { +fn ty_region(ty: t) -> Region { match get(ty).sty { ty_rptr(r, _) => r, s => fail fmt!("ty_region() invoked on non-rptr: %?", s) @@ -3020,7 +3042,7 @@ fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field { match vec::find(get_fields(rec_ty), |f| f.ident == id) { Some(f) => f, // Do we only call this when we know the field is legit? - None => fail (#fmt("get_field: ty doesn't have a field %s", + None => fail (fmt!("get_field: ty doesn't have a field %s", tcx.sess.str_of(id))) } } @@ -3318,7 +3340,7 @@ fn note_and_explain_type_err(cx: ctxt, err: &type_err) { fn def_has_ty_params(def: ast::def) -> bool { match def { - ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_, _) + ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_) => true, _ => false } @@ -3328,20 +3350,18 @@ fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) { cx.trait_method_cache.insert(ast_util::local_def(id), ms); } -fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@ast::method] { +fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] { if is_local(id) { match cx.items.find(id.node) { Some(ast_map::node_item(@{node: item_trait(_, _, ms),_}, _)) => match ast_util::split_trait_methods(ms) { - (_, p) => p + (_, p) => p.map(|method| method.ident) }, - _ => cx.sess.bug(#fmt("provided_trait_methods: %? is not a trait", + _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait", id)) } - } - else { - // FIXME #2794: default methods for traits don't work cross-crate - ~[] + } else { + csearch::get_provided_trait_methods(cx, id).map(|info| info.ty.ident) } } @@ -3492,9 +3512,6 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { ast_map::path_name(variant.node.name)) } - ast_map::node_ctor(nm, _, _, _, path) => { - vec::append_one(*path, ast_map::path_name(nm)) - } ast_map::node_dtor(_, _, _, path) => { vec::append_one(*path, ast_map::path_name( syntax::parse::token::special_idents::literally_dtor)) @@ -3552,7 +3569,6 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] { }; match variant.node.disr_expr { Some (ex) => { - // FIXME: issue #1417 disr_val = match const_eval::eval_const_expr(cx, ex) { const_eval::const_int(val) => val as int, @@ -3603,10 +3619,12 @@ fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id, // the type cache. Returns the type parameters and type. fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty { match cx.tcache.find(did) { - Some(tpt) => return tpt, - None => { + Some(tpt) => { // The item is in this crate. The caller should have added it to the // type cache already + return tpt; + } + None => { assert did.crate != ast::local_crate; let tyt = csearch::get_type(cx, did); cx.tcache.insert(did, tyt); @@ -3895,9 +3913,11 @@ fn normalize_ty(cx: ctxt, t: t) -> t { ty_enum(did, r) => match r.self_r { Some(_) => - // This enum has a self region. Get rid of it + // Use re_static since trans doesn't care about regions mk_enum(cx, did, - {self_r: None, self_ty: None, tps: r.tps}), + {self_r: Some(ty::re_static), + self_ty: None, + tps: r.tps}), None => t }, @@ -3906,7 +3926,8 @@ fn normalize_ty(cx: ctxt, t: t) -> t { match r.self_r { Some(_) => // Ditto. - mk_class(cx, did, {self_r: None, self_ty: None, tps: r.tps}), + mk_class(cx, did, {self_r: Some(ty::re_static), self_ty: None, + tps: r.tps}), None => t }, @@ -3915,10 +3936,6 @@ fn normalize_ty(cx: ctxt, t: t) -> t { t }; - // FIXME #2187: This also reduced int types to their compatible machine - // types, which isn't necessary after #2187 - let t = mk_t(cx, mach_sty(cx.sess.targ_cfg, t)); - let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) }); let t_norm = mk_t(cx, sty); cx.normalized_cache.insert(t, t_norm); @@ -4073,8 +4090,8 @@ impl RegionVid : cmp::Eq { pure fn ne(other: &RegionVid) -> bool { *self != *(*other) } } -impl region : cmp::Eq { - pure fn eq(other: ®ion) -> bool { +impl Region : cmp::Eq { + pure fn eq(other: &Region) -> bool { match self { re_bound(e0a) => { match (*other) { @@ -4108,7 +4125,7 @@ impl region : cmp::Eq { } } } - pure fn ne(other: ®ion) -> bool { !self.eq(other) } + pure fn ne(other: &Region) -> bool { !self.eq(other) } } impl bound_region : cmp::Eq { @@ -4356,9 +4373,9 @@ impl param_bound : cmp::Eq { pure fn ne(other: ¶m_bound) -> bool { !self.eq(other) } } -impl kind : cmp::Eq { - pure fn eq(other: &kind) -> bool { *self == *(*other) } - pure fn ne(other: &kind) -> bool { *self != *(*other) } +impl Kind : cmp::Eq { + pure fn eq(other: &Kind) -> bool { *self == *(*other) } + pure fn ne(other: &Kind) -> bool { *self != *(*other) } } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 514fc2cfbb3..90aacb4b7ce 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -46,8 +46,7 @@ use syntax::ast_map::node_id_to_str; use syntax::ast_util::{local_def, respan, split_trait_methods}; use syntax::visit; use metadata::csearch; -use driver::session::session; -use util::common::may_break; +use util::common::{block_query, loop_query}; use syntax::codemap::span; use pat_util::{pat_is_variant, pat_id_map, PatIdMap}; use middle::ty; @@ -56,20 +55,19 @@ use middle::ty::{vstore_uniq}; use std::smallintmap; use std::map; use std::map::HashMap; -use std::serialization::{serialize_uint, deserialize_uint}; use syntax::print::pprust::*; use util::ppaux::{ty_to_str, tys_to_str, region_to_str, bound_region_to_str, vstore_to_str, expr_repr}; use util::common::{indent, indenter}; use std::list; use list::{List, Nil, Cons}; +use dvec::DVec; export check_crate; export infer; export method_map; -export method_origin, serialize_method_origin, deserialize_method_origin; -export method_map_entry, serialize_method_map_entry; -export deserialize_method_map_entry; +export method_origin; +export method_map_entry; export vtable_map; export vtable_res; export vtable_origin; @@ -78,6 +76,7 @@ export vtable_static, vtable_param, vtable_trait; export provided_methods_map; #[auto_serialize] +#[auto_deserialize] enum method_origin { // fully statically resolved method method_static(ast::def_id), @@ -95,6 +94,7 @@ enum method_origin { // details for a method invoked with a receiver whose type is a type parameter // with a bounded trait. #[auto_serialize] +#[auto_deserialize] type method_param = { // the trait containing the method to be invoked trait_id: ast::def_id, @@ -174,12 +174,6 @@ impl vtable_origin { type vtable_map = HashMap<ast::node_id, vtable_res>; -// Stores information about provided methods, aka "default methods" in traits. -// Maps from a trait's def_id to a MethodInfo about -// that method in that trait. -type provided_methods_map = HashMap<ast::node_id, - ~[@resolve::MethodInfo]>; - type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t}; type crate_ctxt_ = {// A mapping from method call sites to traits that have @@ -188,7 +182,6 @@ type crate_ctxt_ = {// A mapping from method call sites to traits that have method_map: method_map, vtable_map: vtable_map, coherence_info: @coherence::CoherenceInfo, - provided_methods_map: provided_methods_map, tcx: ty::ctxt}; enum crate_ctxt { @@ -340,7 +333,6 @@ fn check_crate(tcx: ty::ctxt, method_map: std::map::HashMap(), vtable_map: std::map::HashMap(), coherence_info: @coherence::CoherenceInfo(), - provided_methods_map: std::map::HashMap(), tcx: tcx}); collect::collect_item_types(ccx, crate); coherence::check_coherence(ccx, crate); diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 14797fcdd6b..da7a71b3efb 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -58,7 +58,7 @@ trait ast_conv { fn get_region_reporting_err(tcx: ty::ctxt, span: span, - res: Result<ty::region, ~str>) -> ty::region { + res: Result<ty::Region, ~str>) -> ty::Region { match res { result::Ok(r) => r, @@ -70,7 +70,7 @@ fn get_region_reporting_err(tcx: ty::ctxt, } fn ast_region_to_region<AC: ast_conv, RS: region_scope Copy Owned>( - self: AC, rscope: RS, span: span, a_r: @ast::region) -> ty::region { + self: AC, rscope: RS, span: span, a_r: @ast::region) -> ty::Region { let res = match a_r.node { ast::re_static => Ok(ty::re_static), @@ -148,14 +148,14 @@ fn ast_path_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( return {substs: substs, ty: ty}; } -const NO_REGIONS: uint = 1u; -const NO_TPS: uint = 2u; +const NO_REGIONS: uint = 1; +const NO_TPS: uint = 2; // Parses the programmer's textual representation of a type into our // internal notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( - self: AC, rscope: RS, &&ast_ty: @ast::ty) -> ty::t { + self: AC, rscope: RS, &&ast_ty: @ast::Ty) -> ty::t { fn ast_mt_to_mt<AC: ast_conv, RS: region_scope Copy Owned>( self: AC, rscope: RS, mt: ast::mt) -> ty::mt { @@ -323,7 +323,7 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( Some(d) => d }; match a_def { - ast::def_ty(did) | ast::def_class(did, _) => { + ast::def_ty(did) | ast::def_class(did) => { ast_path_to_ty(self, rscope, did, path, id).ty } ast::def_prim_ty(nty) => { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 7cc2c8b0ad7..cc542e9f366 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -166,20 +166,20 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t, } // a list of mapping from in-scope-region-names ("isr") to the -// corresponding ty::region -type isr_alist = @List<(ty::bound_region, ty::region)>; +// corresponding ty::Region +type isr_alist = @List<(ty::bound_region, ty::Region)>; trait get_and_find_region { - fn get(br: ty::bound_region) -> ty::region; - fn find(br: ty::bound_region) -> Option<ty::region>; + fn get(br: ty::bound_region) -> ty::Region; + fn find(br: ty::bound_region) -> Option<ty::Region>; } impl isr_alist: get_and_find_region { - fn get(br: ty::bound_region) -> ty::region { + fn get(br: ty::bound_region) -> ty::Region { self.find(br).get() } - fn find(br: ty::bound_region) -> Option<ty::region> { + fn find(br: ty::bound_region) -> Option<ty::Region> { for list::each(self) |isr| { let (isr_br, isr_r) = *isr; if isr_br == br { return Some(isr_r); } @@ -451,18 +451,6 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, let tcx = ccx.tcx; let self_ty = ty::node_id_to_type(tcx, id); - do option::iter(&struct_def.ctor) |ctor| { - let class_t = {self_ty: self_ty, - self_id: ctor.node.self_id, - def_id: local_def(id), - explicit_self: {node: ast::sty_by_ref, - span: ast_util::dummy_sp()}}; - // typecheck the ctor - check_bare_fn(ccx, ctor.node.dec, - ctor.node.body, ctor.node.id, - Some(class_t)); - } - do option::iter(&struct_def.dtor) |dtor| { let class_t = {self_ty: self_ty, self_id: dtor.node.self_id, @@ -575,7 +563,7 @@ impl @fn_ctxt: ast_conv { impl @fn_ctxt { fn search_in_scope_regions(br: ty::bound_region) - -> Result<ty::region, ~str> + -> Result<ty::Region, ~str> { match self.in_scope_regions.find(br) { Some(r) => result::Ok(r), @@ -593,13 +581,13 @@ impl @fn_ctxt { } impl @fn_ctxt: region_scope { - fn anon_region(span: span) -> Result<ty::region, ~str> { + fn anon_region(span: span) -> Result<ty::Region, ~str> { result::Ok(self.infcx().next_region_var_nb(span)) } - fn self_region(_span: span) -> Result<ty::region, ~str> { + fn self_region(_span: span) -> Result<ty::Region, ~str> { self.search_in_scope_regions(ty::br_self) } - fn named_region(_span: span, id: ast::ident) -> Result<ty::region, ~str> { + fn named_region(_span: span, id: ast::ident) -> Result<ty::Region, ~str> { self.search_in_scope_regions(ty::br_named(id)) } } @@ -612,7 +600,7 @@ impl @fn_ctxt { pprust::expr_to_str(expr, self.tcx().sess.intr())) } - fn block_region() -> ty::region { + fn block_region() -> ty::Region { ty::re_scope(self.region_lb) } @@ -657,7 +645,7 @@ impl @fn_ctxt { self.write_ty(node_id, ty::mk_bot(self.tcx())); } - fn to_ty(ast_t: @ast::ty) -> ty::t { + fn to_ty(ast_t: @ast::Ty) -> ty::t { ast_ty_to_ty(self, self, ast_t) } @@ -748,7 +736,7 @@ impl @fn_ctxt { } fn mk_subr(a_is_expected: bool, span: span, - sub: ty::region, sup: ty::region) -> Result<(), ty::type_err> { + sub: ty::Region, sup: ty::Region) -> Result<(), ty::type_err> { infer::mk_subr(self.infcx(), a_is_expected, span, sub, sup) } @@ -772,8 +760,8 @@ impl @fn_ctxt { fn region_var_if_parameterized(rp: Option<ty::region_variance>, span: span, - lower_bound: ty::region) - -> Option<ty::region> + lower_bound: ty::Region) + -> Option<ty::Region> { rp.map( |_rp| self.infcx().next_region_var_with_lb(span, lower_bound)) @@ -1031,7 +1019,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // functions. This is so that we have more information about the types // of arguments when we typecheck the functions. This isn't really the // right way to do this. - for [false, true]/_.each |check_blocks| { + for [false, true].each |check_blocks| { let check_blocks = *check_blocks; debug!("check_blocks=%b", check_blocks); @@ -1371,7 +1359,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Check field access expressions fn check_field(fcx: @fn_ctxt, expr: @ast::expr, is_callee: bool, - base: @ast::expr, field: ast::ident, tys: ~[@ast::ty]) + base: @ast::expr, field: ast::ident, tys: ~[@ast::Ty]) -> bool { let tcx = fcx.ccx.tcx; @@ -1677,7 +1665,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, ast::expr_loop(body, _) => { check_block_no_value(fcx, body); fcx.write_ty(id, ty::mk_nil(tcx)); - bot = !may_break(body); + bot = !may_break(tcx, expr.id, body); } ast::expr_match(discrim, arms) => { bot = alt::check_alt(fcx, expr, discrim, arms); @@ -1925,7 +1913,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Resolve the path. let class_id; match tcx.def_map.find(id) { - Some(ast::def_class(type_def_id, _)) => { + Some(ast::def_class(type_def_id)) => { class_id = type_def_id; } _ => { @@ -2231,9 +2219,14 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool { fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) { let rty = ty::node_id_to_type(ccx.tcx, id); let fcx = blank_fn_ctxt(ccx, rty, e.id); + let declty = fcx.ccx.tcx.tcache.get(local_def(id)).ty; + check_const_with_ty(fcx, _sp, e, declty); +} + +fn check_const_with_ty(fcx: @fn_ctxt, _sp: span, e: @ast::expr, + declty: ty::t) { check_expr(fcx, e, None); let cty = fcx.expr_ty(e); - let declty = fcx.ccx.tcx.tcache.get(local_def(id)).ty; demand::suptype(fcx, e.span, declty, cty); regionck::regionck_expr(fcx, e); writeback::resolve_type_vars_in_expr(fcx, e); @@ -2271,28 +2264,31 @@ fn check_enum_variants(ccx: @crate_ctxt, variants: &mut ~[ty::variant_info]) { let rty = ty::node_id_to_type(ccx.tcx, id); for vs.each |v| { - match v.node.disr_expr { - Some(e) => { - let fcx = blank_fn_ctxt(ccx, rty, e.id); - check_expr(fcx, e, None); - let cty = fcx.expr_ty(e); + do v.node.disr_expr.iter |e_ref| { + let e = *e_ref; + debug!("disr expr, checking %s", + expr_to_str(e, ccx.tcx.sess.intr())); let declty = ty::mk_int(ccx.tcx); - demand::suptype(fcx, e.span, declty, cty); - // FIXME: issue #1417 - // Also, check_expr (from check_const pass) doesn't guarantee + let fcx = blank_fn_ctxt(ccx, rty, e.id); + check_const_with_ty(fcx, e.span, e, declty); + // check_expr (from check_const pass) doesn't guarantee // that the expression is in an form that eval_const_expr can // handle, so we may still get an internal compiler error - match const_eval::eval_const_expr(ccx.tcx, e) { - const_eval::const_int(val) => { + + match const_eval::eval_const_expr_partial(ccx.tcx, e) { + Ok(const_eval::const_int(val)) => { *disr_val = val as int; } - _ => { + Ok(_) => { ccx.tcx.sess.span_err(e.span, ~"expected signed integer \ constant"); } + Err(err) => { + ccx.tcx.sess.span_err(e.span, + #fmt("expected constant: %s", err)); + + } } - } - _ => () } if vec::contains(*disr_vals, &*disr_val) { ccx.tcx.sess.span_err(v.span, @@ -2404,15 +2400,15 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> } ast::def_fn(id, ast::unsafe_fn) | - ast::def_static_method(id, ast::unsafe_fn) => { + ast::def_static_method(id, _, ast::unsafe_fn) => { // Unsafe functions can only be touched in an unsafe context fcx.require_unsafe(sp, ~"access to unsafe function"); return ty::lookup_item_type(fcx.ccx.tcx, id); } - ast::def_fn(id, _) | ast::def_static_method(id, _) | + ast::def_fn(id, _) | ast::def_static_method(id, _, _) | ast::def_const(id) | ast::def_variant(_, id) | - ast::def_class(id, _) => { + ast::def_class(id) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_upvar(_, inner, _, _) => { @@ -2447,7 +2443,7 @@ fn instantiate_path(fcx: @fn_ctxt, tpt: ty_param_bounds_and_ty, span: span, node_id: ast::node_id, - region_lb: ty::region) { + region_lb: ty::Region) { let ty_param_count = vec::len(*tpt.bounds); let ty_substs_len = vec::len(pth.types); @@ -2548,6 +2544,29 @@ fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint, } } +// Returns true if b contains a break that can exit from b +fn may_break(cx: ty::ctxt, id: ast::node_id, b: ast::blk) -> bool { + // First: is there an unlabeled break immediately + // inside the loop? + (loop_query(b, |e| { + match e { + ast::expr_break(_) => true, + _ => false + } + })) || + // Second: is there a labeled break with label + // <id> nested anywhere inside the loop? + (block_query(b, |e| { + match e.node { + ast::expr_break(Some(_)) => + match cx.def_map.find(e.id) { + Some(ast::def_label(loop_id)) if id == loop_id => true, + _ => false, + }, + _ => false + }})) +} + fn check_bounds_are_used(ccx: @crate_ctxt, span: span, tps: ~[ast::ty_param], @@ -2620,7 +2639,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { } ~"get_tydesc" => { - // FIXME (#2712): return *intrinsic::tydesc, not *() + // FIXME (#3730): return *intrinsic::tydesc, not *() (1u, ~[], ty::mk_nil_ptr(tcx)) } ~"visit_tydesc" => { diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs index 0b2e9c8ab3d..caace605198 100644 --- a/src/rustc/middle/typeck/check/alt.rs +++ b/src/rustc/middle/typeck/check/alt.rs @@ -112,8 +112,8 @@ fn check_legality_of_move_bindings(fcx: @fn_ctxt, type pat_ctxt = { fcx: @fn_ctxt, map: PatIdMap, - alt_region: ty::region, // Region for the alt as a whole - block_region: ty::region, // Region for the block of the arm + alt_region: ty::Region, // Region for the alt as a whole + block_region: ty::Region, // Region for the block of the arm }; fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, @@ -325,7 +325,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { // Check to ensure that the struct is the one specified. match tcx.def_map.get(pat.id) { - ast::def_class(supplied_def_id, _) + ast::def_class(supplied_def_id) if supplied_def_id == class_id => { // OK. } diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index f3b2c8f1b7e..eaf1a45afa9 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -69,7 +69,7 @@ obtained the type `Foo`, we would never match this method. */ -use coherence::get_base_type_def_id; +use coherence::{ProvidedMethodInfo, get_base_type_def_id}; use middle::resolve::{Impl, MethodInfo}; use middle::ty::*; use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box, @@ -146,7 +146,7 @@ impl LookupContext { // Prepare the list of candidates self.push_inherent_candidates(self_ty); - self.push_extension_candidates(); + self.push_extension_candidates(self_ty); let enum_dids = DVec(); let mut self_ty = self_ty; @@ -251,7 +251,7 @@ impl LookupContext { } } - fn push_extension_candidates(&self) { + fn push_extension_candidates(&self, self_ty: ty::t) { // If the method being called is associated with a trait, then // find all the impls of that trait. Each of those are // candidates. @@ -259,6 +259,8 @@ impl LookupContext { for opt_applicable_traits.each |applicable_traits| { for applicable_traits.each |trait_did| { let coherence_info = self.fcx.ccx.coherence_info; + + // Look for explicit implementations. let opt_impl_infos = coherence_info.extension_methods.find(*trait_did); for opt_impl_infos.each |impl_infos| { @@ -267,12 +269,21 @@ impl LookupContext { &self.extension_candidates, *impl_info); } } + + // Look for default methods. + match coherence_info.provided_methods.find(*trait_did) { + Some(methods) => { + self.push_candidates_from_provided_methods( + &self.extension_candidates, self_ty, *trait_did, + methods); + } + None => {} + } } } } - fn push_inherent_candidates_from_param(&self, param_ty: param_ty) - { + fn push_inherent_candidates_from_param(&self, param_ty: param_ty) { debug!("push_inherent_candidates_from_param(param_ty=%?)", param_ty); let _indenter = indenter(); @@ -348,8 +359,7 @@ impl LookupContext { self_ty: ty::t, did: def_id, substs: &ty::substs, - vstore: ty::vstore) - { + vstore: ty::vstore) { debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)", self.did_to_str(did), substs_to_str(self.tcx(), substs)); @@ -363,7 +373,7 @@ impl LookupContext { }; let method = &ms[index]; - /* FIXME(#3468) we should transform the vstore in accordance + /* FIXME(#3157) we should transform the vstore in accordance with the self type match method.self_type { @@ -423,8 +433,7 @@ impl LookupContext { }); } - fn push_inherent_impl_candidates_for_type(did: def_id) - { + fn push_inherent_impl_candidates_for_type(did: def_id) { let opt_impl_infos = self.fcx.ccx.coherence_info.inherent_methods.find(did); for opt_impl_infos.each |impl_infos| { @@ -436,8 +445,7 @@ impl LookupContext { } fn push_candidates_from_impl(&self, candidates: &DVec<Candidate>, - impl_info: &resolve::Impl) - { + impl_info: &resolve::Impl) { if !self.impl_dups.insert(impl_info.did, ()) { return; // already visited } @@ -471,12 +479,47 @@ impl LookupContext { }); } + fn push_candidates_from_provided_methods( + &self, + candidates: &DVec<Candidate>, + self_ty: ty::t, + trait_def_id: def_id, + methods: @DVec<@ProvidedMethodInfo>) { + debug!("(pushing candidates from provided methods) considering trait \ + id %d:%d", + trait_def_id.crate, + trait_def_id.node); + + for methods.each |provided_method_info| { + if provided_method_info.method_info.ident != self.m_name { loop; } + + debug!("(pushing candidates from provided methods) adding \ + candidate"); + + // XXX: Needs to support generics. + let dummy_substs = { self_r: None, self_ty: None, tps: ~[] }; + let (impl_ty, impl_substs) = + self.create_rcvr_ty_and_substs_for_method( + provided_method_info.method_info.self_type, + self_ty, + dummy_substs); + + candidates.push(Candidate { + rcvr_ty: impl_ty, + rcvr_substs: move impl_substs, + num_method_tps: provided_method_info.method_info.n_tps, + self_mode: get_mode_from_self_type( + provided_method_info.method_info.self_type), + origin: method_static(provided_method_info.method_info.did) + }); + } + } + fn create_rcvr_ty_and_substs_for_method(&self, self_decl: ast::self_ty_, self_ty: ty::t, +self_substs: ty::substs) - -> (ty::t, ty::substs) - { + -> (ty::t, ty::substs) { // If the self type includes a region (like &self), we need to // ensure that the receiver substitutions have a self region. // If the receiver type does not itself contain borrowed @@ -611,7 +654,7 @@ impl LookupContext { kind: AutoRefKind, autoderefs: uint, mutbls: &[ast::mutability], - mk_autoref_ty: &fn(ast::mutability, ty::region) -> ty::t) + mk_autoref_ty: &fn(ast::mutability, ty::Region) -> ty::t) -> Option<method_map_entry> { // This is hokey. We should have mutability inference as a @@ -693,8 +736,7 @@ impl LookupContext { fn confirm_candidate(&self, self_ty: ty::t, candidate: &Candidate) - -> method_map_entry - { + -> method_map_entry { let tcx = self.tcx(); let fty = self.fn_ty_from_origin(&candidate.origin); @@ -888,7 +930,7 @@ impl LookupContext { } fn transform_self_type_for_method(tcx: ty::ctxt, - self_region: Option<ty::region>, + self_region: Option<ty::Region>, impl_ty: ty::t, self_type: ast::self_ty_) -> ty::t diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index 0b258da5672..932cdd994da 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -32,7 +32,7 @@ use middle::ty::{vstore_uniq}; enum rcx { rcx_({fcx: @fn_ctxt, mut errors_reported: uint}) } type rvt = visit::vt<@rcx>; -fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::region { +fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region { let tcx = fcx.tcx(); match def { def_local(node_id, _) | def_arg(node_id, _) | def_self(node_id) | @@ -335,7 +335,7 @@ fn constrain_auto_ref( fn constrain_free_variables( rcx: @rcx, - region: ty::region, + region: ty::Region, expr: @ast::expr) { /*! @@ -373,7 +373,7 @@ fn constrain_free_variables( fn constrain_regions_in_type_of_node( rcx: @rcx, id: ast::node_id, - encl_region: ty::region, + encl_region: ty::Region, span: span) -> bool { let tcx = rcx.fcx.tcx(); @@ -395,7 +395,7 @@ fn constrain_regions_in_type_of_node( fn constrain_regions_in_type( rcx: @rcx, - encl_region: ty::region, + encl_region: ty::Region, span: span, ty: ty::t) -> bool { @@ -417,9 +417,9 @@ fn constrain_regions_in_type( return (e == rcx.errors_reported); fn constrain_region(rcx: @rcx, - encl_region: ty::region, + encl_region: ty::Region, span: span, - region: ty::region) { + region: ty::Region) { let tcx = rcx.fcx.ccx.tcx; debug!("constrain_region(encl_region=%?, region=%?)", diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs index 4afb3ad78a6..806b234540c 100644 --- a/src/rustc/middle/typeck/check/regionmanip.rs +++ b/src/rustc/middle/typeck/check/regionmanip.rs @@ -10,7 +10,7 @@ fn replace_bound_regions_in_fn_ty( isr: isr_alist, self_info: Option<self_info>, fn_ty: &ty::FnTy, - mapf: fn(ty::bound_region) -> ty::region) -> + mapf: fn(ty::bound_region) -> ty::Region) -> {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy} { // Take self_info apart; the self_ty part is the only one we want @@ -83,7 +83,7 @@ fn replace_bound_regions_in_fn_ty( tcx: ty::ctxt, isr: isr_alist, tys: ~[ty::t], - to_r: fn(ty::bound_region) -> ty::region) -> isr_alist { + to_r: fn(ty::bound_region) -> ty::Region) -> isr_alist { // Takes `isr` (described above), `to_r` (described above), // and `r`, a region. If `r` is anything other than a bound @@ -93,8 +93,8 @@ fn replace_bound_regions_in_fn_ty( // updated isr_alist that now contains a mapping from `r` to // the result of calling `to_r` on it. fn append_isr(isr: isr_alist, - to_r: fn(ty::bound_region) -> ty::region, - r: ty::region) -> isr_alist { + to_r: fn(ty::bound_region) -> ty::Region, + r: ty::Region) -> isr_alist { match r { ty::re_free(_, _) | ty::re_static | ty::re_scope(_) | ty::re_var(_) => { diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index 00fb134f2be..345b8246b42 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -444,7 +444,7 @@ fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t], // XXX: This should work for multiple traits. let ity = ty::impl_traits(tcx, impl_did, vstore)[0]; - let trait_ty = ty::subst_tps(tcx, impl_tys, ity); + let trait_ty = ty::subst_tps(tcx, impl_tys, None, ity); debug!("(connect trait tps) trait type is %?, impl did is %?", ty::get(trait_ty).sty, impl_did); match ty::get(trait_ty).sty { diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs index 89cd696eb6f..189e7377d9c 100644 --- a/src/rustc/middle/typeck/coherence.rs +++ b/src/rustc/middle/typeck/coherence.rs @@ -4,12 +4,13 @@ // has at most one implementation for each type. Then we build a mapping from // each trait in the system to its implementations. -use metadata::csearch::{each_path, get_impl_traits, get_impls_for_mod}; -use metadata::cstore::{cstore, iter_crate_data}; +use metadata::csearch::{ProvidedTraitMethodInfo, each_path, get_impl_traits}; +use metadata::csearch::{get_impls_for_mod}; +use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; -use middle::ty::{get, lookup_item_type, subst, t, ty_box}; -use middle::ty::{ty_uniq, ty_ptr, ty_rptr, ty_enum}; +use middle::ty::{ProvidedMethodSource, get, lookup_item_type, subst, t}; +use middle::ty::{ty_box, ty_uniq, ty_ptr, ty_rptr, ty_enum}; use middle::ty::{ty_class, ty_nil, ty_bot, ty_bool, ty_int, ty_uint}; use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec}; use middle::ty::{ty_fn, ty_trait, ty_tup, ty_infer}; @@ -17,7 +18,7 @@ use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box}; use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_ty_var}; use middle::typeck::infer::{infer_ctxt, can_mk_subty}; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type}; -use syntax::ast::{crate, def_id, def_mod}; +use syntax::ast::{crate, def_id, def_mod, def_ty}; use syntax::ast::{item, item_class, item_const, item_enum, item_fn}; use syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod}; use syntax::ast::{item_trait, item_ty, local_crate, method, node_id}; @@ -118,6 +119,21 @@ fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo { } } +// Stores the method info and definition ID of the associated trait method for +// each instantiation of each provided method. +struct ProvidedMethodInfo { + method_info: @MethodInfo, + trait_method_def_id: def_id +} + +// Stores information about provided methods (a.k.a. default methods) in +// implementations. +// +// This is a map from ID of each implementation to the method info and trait +// method ID of each of the default methods belonging to the trait that that +// implementation implements. +type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>; + struct CoherenceInfo { // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. @@ -128,14 +144,20 @@ struct CoherenceInfo { extension_methods: HashMap<def_id,@DVec<@Impl>>, // A mapping from a supertrait to its subtraits. - supertrait_to_subtraits: HashMap<def_id,@DVec<def_id>> + supertrait_to_subtraits: HashMap<def_id,@DVec<def_id>>, + + // A mapping from an implementation ID to the method info and trait method + // ID of the provided (a.k.a. default) methods in the traits that that + // implementation implements. + provided_methods: ProvidedMethodsMap, } fn CoherenceInfo() -> CoherenceInfo { CoherenceInfo { inherent_methods: HashMap(), extension_methods: HashMap(), - supertrait_to_subtraits: HashMap() + supertrait_to_subtraits: HashMap(), + provided_methods: HashMap(), } } @@ -165,68 +187,6 @@ struct CoherenceChecker { } impl CoherenceChecker { - // Create a mapping containing a MethodInfo for every provided - // method in every trait. - fn build_provided_methods_map(crate: @crate) { - let sess = self.crate_context.tcx.sess; - - let pmm = self.crate_context.provided_methods_map; - - visit_crate(*crate, (), mk_simple_visitor(@{ - visit_item: |item| { - match item.node { - item_trait(_, _, trait_methods) => { - for trait_methods.each |trait_method| { - debug!("(building provided methods map) checking \ - trait `%s` with id %d", - sess.str_of(item.ident), item.id); - - match *trait_method { - required(_) => { /* fall through */} - provided(m) => { - // For every provided method in the - // trait, store a MethodInfo. - let mi = method_to_MethodInfo(m); - - match pmm.find(item.id) { - Some(mis) => { - // If the trait already has an - // entry in the - // provided_methods_map, we just - // need to add this method to - // that entry. - debug!("(building provided \ - methods map) adding \ - method `%s` to entry for \ - existing trait", - sess.str_of(mi.ident)); - let mut method_infos = mis; - method_infos.push(mi); - pmm.insert(item.id, method_infos); - } - None => { - // If the trait doesn't have an - // entry yet, create one. - debug!("(building provided \ - methods map) creating new \ - entry for method `%s`", - sess.str_of(mi.ident)); - pmm.insert(item.id, ~[mi]); - } - } - } - } - } - } - _ => { - // Nothing to do. - } - }; - }, - .. *default_simple_visitor() - })); - } - fn check_coherence(crate: @crate) { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also @@ -307,6 +267,7 @@ impl CoherenceChecker { self.crate_context.tcx.sess.parse_sess.interner), self.crate_context.tcx.sess.str_of(item.ident)); + self.instantiate_default_methods(item.id, trait_did); let implementation = self.create_impl_from_item(item); self.add_trait_method(trait_did, implementation); } @@ -321,6 +282,7 @@ impl CoherenceChecker { // Nothing to do. } Some(base_type_def_id) => { + // XXX: Gather up default methods? let implementation = self.create_impl_from_item(item); self.add_inherent_method(base_type_def_id, implementation); @@ -330,6 +292,68 @@ impl CoherenceChecker { } } + // Creates default method IDs and performs type substitutions for an impl + // and trait pair. Then, for each provided method in the trait, inserts a + // `ProvidedMethodInfo` instance into the `provided_method_sources` map. + fn instantiate_default_methods(impl_id: ast::node_id, + trait_did: ast::def_id) { + for self.each_provided_trait_method(trait_did) |trait_method| { + // Synthesize an ID. + let tcx = self.crate_context.tcx; + let new_id = syntax::parse::next_node_id(tcx.sess.parse_sess); + let new_did = local_def(new_id); + + // XXX: Perform substitutions. + let new_polytype = ty::lookup_item_type(tcx, trait_method.def_id); + tcx.tcache.insert(new_did, new_polytype); + + // Pair the new synthesized ID up with the + // ID of the method. + let source = ProvidedMethodSource { + method_id: trait_method.def_id, + impl_id: local_def(impl_id) + }; + + self.crate_context.tcx.provided_method_sources.insert(new_did, + source); + + let provided_method_info = + @ProvidedMethodInfo { + method_info: @{ + did: new_did, + n_tps: trait_method.tps.len(), + ident: trait_method.ident, + self_type: trait_method.self_ty + }, + trait_method_def_id: trait_method.def_id + }; + + let pmm = self.crate_context.coherence_info.provided_methods; + match pmm.find(local_def(impl_id)) { + Some(mis) => { + // If the trait already has an entry in the + // provided_methods_map, we just need to add this + // method to that entry. + debug!("(checking implementation) adding method `%s` \ + to entry for existing trait", + self.crate_context.tcx.sess.str_of( + provided_method_info.method_info.ident)); + mis.push(provided_method_info); + } + None => { + // If the trait doesn't have an entry yet, create one. + debug!("(checking implementation) creating new entry \ + for method `%s`", + self.crate_context.tcx.sess.str_of( + provided_method_info.method_info.ident)); + let method_infos = @DVec(); + method_infos.push(provided_method_info); + pmm.insert(local_def(impl_id), method_infos); + } + } + } + } + fn register_inherited_trait(item: @item, supertraits: ~[@trait_ref]) { // XXX: This is wrong. We need to support substitutions; e.g. // trait Foo : Bar<int>. @@ -354,8 +378,7 @@ impl CoherenceChecker { fn add_inherent_method(base_def_id: def_id, implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.inherent_methods - .find(base_def_id) { - + .find(base_def_id) { None => { implementation_list = @DVec(); self.crate_context.coherence_info.inherent_methods @@ -372,8 +395,7 @@ impl CoherenceChecker { fn add_trait_method(trait_id: def_id, implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.extension_methods - .find(trait_id) { - + .find(trait_id) { None => { implementation_list = @DVec(); self.crate_context.coherence_info.extension_methods @@ -413,6 +435,26 @@ impl CoherenceChecker { } } + fn each_provided_trait_method( + trait_did: ast::def_id, + f: &fn(x: &ty::method) -> bool) { + // Make a list of all the names of the provided methods. + // XXX: This is horrible. + let provided_method_idents = HashMap(); + let tcx = self.crate_context.tcx; + for ty::provided_trait_methods(tcx, trait_did).each |ident| { + provided_method_idents.insert(*ident, ()); + } + + for ty::trait_methods(tcx, trait_did).each |method| { + if provided_method_idents.contains_key(method.ident) { + if !f(method) { + break; + } + } + } + } + fn polytypes_unify(polytype_a: ty_param_bounds_and_ty, polytype_b: ty_param_bounds_and_ty) -> bool { @@ -449,7 +491,6 @@ impl CoherenceChecker { fn get_self_type_for_implementation(implementation: @Impl) -> ty_param_bounds_and_ty { - return self.crate_context.tcx.tcache.get(implementation.did); } @@ -552,33 +593,15 @@ impl CoherenceChecker { // Converts an implementation in the AST to an Impl structure. fn create_impl_from_item(item: @item) -> @Impl { - - fn add_provided_methods(inherent_methods: ~[@MethodInfo], - all_provided_methods: ~[@MethodInfo], - sess: driver::session::session) - -> ~[@MethodInfo] { - - let mut methods = inherent_methods; - - // If there's no inherent method with the same name as a - // provided method, add that provided method to `methods`. + fn add_provided_methods(all_methods: &mut ~[@MethodInfo], + all_provided_methods: ~[@ProvidedMethodInfo], + sess: driver::session::Session) { for all_provided_methods.each |provided_method| { - let mut method_inherent_to_impl = false; - for inherent_methods.each |inherent_method| { - if provided_method.ident == inherent_method.ident { - method_inherent_to_impl = true; - } - } - - if !method_inherent_to_impl { - debug!( - "(creating impl) adding provided method `%s` to impl", - sess.str_of(provided_method.ident)); - methods.push(*provided_method); - } + debug!( + "(creating impl) adding provided method `%s` to impl", + sess.str_of(provided_method.method_info.ident)); + vec::push(all_methods, provided_method.method_info); } - - return methods; } match item.node { @@ -598,24 +621,22 @@ impl CoherenceChecker { let trait_did = self.trait_ref_to_trait_def_id(*trait_ref); - match self.crate_context.provided_methods_map - .find(trait_did.node) { + match self.crate_context + .coherence_info + .provided_methods + .find(local_def(item.id)) { None => { debug!("(creating impl) trait with node_id `%d` \ has no provided methods", trait_did.node); /* fall through */ } - Some(all_provided) - => { + Some(all_provided) => { debug!("(creating impl) trait with node_id `%d` \ has provided methods", trait_did.node); - // Selectively add only those provided - // methods that aren't inherent to the - // trait. - - // XXX: could probably be doing this with filter. - methods = add_provided_methods( - methods, all_provided, + // Add all provided methods. + add_provided_methods( + &mut methods, + all_provided.get(), self.crate_context.tcx.sess); } } @@ -673,7 +694,7 @@ impl CoherenceChecker { // External crate handling fn add_impls_for_module(impls_seen: HashMap<def_id,()>, - crate_store: cstore, + crate_store: CStore, module_def_id: def_id) { let implementations = get_impls_for_mod(crate_store, @@ -758,6 +779,41 @@ impl CoherenceChecker { } } + fn add_default_methods_for_external_trait(trait_def_id: ast::def_id) { + let tcx = self.crate_context.tcx; + let pmm = self.crate_context.coherence_info.provided_methods; + + if pmm.contains_key(trait_def_id) { return; } + + debug!("(adding default methods for trait) processing trait"); + + for csearch::get_provided_trait_methods(tcx, + trait_def_id).each |info| { + debug!("(adding default methods for trait) found default method"); + + // Create a new def ID for this provided method. + let parse_sess = &self.crate_context.tcx.sess.parse_sess; + let new_did = local_def(syntax::parse::next_node_id(*parse_sess)); + + let provided_method_info = + @ProvidedMethodInfo { + method_info: @{ + did: new_did, + n_tps: info.ty.tps.len(), + ident: info.ty.ident, + self_type: info.ty.self_ty + }, + trait_method_def_id: info.def_id + }; + + let method_infos = @DVec(); + method_infos.push(provided_method_info); + pmm.insert(trait_def_id, method_infos); + } + } + + // Adds implementations and traits from external crates to the coherence + // info. fn add_external_crates() { let impls_seen = HashMap(); @@ -768,20 +824,28 @@ impl CoherenceChecker { { crate: crate_number, node: 0 }); for each_path(crate_store, crate_number) |path_entry| { - let module_def_id; match path_entry.def_like { dl_def(def_mod(def_id)) => { - module_def_id = def_id; + self.add_impls_for_module(impls_seen, + crate_store, + def_id); + } + dl_def(def_ty(def_id)) => { + let tcx = self.crate_context.tcx; + let polytype = csearch::get_type(tcx, def_id); + match ty::get(polytype.ty).sty { + ty::ty_trait(*) => { + self.add_default_methods_for_external_trait( + def_id); + } + _ => {} + } } dl_def(_) | dl_impl(_) | dl_field => { // Skip this. loop; } } - - self.add_impls_for_module(impls_seen, - crate_store, - module_def_id); } } } @@ -789,7 +853,6 @@ impl CoherenceChecker { fn check_coherence(crate_context: @crate_ctxt, crate: @crate) { let coherence_checker = @CoherenceChecker(crate_context); - (*coherence_checker).build_provided_methods_map(crate); (*coherence_checker).check_coherence(crate); } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 18e29981af3..e12104a21da 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -76,7 +76,7 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { impl @crate_ctxt { fn to_ty<RS: region_scope Copy Owned>( - rs: RS, ast_ty: @ast::ty) -> ty::t { + rs: RS, ast_ty: @ast::Ty) -> ty::t { ast_ty_to_ty(self, rs, ast_ty) } @@ -212,9 +212,15 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { match tcx.items.get(id) { ast_map::node_item(@{node: ast::item_trait(params, _, ms), _}, _) => { store_methods::<ast::trait_method>(ccx, id, ms, |m| { + let def_id; + match *m { + ast::required(ty_method) => def_id = local_def(ty_method.id), + ast::provided(method) => def_id = local_def(method.id) + } + let trait_bounds = ty_param_bounds(ccx, params); let ty_m = trait_method_to_ty_method(*m); - let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd); + let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id); if ty_m.self_ty.node == ast::sty_static { make_static_method_ty(ccx, ty_m, region_paramd, method_ty, trait_ty, trait_bounds); @@ -266,7 +272,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, } if impl_m.tps.len() != trait_m.tps.len() { - tcx.sess.span_err(sp, #fmt("method `%s` \ + tcx.sess.span_err(sp, fmt!("method `%s` \ has %u type %s, but its trait declaration has %u type %s", tcx.sess.str_of(trait_m.ident), impl_m.tps.len(), pluralize(impl_m.tps.len(), ~"parameter"), @@ -291,7 +297,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, // Would be nice to use the ty param names in the error message, // but we don't have easy access to them here if impl_param_bounds.len() != trait_param_bounds.len() { - tcx.sess.span_err(sp, #fmt("in method `%s`, \ + tcx.sess.span_err(sp, fmt!("in method `%s`, \ type parameter %u has %u %s, but the same type \ parameter in its trait declaration has %u %s", tcx.sess.str_of(trait_m.ident), @@ -339,7 +345,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, // Replaces bound references to the self region with `with_r`. fn replace_bound_self(tcx: ty::ctxt, ty: ty::t, - with_r: ty::region) -> ty::t { + with_r: ty::Region) -> ty::t { do ty::fold_regions(tcx, ty) |r, _in_fn| { if r == ty::re_bound(ty::br_self) {with_r} else {r} } @@ -373,7 +379,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt, let provided_methods = ty::provided_trait_methods(tcx, did); match vec::find(provided_methods, |provided_method| - provided_method.ident == trait_m.ident) { + *provided_method == trait_m.ident) { Some(_) => { // If there's a provided method with the name we // want, then we're fine; nothing else to do. @@ -497,30 +503,6 @@ fn convert_struct(ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty, id: ast::node_id) { let tcx = ccx.tcx; - do option::iter(&struct_def.ctor) |ctor| { - // Write the ctor type - let t_args = ctor.node.dec.inputs.map( - |a| ty_of_arg(ccx, type_rscope(rp), *a, None) ); - let t_res = ty::mk_class( - tcx, local_def(id), - {self_r: rscope::bound_self_region(rp), - self_ty: None, - tps: ty::ty_params_to_tys(tcx, tps)}); - let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static)); - let t_ctor = ty::mk_fn(tcx, FnTyBase { - meta: FnMeta {purity: ast::impure_fn, - proto: proto, - bounds: @~[], - ret_style: ast::return_val}, - sig: FnSig {inputs: t_args, - output: t_res} - }); - write_ty_to_tcx(tcx, ctor.node.id, t_ctor); - tcx.tcache.insert(local_def(ctor.node.id), - {bounds: tpt.bounds, - region_param: rp, - ty: t_ctor}); - } do option::iter(&struct_def.dtor) |dtor| { // Write the dtor type @@ -570,19 +552,22 @@ fn ty_of_method(ccx: @crate_ctxt, m.purity, @~[], m.decl, None, m.span), self_ty: m.self_ty.node, - vis: m.vis} + vis: m.vis, + def_id: local_def(m.id)} } fn ty_of_ty_method(self: @crate_ctxt, m: ast::ty_method, - rp: Option<ty::region_variance>) -> ty::method { + rp: Option<ty::region_variance>, + id: ast::def_id) -> ty::method { {ident: m.ident, tps: ty_param_bounds(self, m.tps), fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare, m.purity, @~[], m.decl, None, m.span), // assume public, because this is only invoked on trait methods self_ty: m.self_ty.node, - vis: ast::public} + vis: ast::public, + def_id: id} } /* @@ -722,28 +707,41 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item) } } +// Translate the AST's notion of ty param bounds (which are just newtyped Tys) +// to ty's notion of ty param bounds, which can either be user-defined traits, +// or one of the four built-in traits (formerly known as kinds): Const, Copy, +// Owned, and Send. fn compute_bounds(ccx: @crate_ctxt, ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds { @do vec::flat_map(*ast_bounds) |b| { - match *b { - ast::bound_send => ~[ty::bound_send], - ast::bound_copy => ~[ty::bound_copy], - ast::bound_const => ~[ty::bound_const], - ast::bound_owned => ~[ty::bound_owned], - ast::bound_trait(t) => { - let ity = ast_ty_to_ty(ccx, empty_rscope, t); - match ty::get(ity).sty { - ty::ty_trait(*) => { - ~[ty::bound_trait(ity)] - } - _ => { + let li = &ccx.tcx.lang_items; + let ity = ast_ty_to_ty(ccx, empty_rscope, **b); + match ty::get(ity).sty { + ty::ty_trait(did, _, _) => { + let d = Some(did); + if d == li.send_trait { + ~[ty::bound_send] + } + else if d == li.copy_trait { + ~[ty::bound_copy] + } + else if d == li.const_trait { + ~[ty::bound_const] + } + else if d == li.owned_trait { + ~[ty::bound_owned] + } + else { + // Must be a user-defined trait + ~[ty::bound_trait(ity)] + } + } + _ => { ccx.tcx.sess.span_err( - t.span, ~"type parameter bounds must be \ - trait types"); + (*b).span, ~"type parameter bounds must be \ + trait types"); ~[] - } } - } } } } diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index e5aa0debfe1..e0465b22c93 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -258,7 +258,6 @@ use util::ppaux::{ty_to_str, mt_to_str}; use result::{Result, Ok, Err, map_vec, map_vec2, iter_vec2}; use ty::{mk_fn, type_is_bot}; use check::regionmanip::{replace_bound_regions_in_fn_ty}; -use driver::session::session; use util::common::{indent, indenter}; use ast::{unsafe_fn, impure_fn, pure_fn, extern_fn}; use ast::{m_const, m_imm, m_mutbl}; @@ -275,7 +274,7 @@ use unify::{vals_and_bindings, root}; use integral::{int_ty_set, int_ty_set_all}; use combine::{combine_fields, eq_tys}; use assignment::Assign; -use to_str::to_str; +use to_str::ToStr; use sub::Sub; use lub::Lub; @@ -385,7 +384,7 @@ fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { } fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span, - a: ty::region, b: ty::region) -> ures { + a: ty::Region, b: ty::Region) -> ures { debug!("mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx)); do indent { do cx.commit { @@ -431,8 +430,8 @@ fn resolve_type(cx: infer_ctxt, a: ty::t, modes: uint) resolver(cx, modes).resolve_type_chk(a) } -fn resolve_region(cx: infer_ctxt, r: ty::region, modes: uint) - -> fres<ty::region> { +fn resolve_region(cx: infer_ctxt, r: ty::Region, modes: uint) + -> fres<ty::Region> { resolver(cx, modes).resolve_region_chk(r) } @@ -565,11 +564,8 @@ impl infer_ctxt { do indent { let r <- self.try(f); - // FIXME (#2814)---could use a vec::clear() that ran - // destructors but kept the vec at its currently allocated - // length - self.ty_var_bindings.bindings = ~[]; - self.int_var_bindings.bindings = ~[]; + self.ty_var_bindings.bindings.truncate(0); + self.int_var_bindings.bindings.truncate(0); self.region_vars.commit(); move r } @@ -631,12 +627,12 @@ impl infer_ctxt { ty::mk_int_var(self.tcx, self.next_int_var_id()) } - fn next_region_var_nb(span: span) -> ty::region { + fn next_region_var_nb(span: span) -> ty::Region { ty::re_var(self.region_vars.new_region_var(span)) } fn next_region_var_with_lb(span: span, - lb_region: ty::region) -> ty::region { + lb_region: ty::Region) -> ty::Region { let region_var = self.next_region_var_nb(span); // add lb_region as a lower bound on the newly built variable @@ -647,7 +643,7 @@ impl infer_ctxt { return region_var; } - fn next_region_var(span: span, scope_id: ast::node_id) -> ty::region { + fn next_region_var(span: span, scope_id: ast::node_id) -> ty::Region { self.next_region_var_with_lb(span, ty::re_scope(scope_id)) } diff --git a/src/rustc/middle/typeck/infer/assignment.rs b/src/rustc/middle/typeck/infer/assignment.rs index 53731551df5..a5af58904dd 100644 --- a/src/rustc/middle/typeck/infer/assignment.rs +++ b/src/rustc/middle/typeck/infer/assignment.rs @@ -48,7 +48,7 @@ // A. But this upper-bound might be stricter than what is truly // needed. -use to_str::to_str; +use to_str::ToStr; use combine::combine_fields; fn to_ares(+c: cres<ty::t>) -> ares { @@ -190,7 +190,7 @@ priv impl Assign { a: ty::t, nr_b: ty::t, m: ast::mutability, - r_b: ty::region) -> ares { + r_b: ty::Region) -> ares { debug!("try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)", a.to_str(self.infcx), diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs index db65bff9bfe..342a2ce2b76 100644 --- a/src/rustc/middle/typeck/infer/combine.rs +++ b/src/rustc/middle/typeck/infer/combine.rs @@ -44,7 +44,7 @@ // terms of error reporting, although we do not do that properly right // now. -use to_str::to_str; +use to_str::ToStr; use ty::{FnTyBase, FnMeta, FnSig}; trait combine { @@ -72,8 +72,8 @@ trait combine { fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres<ty::fn_proto>; fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>; fn purities(a: purity, b: purity) -> cres<purity>; - fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region>; - fn regions(a: ty::region, b: ty::region) -> cres<ty::region>; + fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region>; + fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region>; fn vstores(vk: ty::terr_vstore_kind, a: ty::vstore, b: ty::vstore) -> cres<ty::vstore>; } @@ -88,9 +88,9 @@ fn expected_found<C: combine,T>( self: &C, +a: T, +b: T) -> ty::expected_found<T> { if self.a_is_expected() { - ty::expected_found {expected: a, found: b} + ty::expected_found {expected: move a, found: move b} } else { - ty::expected_found {expected: b, found: a} + ty::expected_found {expected: move b, found: move a} } } @@ -103,7 +103,7 @@ fn eq_tys<C: combine>(self: &C, a: ty::t, b: ty::t) -> ures { } } -fn eq_regions<C: combine>(self: &C, a: ty::region, b: ty::region) -> ures { +fn eq_regions<C: combine>(self: &C, a: ty::Region, b: ty::Region) -> ures { debug!("eq_regions(%s, %s)", a.to_str(self.infcx()), b.to_str(self.infcx())); @@ -127,8 +127,8 @@ fn eq_regions<C: combine>(self: &C, a: ty::region, b: ty::region) -> ures { fn eq_opt_regions<C:combine>( self: &C, - a: Option<ty::region>, - b: Option<ty::region>) -> cres<Option<ty::region>> { + a: Option<ty::Region>, + b: Option<ty::Region>) -> cres<Option<ty::Region>> { match (a, b) { (None, None) => { @@ -160,9 +160,9 @@ fn super_substs<C:combine>( fn relate_region_param<C:combine>( self: &C, did: ast::def_id, - a: Option<ty::region>, - b: Option<ty::region>) - -> cres<Option<ty::region>> + a: Option<ty::Region>, + b: Option<ty::Region>) + -> cres<Option<ty::Region>> { let polyty = ty::lookup_item_type(self.infcx().tcx, did); match (polyty.region_param, a, b) { diff --git a/src/rustc/middle/typeck/infer/glb.rs b/src/rustc/middle/typeck/infer/glb.rs index a8676a63b88..77e753fa220 100644 --- a/src/rustc/middle/typeck/infer/glb.rs +++ b/src/rustc/middle/typeck/infer/glb.rs @@ -1,6 +1,6 @@ use combine::*; use lattice::*; -use to_str::to_str; +use to_str::ToStr; enum Glb = combine_fields; // "greatest lower bound" (common subtype) @@ -109,7 +109,7 @@ impl Glb: combine { } } - fn regions(a: ty::region, b: ty::region) -> cres<ty::region> { + fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> { debug!("%s.regions(%?, %?)", self.tag(), a.to_str(self.infcx), @@ -120,7 +120,7 @@ impl Glb: combine { } } - fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region> { + fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region> { Lub(*self).regions(a, b) } diff --git a/src/rustc/middle/typeck/infer/integral.rs b/src/rustc/middle/typeck/infer/integral.rs index 168709596dc..1b23cb52b20 100644 --- a/src/rustc/middle/typeck/infer/integral.rs +++ b/src/rustc/middle/typeck/infer/integral.rs @@ -4,7 +4,7 @@ Code related to integral type inference. */ -use to_str::to_str; +use to_str::ToStr; // Bitvector to represent sets of integral types enum int_ty_set = uint; diff --git a/src/rustc/middle/typeck/infer/lattice.rs b/src/rustc/middle/typeck/infer/lattice.rs index 04133cab9d7..699613e8ae6 100644 --- a/src/rustc/middle/typeck/infer/lattice.rs +++ b/src/rustc/middle/typeck/infer/lattice.rs @@ -1,6 +1,6 @@ use combine::*; use unify::*; -use to_str::to_str; +use to_str::ToStr; // ______________________________________________________________________ // Lattice operations on variables diff --git a/src/rustc/middle/typeck/infer/lub.rs b/src/rustc/middle/typeck/infer/lub.rs index 093da5caec8..dcff863a126 100644 --- a/src/rustc/middle/typeck/infer/lub.rs +++ b/src/rustc/middle/typeck/infer/lub.rs @@ -1,6 +1,6 @@ use combine::*; use lattice::*; -use to_str::to_str; +use to_str::ToStr; enum Lub = combine_fields; // "subtype", "subregion" etc @@ -88,11 +88,11 @@ impl Lub: combine { } } - fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region> { + fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region> { return Glb(*self).regions(a, b); } - fn regions(a: ty::region, b: ty::region) -> cres<ty::region> { + fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> { debug!("%s.regions(%?, %?)", self.tag(), a.to_str(self.infcx), diff --git a/src/rustc/middle/typeck/infer/region_var_bindings.rs b/src/rustc/middle/typeck/infer/region_var_bindings.rs index 8bbdab74d23..86a872341f5 100644 --- a/src/rustc/middle/typeck/infer/region_var_bindings.rs +++ b/src/rustc/middle/typeck/infer/region_var_bindings.rs @@ -312,10 +312,10 @@ use std::map::HashMap; use std::cell::{Cell, empty_cell}; use std::list::{List, Nil, Cons}; -use ty::{region, RegionVid}; use region::is_subregion_of; +use ty::{Region, RegionVid}; use syntax::codemap; -use to_str::to_str; +use to_str::ToStr; use util::ppaux::note_and_explain_region; export RegionVarBindings; @@ -325,8 +325,8 @@ export glb_regions; enum Constraint { ConstrainVarSubVar(RegionVid, RegionVid), - ConstrainRegSubVar(region, RegionVid), - ConstrainVarSubReg(RegionVid, region) + ConstrainRegSubVar(Region, RegionVid), + ConstrainVarSubReg(RegionVid, Region) } impl Constraint : cmp::Eq { @@ -365,8 +365,8 @@ impl Constraint : to_bytes::IterBytes { } struct TwoRegions { - a: region, - b: region, + a: Region, + b: Region, } impl TwoRegions : cmp::Eq { @@ -394,7 +394,7 @@ type CombineMap = HashMap<TwoRegions, RegionVid>; struct RegionVarBindings { tcx: ty::ctxt, var_spans: DVec<span>, - values: Cell<~[ty::region]>, + values: Cell<~[ty::Region]>, constraints: HashMap<Constraint, span>, lubs: CombineMap, glbs: CombineMap, @@ -501,7 +501,7 @@ impl RegionVarBindings { } } - fn make_subregion(span: span, sub: region, sup: region) -> cres<()> { + fn make_subregion(span: span, sub: Region, sup: Region) -> cres<()> { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -529,7 +529,7 @@ impl RegionVarBindings { } } - fn lub_regions(span: span, a: region, b: region) -> cres<region> { + fn lub_regions(span: span, a: Region, b: Region) -> cres<Region> { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -551,7 +551,7 @@ impl RegionVarBindings { } } - fn glb_regions(span: span, a: region, b: region) -> cres<region> { + fn glb_regions(span: span, a: Region, b: Region) -> cres<Region> { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -574,7 +574,7 @@ impl RegionVarBindings { } } - fn resolve_var(rid: RegionVid) -> ty::region { + fn resolve_var(rid: RegionVid) -> ty::Region { debug!("RegionVarBindings: resolve_var(%?=%u)", rid, *rid); if self.values.is_empty() { self.tcx.sess.span_bug( @@ -586,9 +586,9 @@ impl RegionVarBindings { self.values.with_ref(|values| values[*rid]) } - fn combine_vars(combines: CombineMap, a: region, b: region, span: span, - relate: fn(old_r: region, new_r: region) -> cres<()>) - -> cres<region> { + fn combine_vars(combines: CombineMap, a: Region, b: Region, span: span, + relate: fn(old_r: Region, new_r: Region) -> cres<()>) + -> cres<Region> { let vars = TwoRegions { a: a, b: b }; match combines.find(vars) { @@ -623,11 +623,11 @@ impl RegionVarBindings { } priv impl RegionVarBindings { - fn is_subregion_of(sub: region, sup: region) -> bool { + fn is_subregion_of(sub: Region, sup: Region) -> bool { is_subregion_of(self.tcx.region_map, sub, sup) } - fn lub_concrete_regions(+a: region, +b: region) -> region { + fn lub_concrete_regions(+a: Region, +b: Region) -> Region { match (a, b) { (ty::re_static, _) | (_, ty::re_static) => { ty::re_static // nothing lives longer than static @@ -682,7 +682,7 @@ priv impl RegionVarBindings { } } - fn glb_concrete_regions(+a: region, +b: region) -> cres<region> { + fn glb_concrete_regions(+a: Region, +b: Region) -> cres<Region> { match (a, b) { (ty::re_static, r) | (r, ty::re_static) => { // static lives longer than everything else @@ -771,7 +771,7 @@ impl Classification : cmp::Eq { pure fn ne(other: &Classification) -> bool { !self.eq(other) } } -enum GraphNodeValue { NoValue, Value(region), ErrorValue } +enum GraphNodeValue { NoValue, Value(Region), ErrorValue } struct GraphNode { span: span, @@ -792,7 +792,7 @@ struct Graph { } struct SpannedRegion { - region: region, + region: Region, span: span, } @@ -803,7 +803,7 @@ fn TwoRegionsMap() -> TwoRegionsMap { } impl RegionVarBindings { - fn infer_variable_values() -> ~[region] { + fn infer_variable_values() -> ~[Region] { let graph = self.construct_graph(); self.expansion(&graph); self.contraction(&graph); @@ -895,7 +895,7 @@ impl RegionVarBindings { } } - fn expand_node(a_region: region, + fn expand_node(a_region: Region, b_vid: RegionVid, b_node: &GraphNode) -> bool { debug!("expand_node(%?, %? == %?)", @@ -955,7 +955,7 @@ impl RegionVarBindings { fn contract_node(a_vid: RegionVid, a_node: &GraphNode, - b_region: region) -> bool { + b_region: Region) -> bool { debug!("contract_node(%? == %?/%?, %?)", a_vid, a_node.value, a_node.classification, b_region); @@ -985,8 +985,8 @@ impl RegionVarBindings { fn check_node(self: &RegionVarBindings, a_vid: RegionVid, a_node: &GraphNode, - a_region: region, - b_region: region) -> bool { + a_region: Region, + b_region: Region) -> bool { if !self.is_subregion_of(a_region, b_region) { debug!("Setting %? to ErrorValue: %? not subregion of %?", a_vid, a_region, b_region); @@ -998,8 +998,8 @@ impl RegionVarBindings { fn adjust_node(self: &RegionVarBindings, a_vid: RegionVid, a_node: &GraphNode, - a_region: region, - b_region: region) -> bool { + a_region: Region, + b_region: Region) -> bool { match self.glb_concrete_regions(a_region, b_region) { Ok(glb) => { if glb == a_region { @@ -1040,7 +1040,7 @@ impl RegionVarBindings { debug!("---- %s Complete after %u iteration(s)", tag, iteration); } - fn extract_regions_and_report_errors(graph: &Graph) -> ~[region] { + fn extract_regions_and_report_errors(graph: &Graph) -> ~[Region] { let dup_map = TwoRegionsMap(); graph.nodes.mapi(|idx, node| { match node.value { @@ -1073,8 +1073,8 @@ impl RegionVarBindings { // Used to suppress reporting the same basic error over and over fn is_reported(dup_map: TwoRegionsMap, - r_a: region, - r_b: region) -> bool { + r_a: Region, + r_b: Region) -> bool { let key = TwoRegions { a: r_a, b: r_b }; !dup_map.insert(key, ()) } diff --git a/src/rustc/middle/typeck/infer/resolve.rs b/src/rustc/middle/typeck/infer/resolve.rs index 2a851a5f7bb..5a55fbf9a5d 100644 --- a/src/rustc/middle/typeck/infer/resolve.rs +++ b/src/rustc/middle/typeck/infer/resolve.rs @@ -35,7 +35,7 @@ // probably better off writing `resolve_all - resolve_ivar`. use integral::*; -use to_str::to_str; +use to_str::ToStr; const resolve_nested_tvar: uint = 0b00000001; const resolve_rvar: uint = 0b00000010; @@ -98,7 +98,7 @@ impl resolve_state { } } - fn resolve_region_chk(orig: ty::region) -> fres<ty::region> { + fn resolve_region_chk(orig: ty::Region) -> fres<ty::Region> { self.err = None; let resolved = indent(|| self.resolve_region(orig) ); match self.err { @@ -145,7 +145,7 @@ impl resolve_state { } } - fn resolve_region(orig: ty::region) -> ty::region { + fn resolve_region(orig: ty::Region) -> ty::Region { debug!("Resolve_region(%s)", orig.to_str(self.infcx)); match orig { ty::re_var(rid) => self.resolve_region_var(rid), @@ -153,14 +153,14 @@ impl resolve_state { } } - fn resolve_region_var(rid: RegionVid) -> ty::region { + fn resolve_region_var(rid: RegionVid) -> ty::Region { if !self.should(resolve_rvar) { return ty::re_var(rid) } self.infcx.region_vars.resolve_var(rid) } - fn assert_not_rvar(rid: RegionVid, r: ty::region) { + fn assert_not_rvar(rid: RegionVid, r: ty::Region) { match r { ty::re_var(rid2) => { self.err = Some(region_var_bound_by_region_var(rid, rid2)); diff --git a/src/rustc/middle/typeck/infer/sub.rs b/src/rustc/middle/typeck/infer/sub.rs index e6bcdf3e71f..0aba993512b 100644 --- a/src/rustc/middle/typeck/infer/sub.rs +++ b/src/rustc/middle/typeck/infer/sub.rs @@ -1,6 +1,6 @@ use combine::*; use unify::*; -use to_str::to_str; +use to_str::ToStr; enum Sub = combine_fields; // "subtype", "subregion" etc @@ -20,14 +20,14 @@ impl Sub: combine { Sub(opp).tys(b, a) } - fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region> { + fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region> { let opp = combine_fields { a_is_expected: !self.a_is_expected,.. *self }; Sub(opp).regions(b, a) } - fn regions(a: ty::region, b: ty::region) -> cres<ty::region> { + fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> { debug!("%s.regions(%s, %s)", self.tag(), a.to_str(self.infcx), diff --git a/src/rustc/middle/typeck/infer/to_str.rs b/src/rustc/middle/typeck/infer/to_str.rs index 7acfdcac424..c98a217a746 100644 --- a/src/rustc/middle/typeck/infer/to_str.rs +++ b/src/rustc/middle/typeck/infer/to_str.rs @@ -1,29 +1,29 @@ use integral::{int_ty_set}; use unify::{var_value, redirect, root}; -trait to_str { +trait ToStr { fn to_str(cx: infer_ctxt) -> ~str; } -impl ty::t: to_str { +impl ty::t: ToStr { fn to_str(cx: infer_ctxt) -> ~str { ty_to_str(cx.tcx, self) } } -impl ty::mt: to_str { +impl ty::mt: ToStr { fn to_str(cx: infer_ctxt) -> ~str { mt_to_str(cx.tcx, self) } } -impl ty::region: to_str { +impl ty::Region: ToStr { fn to_str(cx: infer_ctxt) -> ~str { util::ppaux::region_to_str(cx.tcx, self) } } -impl<V:Copy to_str> bound<V>: to_str { +impl<V:Copy ToStr> bound<V>: ToStr { fn to_str(cx: infer_ctxt) -> ~str { match self { Some(v) => v.to_str(cx), @@ -32,7 +32,7 @@ impl<V:Copy to_str> bound<V>: to_str { } } -impl<T:Copy to_str> bounds<T>: to_str { +impl<T:Copy ToStr> bounds<T>: ToStr { fn to_str(cx: infer_ctxt) -> ~str { fmt!("{%s <: %s}", self.lb.to_str(cx), @@ -40,7 +40,7 @@ impl<T:Copy to_str> bounds<T>: to_str { } } -impl int_ty_set: to_str { +impl int_ty_set: ToStr { fn to_str(_cx: infer_ctxt) -> ~str { match self { int_ty_set(v) => uint::to_str(v, 10u) @@ -48,7 +48,7 @@ impl int_ty_set: to_str { } } -impl<V:Copy vid, T:Copy to_str> var_value<V, T>: to_str { +impl<V:Copy vid, T:Copy ToStr> var_value<V, T>: ToStr { fn to_str(cx: infer_ctxt) -> ~str { match self { redirect(vid) => fmt!("redirect(%s)", vid.to_str()), diff --git a/src/rustc/middle/typeck/infer/unify.rs b/src/rustc/middle/typeck/infer/unify.rs index 7ccbaa40ada..f865705563c 100644 --- a/src/rustc/middle/typeck/infer/unify.rs +++ b/src/rustc/middle/typeck/infer/unify.rs @@ -1,6 +1,6 @@ use combine::combine; use integral::*; -use to_str::to_str; +use to_str::ToStr; use std::smallintmap::SmallIntMap; enum var_value<V:Copy, T:Copy> { @@ -46,7 +46,7 @@ impl infer_ctxt { } } - fn set<V:Copy vid, T:Copy to_str>( + fn set<V:Copy vid, T:Copy ToStr>( vb: &vals_and_bindings<V, T>, vid: V, +new_v: var_value<V, T>) { diff --git a/src/rustc/middle/typeck/rscope.rs b/src/rustc/middle/typeck/rscope.rs index 9b9695088f3..d379607d6a8 100644 --- a/src/rustc/middle/typeck/rscope.rs +++ b/src/rustc/middle/typeck/rscope.rs @@ -2,21 +2,21 @@ use result::Result; use syntax::parse::token::special_idents; trait region_scope { - fn anon_region(span: span) -> Result<ty::region, ~str>; - fn self_region(span: span) -> Result<ty::region, ~str>; - fn named_region(span: span, id: ast::ident) -> Result<ty::region, ~str>; + fn anon_region(span: span) -> Result<ty::Region, ~str>; + fn self_region(span: span) -> Result<ty::Region, ~str>; + fn named_region(span: span, id: ast::ident) -> Result<ty::Region, ~str>; } enum empty_rscope { empty_rscope } impl empty_rscope: region_scope { - fn anon_region(_span: span) -> Result<ty::region, ~str> { + fn anon_region(_span: span) -> Result<ty::Region, ~str> { result::Ok(ty::re_static) } - fn self_region(_span: span) -> Result<ty::region, ~str> { + fn self_region(_span: span) -> Result<ty::Region, ~str> { result::Err(~"only the static region is allowed here") } fn named_region(_span: span, _id: ast::ident) - -> Result<ty::region, ~str> + -> Result<ty::Region, ~str> { result::Err(~"only the static region is allowed here") } @@ -24,17 +24,17 @@ impl empty_rscope: region_scope { enum type_rscope = Option<ty::region_variance>; impl type_rscope: region_scope { - fn anon_region(_span: span) -> Result<ty::region, ~str> { + fn anon_region(_span: span) -> Result<ty::Region, ~str> { match *self { Some(_) => result::Ok(ty::re_bound(ty::br_self)), None => result::Err(~"to use region types here, the containing \ type must be declared with a region bound") } } - fn self_region(span: span) -> Result<ty::region, ~str> { + fn self_region(span: span) -> Result<ty::Region, ~str> { self.anon_region(span) } - fn named_region(span: span, id: ast::ident) -> Result<ty::region, ~str> { + fn named_region(span: span, id: ast::ident) -> Result<ty::Region, ~str> { do empty_rscope.named_region(span, id).chain_err |_e| { result::Err(~"named regions other than `self` are not \ allowed as part of a type declaration") @@ -42,26 +42,26 @@ impl type_rscope: region_scope { } } -fn bound_self_region(rp: Option<ty::region_variance>) -> Option<ty::region> { +fn bound_self_region(rp: Option<ty::region_variance>) -> Option<ty::Region> { match rp { Some(_) => Some(ty::re_bound(ty::br_self)), None => None } } -enum anon_rscope = {anon: ty::region, base: region_scope}; -fn in_anon_rscope<RS: region_scope Copy Owned>(self: RS, r: ty::region) +enum anon_rscope = {anon: ty::Region, base: region_scope}; +fn in_anon_rscope<RS: region_scope Copy Owned>(self: RS, r: ty::Region) -> @anon_rscope { @anon_rscope({anon: r, base: self as region_scope}) } impl @anon_rscope: region_scope { - fn anon_region(_span: span) -> Result<ty::region, ~str> { + fn anon_region(_span: span) -> Result<ty::Region, ~str> { result::Ok(self.anon) } - fn self_region(span: span) -> Result<ty::region, ~str> { + fn self_region(span: span) -> Result<ty::Region, ~str> { self.base.self_region(span) } - fn named_region(span: span, id: ast::ident) -> Result<ty::region, ~str> { + fn named_region(span: span, id: ast::ident) -> Result<ty::Region, ~str> { self.base.named_region(span, id) } } @@ -76,15 +76,15 @@ fn in_binding_rscope<RS: region_scope Copy Owned>(self: RS) @binding_rscope { base: base, anon_bindings: 0 } } impl @binding_rscope: region_scope { - fn anon_region(_span: span) -> Result<ty::region, ~str> { + fn anon_region(_span: span) -> Result<ty::Region, ~str> { let idx = self.anon_bindings; self.anon_bindings += 1; result::Ok(ty::re_bound(ty::br_anon(idx))) } - fn self_region(span: span) -> Result<ty::region, ~str> { + fn self_region(span: span) -> Result<ty::Region, ~str> { self.base.self_region(span) } - fn named_region(span: span, id: ast::ident) -> Result<ty::region, ~str> { + fn named_region(span: span, id: ast::ident) -> Result<ty::Region, ~str> { do self.base.named_region(span, id).chain_err |_e| { result::Ok(ty::re_bound(ty::br_named(id))) } diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc index dad27b706e6..5d1b217e623 100644 --- a/src/rustc/rustc.rc +++ b/src/rustc/rustc.rc @@ -1,7 +1,7 @@ // -*- rust -*- #[link(name = "rustc", - vers = "0.4", + vers = "0.5", uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf", url = "https://github.com/mozilla/rust/tree/master/src/rustc")]; @@ -19,9 +19,9 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index 37cc016e8ea..0448b022602 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -1,6 +1,5 @@ use std::map::HashMap; use syntax::ast; -use ast::{ty, pat}; use syntax::codemap::{span}; use syntax::visit; use syntax::print; @@ -35,9 +34,7 @@ type flag = HashMap<~str, ()>; fn field_expr(f: ast::field) -> @ast::expr { return f.node.expr; } fn field_exprs(fields: ~[ast::field]) -> ~[@ast::expr] { - let mut es = ~[]; - for fields.each |f| { es.push(f.node.expr); } - return es; + fields.map(|f| f.node.expr) } // Takes a predicate p, returns true iff p is true for any subexpressions @@ -61,22 +58,19 @@ fn loop_query(b: ast::blk, p: fn@(ast::expr_) -> bool) -> bool { return *rs; } -fn has_nonlocal_exits(b: ast::blk) -> bool { - do loop_query(b) |e| { - match e { - ast::expr_break(_) | ast::expr_again(_) => true, - _ => false - } - } -} - -fn may_break(b: ast::blk) -> bool { - do loop_query(b) |e| { - match e { - ast::expr_break(_) => true, - _ => false - } - } +// Takes a predicate p, returns true iff p is true for any subexpressions +// of b -- skipping any inner loops (loop, while, loop_body) +fn block_query(b: ast::blk, p: fn@(@ast::expr) -> bool) -> bool { + let rs = @mut false; + let visit_expr = + |e: @ast::expr, &&flag: @mut bool, v: visit::vt<@mut bool>| { + *flag |= p(e); + visit::visit_expr(e, flag, v) + }; + let v = visit::mk_vt(@{visit_expr: visit_expr + ,.. *visit::default_visitor()}); + visit::visit_block(b, rs, v); + return *rs; } fn local_rhs_span(l: @ast::local, def: span) -> span { @@ -87,8 +81,6 @@ fn local_rhs_span(l: @ast::local, def: span) -> span { } fn is_main_name(path: syntax::ast_map::path) -> bool { - // FIXME (#34): path should be a constrained type, so we know - // the call to last doesn't fail. vec::last(path) == syntax::ast_map::path_name( syntax::parse::token::special_idents::main ) diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 0df5827ed3d..8207082cf20 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -6,7 +6,7 @@ use middle::ty::{bound_copy, bound_const, bound_owned, bound_send, use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid}; use middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method}; use middle::ty::{mt, t, param_bound}; -use middle::ty::{re_bound, re_free, re_scope, re_var, re_static, region}; +use middle::ty::{re_bound, re_free, re_scope, re_var, re_static, Region}; use middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_enum}; use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int}; use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param}; @@ -21,11 +21,10 @@ use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str, purity_to_str}; use syntax::{ast, ast_util}; use syntax::ast_map; -use driver::session::session; fn note_and_explain_region(cx: ctxt, prefix: ~str, - region: ty::region, + region: ty::Region, suffix: ~str) { match explain_region_and_span(cx, region) { (str, Some(span)) => { @@ -42,13 +41,13 @@ fn note_and_explain_region(cx: ctxt, /// Returns a string like "the block at 27:31" that attempts to explain a /// lifetime in a way it might plausibly be understood. -fn explain_region(cx: ctxt, region: ty::region) -> ~str { +fn explain_region(cx: ctxt, region: ty::Region) -> ~str { let (res, _) = explain_region_and_span(cx, region); return res; } -fn explain_region_and_span(cx: ctxt, region: ty::region) +fn explain_region_and_span(cx: ctxt, region: ty::Region) -> (~str, Option<span>) { return match region { @@ -119,8 +118,6 @@ fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str { if cx.sess.verbose() {fmt!("&%u", idx)} else {~"&"} } - // FIXME(#3011) -- even if this arm is removed, exhaustiveness checking - // does not fail br_cap_avoid(id, br) => { if cx.sess.verbose() { fmt!("br_cap_avoid(%?, %s)", id, bound_region_to_str(cx, *br)) @@ -174,7 +171,7 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { // In general, if you are giving a region error message, // you should use `explain_region()` or, better yet, // `note_and_explain_region()` -fn region_to_str(cx: ctxt, region: region) -> ~str { +fn region_to_str(cx: ctxt, region: Region) -> ~str { if cx.sess.verbose() { return fmt!("&%?", region); } @@ -285,8 +282,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { _ => { } } s += ~"("; - let mut strs = ~[]; - for inputs.each |a| { strs.push(fn_input_to_str(cx, *a)); } + let strs = inputs.map(|a| fn_input_to_str(cx, *a)); s += str::connect(strs, ~", "); s += ~")"; if ty::get(output).sty != ty_nil { @@ -341,13 +337,11 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_unboxed_vec(tm) => { ~"unboxed_vec<" + mt_to_str(cx, tm) + ~">" } ty_type => ~"type", ty_rec(elems) => { - let mut strs: ~[~str] = ~[]; - for elems.each |fld| { strs.push(field_to_str(cx, *fld)); } + let strs = elems.map(|fld| field_to_str(cx, *fld)); ~"{" + str::connect(strs, ~",") + ~"}" } ty_tup(elems) => { - let mut strs = ~[]; - for elems.each |elem| { strs.push(ty_to_str(cx, *elem)); } + let strs = elems.map(|elem| ty_to_str(cx, *elem)); ~"(" + str::connect(strs, ~",") + ~")" } ty_fn(ref f) => { @@ -383,7 +377,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn parameterized(cx: ctxt, base: ~str, - self_r: Option<ty::region>, + self_r: Option<ty::Region>, tps: ~[ty::t]) -> ~str { let r_str = match self_r { diff --git a/src/rustdoc/astsrv.rs b/src/rustdoc/astsrv.rs index 2e6cbf579c8..7b2c6fe5f0c 100644 --- a/src/rustdoc/astsrv.rs +++ b/src/rustdoc/astsrv.rs @@ -10,7 +10,7 @@ non-sendableness. use std::map::HashMap; use rustc::driver::session; use session::{basic_options, options}; -use session::session; +use session::Session; use rustc::driver::driver; use syntax::diagnostic; use syntax::diagnostic::handler; @@ -35,7 +35,7 @@ type Ctxt = { type SrvOwner<T> = fn(srv: Srv) -> T; type CtxtHandler<T> = fn~(ctxt: Ctxt) -> T; -type Parser = fn~(session, ~str) -> @ast::crate; +type Parser = fn~(Session, ~str) -> @ast::crate; enum Msg { HandleRequest(fn~(Ctxt)), @@ -57,14 +57,14 @@ fn from_file<T>(file: ~str, owner: SrvOwner<T>) -> T { fn run<T>(owner: SrvOwner<T>, source: ~str, +parse: Parser) -> T { let srv_ = Srv({ - ch: do task::spawn_listener |po| { + ch: do task::spawn_listener |move parse, po| { act(po, source, parse); } }); let res = owner(srv_); comm::send(srv_.ch, Exit); - return res; + move res } fn act(po: comm::Port<Msg>, source: ~str, parse: Parser) { @@ -97,11 +97,11 @@ fn exec<T:Send>( let msg = HandleRequest(fn~(move f, ctxt: Ctxt) { comm::send(ch, f(ctxt)) }); - comm::send(srv.ch, msg); + comm::send(srv.ch, move msg); comm::recv(po) } -fn build_ctxt(sess: session, +fn build_ctxt(sess: Session, ast: @ast::crate) -> Ctxt { use rustc::front::config; @@ -118,7 +118,7 @@ fn build_ctxt(sess: session, } } -fn build_session() -> session { +fn build_session() -> Session { let sopts: @options = basic_options(); let codemap = codemap::new_codemap(); let error_handlers = build_error_handlers(codemap); @@ -137,7 +137,7 @@ type ErrorHandlers = { // Build a custom error handler that will allow us to ignore non-fatal // errors fn build_error_handlers( - codemap: codemap::codemap + codemap: codemap::CodeMap ) -> ErrorHandlers { type DiagnosticHandler = { @@ -156,13 +156,13 @@ fn build_error_handlers( fn note(msg: &str) { self.inner.note(msg) } fn bug(msg: &str) -> ! { self.inner.bug(msg) } fn unimpl(msg: &str) -> ! { self.inner.unimpl(msg) } - fn emit(cmsp: Option<(codemap::codemap, codemap::span)>, + fn emit(cmsp: Option<(codemap::CodeMap, codemap::span)>, msg: &str, lvl: diagnostic::level) { self.inner.emit(cmsp, msg, lvl) } } - let emitter = fn@(cmsp: Option<(codemap::codemap, codemap::span)>, + let emitter = fn@(cmsp: Option<(codemap::CodeMap, codemap::span)>, msg: &str, lvl: diagnostic::level) { diagnostic::emit(cmsp, msg, lvl); }; diff --git a/src/rustdoc/attr_parser.rs b/src/rustdoc/attr_parser.rs index d2b314adf9c..2b16112fe16 100644 --- a/src/rustdoc/attr_parser.rs +++ b/src/rustdoc/attr_parser.rs @@ -36,27 +36,6 @@ mod test { } } -fn doc_meta( - attrs: ~[ast::attribute] -) -> Option<@ast::meta_item> { - - /*! - * Given a vec of attributes, extract the meta_items contained in the \ - * doc attribute - */ - - let doc_metas = doc_metas(attrs); - if vec::is_not_empty(doc_metas) { - if vec::len(doc_metas) != 1u { - warn!("ignoring %u doc attributes", vec::len(doc_metas) - 1u); - } - Some(doc_metas[0]) - } else { - None - } - -} - fn doc_metas( attrs: ~[ast::attribute] ) -> ~[@ast::meta_item] { @@ -102,11 +81,13 @@ fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() { } fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> { - match doc_meta(attrs) { - Some(meta) => { - attr::get_meta_item_value_str(meta) - } - None => None + let doc_strs = do doc_metas(attrs).filter_map |meta| { + attr::get_meta_item_value_str(*meta) + }; + if doc_strs.is_empty() { + None + } else { + Some(str::connect(doc_strs, "\n")) } } @@ -158,3 +139,12 @@ fn should_not_parse_non_hidden_attribute() { let attrs = test::parse_attributes(source); assert parse_hidden(attrs) == false; } + +#[test] +fn should_concatenate_multiple_doc_comments() { + let source = ~"/// foo\n/// bar"; + let desc = parse_desc(test::parse_attributes(source)); + assert desc == Some(~"foo\nbar"); +} + + diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs index d5f0ca9f507..0748f603580 100644 --- a/src/rustdoc/attr_pass.rs +++ b/src/rustdoc/attr_pass.rs @@ -52,7 +52,7 @@ fn fold_crate( { topmod: doc::ModDoc_({ item: { - name: option::get_default(&attrs.name, doc.topmod.name()), + name: option::get_default(attrs.name, doc.topmod.name()), .. doc.topmod.item }, .. *doc.topmod @@ -93,7 +93,7 @@ fn parse_item_attrs<T:Send>( srv: astsrv::Srv, id: doc::AstId, +parse_attrs: fn~(~[ast::attribute]) -> T) -> T { - do astsrv::exec(srv) |ctxt| { + do astsrv::exec(srv) |move parse_attrs, ctxt| { let attrs = match ctxt.ast_map.get(id) { ast_map::node_item(item, _) => item.attrs, ast_map::node_foreign_item(item, _, _) => item.attrs, @@ -151,13 +151,13 @@ fn fold_enum( node: ast::item_enum(enum_definition, _), _ }, _) => { let ast_variant = option::get( - &vec::find(enum_definition.variants, |v| { + vec::find(enum_definition.variants, |v| { to_str(v.node.name) == variant.name })); attr_parser::parse_desc(ast_variant.node.attrs) } - _ => fail #fmt("Enum variant %s has id that's not bound \ + _ => fail fmt!("Enum variant %s has id that's not bound \ to an enum item", variant.name) } }; diff --git a/src/rustdoc/demo.rs b/src/rustdoc/demo.rs index bf1cdf2622e..1223f6b9723 100644 --- a/src/rustdoc/demo.rs +++ b/src/rustdoc/demo.rs @@ -7,7 +7,7 @@ * for testing purposes. It doesn't surve any functional * purpose. This here, for instance, is just some filler text. * - * FIXME (#1654): It would be nice if we could run some automated + * FIXME (#3731): It would be nice if we could run some automated * tests on this file */ diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs index 0764d9e2432..2d5bf5fc3c6 100644 --- a/src/rustdoc/doc.rs +++ b/src/rustdoc/doc.rs @@ -377,7 +377,7 @@ impl IndexEntry : cmp::Eq { impl Doc { fn CrateDoc() -> CrateDoc { - option::get(&vec::foldl(None, self.pages, |_m, page| { + option::get(vec::foldl(None, self.pages, |_m, page| { match *page { doc::CratePage(doc) => Some(doc), _ => None diff --git a/src/rustdoc/fold.rs b/src/rustdoc/fold.rs index 28dbdaeea80..e8d914bd2cb 100644 --- a/src/rustdoc/fold.rs +++ b/src/rustdoc/fold.rs @@ -71,18 +71,18 @@ fn mk_fold<T:Copy>( ) -> Fold<T> { Fold({ ctxt: ctxt, - fold_doc: fold_doc, - fold_crate: fold_crate, - fold_item: fold_item, - fold_mod: fold_mod, - fold_nmod: fold_nmod, - fold_fn: fold_fn, - fold_const: fold_const, - fold_enum: fold_enum, - fold_trait: fold_trait, - fold_impl: fold_impl, - fold_type: fold_type, - fold_struct: fold_struct, + fold_doc: move fold_doc, + fold_crate: move fold_crate, + fold_item: move fold_item, + fold_mod: move fold_mod, + fold_nmod: move fold_nmod, + fold_fn: move fold_fn, + fold_const: move fold_const, + fold_enum: move fold_enum, + fold_trait: move fold_trait, + fold_impl: move fold_impl, + fold_type: move fold_type, + fold_struct: move fold_struct }) } diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs index 924e4be6305..99357e254a4 100644 --- a/src/rustdoc/markdown_pass.rs +++ b/src/rustdoc/markdown_pass.rs @@ -9,13 +9,14 @@ export mk_pass; export header_kind, header_name, header_text; fn mk_pass(+writer_factory: WriterFactory) -> Pass { - let f = fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { + let f = fn~(move writer_factory, + srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { run(srv, doc, copy writer_factory) }; { name: ~"markdown", - f: f + f: move f } } @@ -44,7 +45,7 @@ fn run( ~"mods last", mods_last ).f(srv, doc); - write_markdown(sorted_doc, writer_factory); + write_markdown(sorted_doc, move writer_factory); return doc; } @@ -84,8 +85,9 @@ fn write_markdown( doc: doc::Doc, +writer_factory: WriterFactory ) { - // FIXME #2484: There is easy parallelism to be had here but - // we don't want to spawn too many pandoc processes + // There is easy parallelism to be had here, but + // we don't want to spawn too many pandoc processes. + // (See #2484, which is closed.) do doc.pages.map |page| { let ctxt = { w: writer_factory(*page) @@ -117,9 +119,9 @@ fn should_request_new_writer_for_each_page() { let (srv, doc) = test::create_doc_srv(~"mod a { }"); // Split the document up into pages let doc = page_pass::mk_pass(config::DocPerMod).f(srv, doc); - write_markdown(doc, writer_factory); + write_markdown(doc, move writer_factory); // We expect two pages to have been written - for iter::repeat(2u) { + for iter::repeat(2) { comm::recv(po); } } @@ -149,8 +151,8 @@ fn should_write_title_for_each_page() { let (srv, doc) = test::create_doc_srv( ~"#[link(name = \"core\")]; mod a { }"); let doc = page_pass::mk_pass(config::DocPerMod).f(srv, doc); - write_markdown(doc, writer_factory); - for iter::repeat(2u) { + write_markdown(doc, move writer_factory); + for iter::repeat(2) { let (page, markdown) = comm::recv(po); match page { doc::CratePage(_) => { @@ -844,7 +846,7 @@ mod test { doc: doc::Doc ) -> ~str { let (writer_factory, po) = markdown_writer::future_writer_factory(); - write_markdown(doc, writer_factory); + write_markdown(doc, move writer_factory); return comm::recv(po).second(); } @@ -853,7 +855,7 @@ mod test { doc: doc::Doc ) -> ~str { let (writer_factory, po) = markdown_writer::future_writer_factory(); - let pass = mk_pass(writer_factory); + let pass = mk_pass(move writer_factory); pass.f(srv, doc); return comm::recv(po).second(); } diff --git a/src/rustdoc/markdown_writer.rs b/src/rustdoc/markdown_writer.rs index f505f9d0b99..1ed007def63 100644 --- a/src/rustdoc/markdown_writer.rs +++ b/src/rustdoc/markdown_writer.rs @@ -136,17 +136,20 @@ fn readclose(fd: libc::c_int) -> ~str { // Copied from run::program_output let file = os::fdopen(fd); let reader = io::FILE_reader(file, false); - let mut buf = ~""; - while !reader.eof() { - let bytes = reader.read_bytes(4096u); - buf += str::from_bytes(bytes); - } + let buf = io::with_bytes_writer(|writer| { + let mut bytes = [mut 0, ..4096]; + while !reader.eof() { + let nread = reader.read(bytes, bytes.len()); + writer.write(bytes.view(0, nread)); + } + }); os::fclose(file); - return buf; + str::from_bytes(buf) } fn generic_writer(+process: fn~(markdown: ~str)) -> Writer { - let ch = do task::spawn_listener |po: comm::Port<WriteInstr>| { + let ch = do task::spawn_listener + |move process, po: comm::Port<WriteInstr>| { let mut markdown = ~""; let mut keep_going = true; while keep_going { @@ -155,7 +158,7 @@ fn generic_writer(+process: fn~(markdown: ~str)) -> Writer { Done => keep_going = false } } - process(markdown); + process(move markdown); }; fn~(+instr: WriteInstr) { @@ -274,22 +277,22 @@ fn future_writer_factory( let writer_ch = comm::Chan(&writer_po); do task::spawn { let (writer, future) = future_writer(); - comm::send(writer_ch, writer); + comm::send(writer_ch, move writer); let s = future::get(&future); comm::send(markdown_ch, (page, s)); } comm::recv(writer_po) }; - (writer_factory, markdown_po) + (move writer_factory, markdown_po) } fn future_writer() -> (Writer, future::Future<~str>) { let (chan, port) = pipes::stream(); - let writer = fn~(+instr: WriteInstr) { + let writer = fn~(move chan, +instr: WriteInstr) { chan.send(copy instr); }; - let future = do future::from_fn { + let future = do future::from_fn |move port| { let mut res = ~""; loop { match port.recv() { @@ -299,5 +302,5 @@ fn future_writer() -> (Writer, future::Future<~str>) { } res }; - (writer, future) + (move writer, move future) } diff --git a/src/rustdoc/page_pass.rs b/src/rustdoc/page_pass.rs index ad3f679a97c..fc911d23e04 100644 --- a/src/rustdoc/page_pass.rs +++ b/src/rustdoc/page_pass.rs @@ -46,7 +46,7 @@ fn make_doc_from_pages(page_port: PagePort) -> doc::Doc { loop { let val = comm::recv(page_port); if val.is_some() { - pages += ~[option::unwrap(val)]; + pages += ~[option::unwrap(move val)]; } else { break; } diff --git a/src/rustdoc/parse.rs b/src/rustdoc/parse.rs index 59d64f18d59..7fc17dfe838 100644 --- a/src/rustdoc/parse.rs +++ b/src/rustdoc/parse.rs @@ -20,16 +20,16 @@ fn from_str(source: ~str) -> @ast::crate { ~"-", @source, ~[], parse::new_parse_sess(None)) } -fn from_file_sess(sess: session::session, file: &Path) -> @ast::crate { +fn from_file_sess(sess: session::Session, file: &Path) -> @ast::crate { parse::parse_crate_from_file( file, cfg(sess, file_input(*file)), sess.parse_sess) } -fn from_str_sess(sess: session::session, source: ~str) -> @ast::crate { +fn from_str_sess(sess: session::Session, source: ~str) -> @ast::crate { parse::parse_crate_from_source_str( ~"-", @source, cfg(sess, str_input(source)), sess.parse_sess) } -fn cfg(sess: session::session, input: driver::input) -> ast::crate_cfg { +fn cfg(sess: session::Session, input: driver::input) -> ast::crate_cfg { driver::default_configuration(sess, ~"rustdoc", input) } diff --git a/src/rustdoc/rustdoc.rc b/src/rustdoc/rustdoc.rc index f8714b0e9ba..e8f0ec00545 100644 --- a/src/rustdoc/rustdoc.rc +++ b/src/rustdoc/rustdoc.rc @@ -1,7 +1,7 @@ //! Rustdoc - The Rust documentation generator #[link(name = "rustdoc", - vers = "0.4", + vers = "0.5", uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; @@ -18,10 +18,10 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod rustc(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod rustc(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; use std::par; diff --git a/src/rustdoc/rustdoc.rs b/src/rustdoc/rustdoc.rs index b79b6ba2189..e09f57339a7 100755 --- a/src/rustdoc/rustdoc.rs +++ b/src/rustdoc/rustdoc.rs @@ -87,5 +87,5 @@ fn time<T>(what: ~str, f: fn() -> T) -> T { let rv = f(); let end = std::time::precise_time_s(); info!("time: %3.3f s %s", end - start, what); - return rv; + move rv } diff --git a/src/rustdoc/sort_pass.rs b/src/rustdoc/sort_pass.rs index da3cf239538..d4d9e7e5156 100644 --- a/src/rustdoc/sort_pass.rs +++ b/src/rustdoc/sort_pass.rs @@ -10,7 +10,7 @@ type ItemLtEq = pure fn~(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool; fn mk_pass(name: ~str, +lteq: ItemLtEq) -> Pass { { name: name, - f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { + f: fn~(move lteq, srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { run(srv, doc, lteq) } } diff --git a/src/rustdoc/text_pass.rs b/src/rustdoc/text_pass.rs index b929cd0aa91..f5ba9e9a2c9 100644 --- a/src/rustdoc/text_pass.rs +++ b/src/rustdoc/text_pass.rs @@ -7,7 +7,7 @@ export mk_pass; fn mk_pass(name: ~str, +op: fn~(~str) -> ~str) -> Pass { { name: name, - f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { + f: fn~(move op, srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { run(srv, doc, op) } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index fc2049507ee..498a4e137f0 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -493,5 +493,7 @@ extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, } extern "C" void LLVMSetDebug(int Enabled) { +#ifndef NDEBUG DebugFlag = Enabled; +#endif } diff --git a/src/snapshots.txt b/src/snapshots.txt index e1469d99d2b..05a4ec10c45 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,27 @@ +S 2012-10-09 cd6f24f + macos-i386 7f2f2857eac33ff0792e4ea7a3ff91a09304fcab + macos-x86_64 bb3d191e2e31cb754223ab162281fd9727e63ea9 + freebsd-x86_64 a2b5e9dddfa8f21cc8a068b77a47ba5425bfdcc6 + linux-i386 7c13c04ed6593dc77db6b3b56f057213f567a32b + linux-x86_64 7860cdd4023e9d6bec892dc5a7144b286a7fd38e + winnt-i386 9e917c2f3d72f72042d5e9b60b45790740676e82 + +S 2012-10-08 a477c5a + macos-i386 c059c3d5bd113f7edec48a4c2128f4b6138c3db8 + macos-x86_64 f121f4e2d831434f7825f72f3d328c11b13a522f + freebsd-x86_64 7f0de8feefc13267cbdebd299adc6b06f832cb9f + linux-i386 5975e794e5939034516fe888b70b532d34327bb2 + linux-x86_64 6dd88754f170f85d268e9430f7728efe43522383 + winnt-i386 76655d202b59c9b61cae860110ad5d0ca6e12cbf + +S 2012-10-07 d301dd3 + macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b + macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d + freebsd-x86_64 784ac161fee0351281e3edfefc81a0c1b5d068b5 + linux-i386 4d945d7e0de4e4544928ed5aa111d1508522c697 + linux-x86_64 9bea5436042dd4bb7e682d3a10d0d51c3590b531 + winnt-i386 62de5eea3eba70a2f4a2b4d42c72aa2fa75f999a + S 2012-10-05 937f8f4 macos-i386 8b5ddc78b3004e539c6fbe224e492e4a6a1bc867 macos-x86_64 03793e0136512c644edfb5f13cc5bb7d67fb24e5 diff --git a/src/test/auxiliary/anon_trait_static_method_lib.rs b/src/test/auxiliary/anon_trait_static_method_lib.rs new file mode 100644 index 00000000000..ec9398dea15 --- /dev/null +++ b/src/test/auxiliary/anon_trait_static_method_lib.rs @@ -0,0 +1,10 @@ +pub struct Foo { + x: int +} + +pub impl Foo { + static fn new() -> Foo { + Foo { x: 3 } + } +} + diff --git a/src/test/auxiliary/cci_class_6.rs b/src/test/auxiliary/cci_class_6.rs index 6cf86aff055..da1a8b5f0ed 100644 --- a/src/test/auxiliary/cci_class_6.rs +++ b/src/test/auxiliary/cci_class_6.rs @@ -21,7 +21,7 @@ fn cat<U>(in_x : uint, in_y : int, -in_info: ~[U]) -> cat<U> { cat { meows: in_x, how_hungry: in_y, - info: in_info + info: move in_info } } diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs index 288fe66dd20..ca2af387587 100644 --- a/src/test/auxiliary/cci_class_cast.rs +++ b/src/test/auxiliary/cci_class_cast.rs @@ -13,7 +13,7 @@ struct cat { } impl cat : ToStr { - fn to_str() -> ~str { self.name } + pure fn to_str() -> ~str { self.name } } priv impl cat { diff --git a/src/test/auxiliary/issue_3136_a.rc b/src/test/auxiliary/issue_3136_a.rc new file mode 100644 index 00000000000..532c669bd1d --- /dev/null +++ b/src/test/auxiliary/issue_3136_a.rc @@ -0,0 +1,3 @@ +#[crate_type = "lib"]; + +pub mod issue_3136_a; diff --git a/src/test/auxiliary/issue_3136_a.rs b/src/test/auxiliary/issue_3136_a.rs new file mode 100644 index 00000000000..b3af6880323 --- /dev/null +++ b/src/test/auxiliary/issue_3136_a.rs @@ -0,0 +1,15 @@ +trait x { + fn use_x<T>(); +} +enum y = (); +impl y:x { + fn use_x<T>() { + struct foo { //~ ERROR quux + i: () + } + fn new_foo<T>(i: ()) -> foo { + foo { i: i } + } + } +} + diff --git a/src/test/auxiliary/test_comm.rs b/src/test/auxiliary/test_comm.rs index 77f107fda09..18960d0ad8a 100644 --- a/src/test/auxiliary/test_comm.rs +++ b/src/test/auxiliary/test_comm.rs @@ -7,7 +7,6 @@ use libc::size_t; -export port::{}; export port; export recv; @@ -65,13 +64,13 @@ fn recv<T: Send>(p: port<T>) -> T { recv_((**p).po) } /// Receive on a raw port pointer fn recv_<T: Send>(p: *rust_port) -> T { - let yield = 0u; + let yield = 0; let yieldp = ptr::addr_of(&yield); let mut res; res = rusti::init::<T>(); rustrt::port_recv(ptr::addr_of(&res) as *uint, p, yieldp); - if yield != 0u { + if yield != 0 { // Data isn't available yet, so res has not been initialized. task::yield(); } else { @@ -79,7 +78,7 @@ fn recv_<T: Send>(p: *rust_port) -> T { // this is a good place to yield task::yield(); } - return res; + move res } diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 5acde71c6fd..c877d1d3657 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -119,7 +119,7 @@ fn bfs(graph: graph, key: node_id) -> bfs_result { Q.add_back(key); marks[key] = key; - while Q.size() > 0u { + while Q.size() > 0 { let t = Q.pop_front(); do graph[t].each() |k| { @@ -131,7 +131,7 @@ fn bfs(graph: graph, key: node_id) -> bfs_result { }; } - vec::from_mut(marks) + vec::from_mut(move marks) } /** @@ -167,11 +167,11 @@ fn bfs2(graph: graph, key: node_id) -> bfs_result { } } - let mut i = 0u; + let mut i = 0; while vec::any(colors, is_gray) { // Do the BFS. log(info, fmt!("PBFS iteration %?", i)); - i += 1u; + i += 1; colors = do colors.mapi() |i, c| { let c : color = *c; match c { @@ -245,13 +245,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result { i += 1; let old_len = colors.len(); - let color = arc::ARC(colors); + let color = arc::ARC(move colors); let color_vec = arc::get(&color); // FIXME #3387 requires this temp colors = do par::mapi_factory(*color_vec) { let colors = arc::clone(&color); let graph = arc::clone(&graph); - fn~(+i: uint, +c: color) -> color { + fn~(move graph, move colors, +i: uint, +c: color) -> color { let c : color = c; let colors = arc::get(&colors); let graph = arc::get(&graph); @@ -388,7 +388,7 @@ fn main() { let args = os::args(); let args = if os::getenv(~"RUST_BENCH").is_some() { ~[~"", ~"15", ~"48"] - } else if args.len() <= 1u { + } else if args.len() <= 1 { ~[~"", ~"10", ~"16"] } else { args @@ -400,21 +400,21 @@ fn main() { let do_sequential = true; let start = time::precise_time_s(); - let edges = make_edges(scale, 16u); + let edges = make_edges(scale, 16); let stop = time::precise_time_s(); io::stdout().write_line(fmt!("Generated %? edges in %? seconds.", vec::len(edges), stop - start)); let start = time::precise_time_s(); - let graph = make_graph(1u << scale, edges); + let graph = make_graph(1 << scale, edges); let stop = time::precise_time_s(); - let mut total_edges = 0u; + let mut total_edges = 0; vec::each(graph, |edges| { total_edges += edges.len(); true }); io::stdout().write_line(fmt!("Generated graph with %? edges in %? seconds.", - total_edges / 2u, + total_edges / 2, stop - start)); let mut total_seq = 0.0; diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index d60937af13c..88ca0d3e0c2 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -19,7 +19,7 @@ use io::WriterUtil; use pipes::{Port, Chan, SharedChan}; macro_rules! move_out ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) enum request { @@ -50,26 +50,26 @@ fn run(args: &[~str]) { let (to_parent, from_child) = pipes::stream(); let (to_child, from_parent) = pipes::stream(); - let to_child = SharedChan(to_child); + let to_child = SharedChan(move to_child); let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); let num_bytes = 100; let start = std::time::precise_time_s(); let mut worker_results = ~[]; - for uint::range(0u, workers) |i| { + for uint::range(0, workers) |_i| { let to_child = to_child.clone(); do task::task().future_result(|+r| { - worker_results.push(r); - }).spawn { - for uint::range(0u, size / workers) |_i| { + worker_results.push(move r); + }).spawn |move to_child| { + for uint::range(0, size / workers) |_i| { //error!("worker %?: sending %? bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //error!("worker %? exiting", i); }; } - do task::spawn { + do task::spawn |move from_parent, move to_parent| { server(from_parent, to_parent); } diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index e2d115600ef..ce3fd5134ac 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -15,7 +15,7 @@ use io::WriterUtil; use pipes::{Port, PortSet, Chan}; macro_rules! move_out ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) enum request { @@ -46,27 +46,27 @@ fn run(args: &[~str]) { let (to_parent, from_child) = pipes::stream(); let (to_child, from_parent_) = pipes::stream(); let from_parent = PortSet(); - from_parent.add(from_parent_); + from_parent.add(move from_parent_); let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); let num_bytes = 100; let start = std::time::precise_time_s(); let mut worker_results = ~[]; - for uint::range(0u, workers) |i| { + for uint::range(0, workers) |_i| { let (to_child, from_parent_) = pipes::stream(); - from_parent.add(from_parent_); + from_parent.add(move from_parent_); do task::task().future_result(|+r| { - worker_results.push(r); - }).spawn { - for uint::range(0u, size / workers) |_i| { + worker_results.push(move r); + }).spawn |move to_child| { + for uint::range(0, size / workers) |_i| { //error!("worker %?: sending %? bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //error!("worker %? exiting", i); }; } - do task::spawn { + do task::spawn |move from_parent, move to_parent| { server(from_parent, to_parent); } diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index f657884eeef..3ec89567d20 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -33,7 +33,7 @@ fn recv(p: &pipe) -> uint { fn init() -> (pipe,pipe) { let m = arc::MutexARC(~[]); - ((&m).clone(), m) + ((&m).clone(), move m) } @@ -41,18 +41,18 @@ fn thread_ring(i: uint, count: uint, +num_chan: pipe, +num_port: pipe) { - let mut num_chan <- Some(num_chan); - let mut num_port <- Some(num_port); + let mut num_chan <- Some(move num_chan); + let mut num_port <- Some(move num_port); // Send/Receive lots of messages. for uint::range(0u, count) |j| { //error!("task %?, iter %?", i, j); let mut num_chan2 = option::swap_unwrap(&mut num_chan); let mut num_port2 = option::swap_unwrap(&mut num_port); send(&num_chan2, i * j); - num_chan = Some(num_chan2); + num_chan = Some(move num_chan2); let _n = recv(&num_port2); //log(error, _n); - num_port = Some(num_port2); + num_port = Some(move num_port2); }; } @@ -70,7 +70,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = init(); - let mut num_chan = Some(num_chan); + let mut num_chan = Some(move num_chan); let start = time::precise_time_s(); @@ -82,22 +82,22 @@ fn main() { let (new_chan, num_port) = init(); let num_chan2 = ~mut None; *num_chan2 <-> num_chan; - let num_port = ~mut Some(num_port); + let num_port = ~mut Some(move num_port); let new_future = future::spawn(|move num_chan2, move num_port| { let mut num_chan = None; num_chan <-> *num_chan2; let mut num_port1 = None; num_port1 <-> *num_port; thread_ring(i, msg_per_task, - option::unwrap(num_chan), - option::unwrap(num_port1)) + option::unwrap(move num_chan), + option::unwrap(move num_port1)) }); - futures.push(new_future); - num_chan = Some(new_chan); + futures.push(move new_future); + num_chan = Some(move new_chan); }; // do our iteration - thread_ring(0u, msg_per_task, option::unwrap(num_chan), num_port); + thread_ring(0, msg_per_task, option::unwrap(move num_chan), move num_port); // synchronize for futures.each |f| { future::get(f) }; diff --git a/src/test/bench/msgsend-ring-pipes.rs b/src/test/bench/msgsend-ring-pipes.rs index 73942d4ddf8..68429ee01bb 100644 --- a/src/test/bench/msgsend-ring-pipes.rs +++ b/src/test/bench/msgsend-ring-pipes.rs @@ -24,7 +24,7 @@ proto! ring ( fn macros() { #macro[ [#move_out[x], - unsafe { let y <- *ptr::addr_of(&x); y }] + unsafe { let y <- *ptr::addr_of(&x); move y }] ]; } @@ -32,18 +32,18 @@ fn thread_ring(i: uint, count: uint, +num_chan: ring::client::num, +num_port: ring::server::num) { - let mut num_chan <- Some(num_chan); - let mut num_port <- Some(num_port); + let mut num_chan <- Some(move num_chan); + let mut num_port <- Some(move num_port); // Send/Receive lots of messages. - for uint::range(0u, count) |j| { + for uint::range(0, count) |j| { //error!("task %?, iter %?", i, j); let mut num_chan2 = None; let mut num_port2 = None; num_chan2 <-> num_chan; num_port2 <-> num_port; - num_chan = Some(ring::client::num(option::unwrap(num_chan2), i * j)); - let port = option::unwrap(num_port2); - match recv(port) { + num_chan = Some(ring::client::num(option::unwrap(move num_chan2), i * j)); + let port = option::unwrap(move num_port2); + match recv(move port) { ring::num(_n, p) => { //log(error, _n); num_port = Some(move_out!(p)); @@ -66,7 +66,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = ring::init(); - let mut num_chan = Some(num_chan); + let mut num_chan = Some(move num_chan); let start = time::precise_time_s(); @@ -78,7 +78,7 @@ fn main() { let (new_chan, num_port) = ring::init(); let num_chan2 = ~mut None; *num_chan2 <-> num_chan; - let num_port = ~mut Some(num_port); + let num_port = ~mut Some(move num_port); let new_future = do future::spawn |move num_chan2, move num_port| { let mut num_chan = None; @@ -86,15 +86,15 @@ fn main() { let mut num_port1 = None; num_port1 <-> *num_port; thread_ring(i, msg_per_task, - option::unwrap(num_chan), - option::unwrap(num_port1)) + option::unwrap(move num_chan), + option::unwrap(move num_port1)) }; - futures.push(new_future); - num_chan = Some(new_chan); + futures.push(move new_future); + num_chan = Some(move new_chan); }; // do our iteration - thread_ring(0u, msg_per_task, option::unwrap(num_chan), num_port); + thread_ring(0, msg_per_task, option::unwrap(move num_chan), move num_port); // synchronize for futures.each |f| { future::get(f) }; diff --git a/src/test/bench/msgsend-ring-rw-arcs.rs b/src/test/bench/msgsend-ring-rw-arcs.rs index 386496f459d..5e3d2f7d3e0 100644 --- a/src/test/bench/msgsend-ring-rw-arcs.rs +++ b/src/test/bench/msgsend-ring-rw-arcs.rs @@ -33,7 +33,7 @@ fn recv(p: &pipe) -> uint { fn init() -> (pipe,pipe) { let x = arc::RWARC(~[]); - ((&x).clone(), x) + ((&x).clone(), move x) } @@ -41,18 +41,18 @@ fn thread_ring(i: uint, count: uint, +num_chan: pipe, +num_port: pipe) { - let mut num_chan <- Some(num_chan); - let mut num_port <- Some(num_port); + let mut num_chan <- Some(move num_chan); + let mut num_port <- Some(move num_port); // Send/Receive lots of messages. for uint::range(0u, count) |j| { //error!("task %?, iter %?", i, j); let mut num_chan2 = option::swap_unwrap(&mut num_chan); let mut num_port2 = option::swap_unwrap(&mut num_port); send(&num_chan2, i * j); - num_chan = Some(num_chan2); + num_chan = Some(move num_chan2); let _n = recv(&num_port2); //log(error, _n); - num_port = Some(num_port2); + num_port = Some(move num_port2); }; } @@ -70,7 +70,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = init(); - let mut num_chan = Some(num_chan); + let mut num_chan = Some(move num_chan); let start = time::precise_time_s(); @@ -82,7 +82,7 @@ fn main() { let (new_chan, num_port) = init(); let num_chan2 = ~mut None; *num_chan2 <-> num_chan; - let num_port = ~mut Some(num_port); + let num_port = ~mut Some(move num_port); let new_future = do future::spawn |move num_chan2, move num_port| { let mut num_chan = None; @@ -90,15 +90,15 @@ fn main() { let mut num_port1 = None; num_port1 <-> *num_port; thread_ring(i, msg_per_task, - option::unwrap(num_chan), - option::unwrap(num_port1)) + option::unwrap(move num_chan), + option::unwrap(move num_port1)) }; - futures.push(new_future); - num_chan = Some(new_chan); + futures.push(move new_future); + num_chan = Some(move new_chan); }; // do our iteration - thread_ring(0u, msg_per_task, option::unwrap(num_chan), num_port); + thread_ring(0, msg_per_task, option::unwrap(move num_chan), move num_port); // synchronize for futures.each |f| { future::get(f) }; diff --git a/src/test/bench/msgsend-ring.rs b/src/test/bench/msgsend-ring.rs index 1dfcd241b83..5cb278b0dd2 100644 --- a/src/test/bench/msgsend-ring.rs +++ b/src/test/bench/msgsend-ring.rs @@ -52,7 +52,7 @@ fn main() { get_chan_chan.send(Chan(&p)); thread_ring(i, msg_per_task, num_chan, p) }; - futures.push(new_future); + futures.push(move new_future); num_chan = get_chan.recv(); }; diff --git a/src/test/bench/msgsend.rs b/src/test/bench/msgsend.rs index 8564adaab72..6ab22779c55 100644 --- a/src/test/bench/msgsend.rs +++ b/src/test/bench/msgsend.rs @@ -35,12 +35,12 @@ fn run(args: ~[~str]) { let workers = uint::from_str(args[2]).get(); let start = std::time::precise_time_s(); let mut worker_results = ~[]; - for uint::range(0u, workers) |_i| { + for uint::range(0, workers) |_i| { do task::task().future_result(|+r| { - worker_results.push(r); + worker_results.push(move r); }).spawn { - for uint::range(0u, size / workers) |_i| { - comm::send(to_child, bytes(100u)); + for uint::range(0, size / workers) |_i| { + comm::send(to_child, bytes(100)); } }; } diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs index 70f98934e1b..e7f9312ce38 100644 --- a/src/test/bench/pingpong.rs +++ b/src/test/bench/pingpong.rs @@ -33,7 +33,7 @@ proto! pingpong_unbounded ( // This stuff should go in libcore::pipes macro_rules! move_it ( - { $x:expr } => { let t <- *ptr::addr_of(&($x)); t } + { $x:expr } => { let t <- *ptr::addr_of(&($x)); move t } ) macro_rules! follow ( @@ -41,11 +41,9 @@ macro_rules! follow ( $($message:path($($x: ident),+) -> $next:ident $e:expr)+ } => ( |m| match move m { - $(Some($message($($x,)* next)) => { - // FIXME (#2329) use regular move here once move out of - // enums is supported. - let $next = unsafe { move_it!(next) }; - $e })+ + $(Some($message($($x,)* move next)) => { + let $next = move next; + move $e })+ _ => { fail } } ); @@ -54,11 +52,9 @@ macro_rules! follow ( $($message:path -> $next:ident $e:expr)+ } => ( |m| match move m { - $(Some($message(next)) => { - // FIXME (#2329) use regular move here once move out of - // enums is supported. - let $next = unsafe { move_it!(next) }; - $e })+ + $(Some($message(move next)) => { + let $next = move next; + move $e })+ _ => { fail } } ) @@ -66,7 +62,7 @@ macro_rules! follow ( fn switch<T: Send, Tb: Send, U>(+endp: pipes::RecvPacketBuffered<T, Tb>, f: fn(+v: Option<T>) -> U) -> U { - f(pipes::try_recv(endp)) + f(pipes::try_recv(move endp)) } // Here's the benchmark @@ -76,10 +72,10 @@ fn bounded(count: uint) { let mut ch = do spawn_service(init) |ch| { let mut count = count; - let mut ch = ch; + let mut ch = move ch; while count > 0 { - ch = switch(ch, follow! ( - ping -> next { server::pong(next) } + ch = switch(move ch, follow! ( + ping -> next { server::pong(move next) } )); count -= 1; @@ -88,10 +84,10 @@ fn bounded(count: uint) { let mut count = count; while count > 0 { - let ch_ = client::ping(ch); + let ch_ = client::ping(move ch); - ch = switch(ch_, follow! ( - pong -> next { next } + ch = switch(move ch_, follow! ( + pong -> next { move next } )); count -= 1; @@ -103,10 +99,10 @@ fn unbounded(count: uint) { let mut ch = do spawn_service(init) |ch| { let mut count = count; - let mut ch = ch; + let mut ch = move ch; while count > 0 { - ch = switch(ch, follow! ( - ping -> next { server::pong(next) } + ch = switch(move ch, follow! ( + ping -> next { server::pong(move next) } )); count -= 1; @@ -115,10 +111,10 @@ fn unbounded(count: uint) { let mut count = count; while count > 0 { - let ch_ = client::ping(ch); + let ch_ = client::ping(move ch); - ch = switch(ch_, follow! ( - pong -> next { next } + ch = switch(move ch_, follow! ( + pong -> next { move next } )); count -= 1; diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index a68b345cbc5..3a3c609853b 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -124,7 +124,7 @@ fn make_sequence_processor(sz: uint, from_parent: pipes::Port<~[u8]>, }; //comm::send(to_parent, fmt!("yay{%u}", sz)); - to_parent.send(buffer); + to_parent.send(move buffer); } // given a FASTA file on stdin, process sequence THREE @@ -143,25 +143,25 @@ fn main() { // initialize each sequence sorter - let sizes = ~[1u,2u,3u,4u,6u,12u,18u]; + let sizes = ~[1,2,3,4,6,12,18]; let streams = vec::map(sizes, |_sz| Some(stream())); - let streams = vec::to_mut(streams); + let streams = vec::to_mut(move streams); let mut from_child = ~[]; let to_child = vec::mapi(sizes, |ii, sz| { let sz = *sz; let mut stream = None; stream <-> streams[ii]; - let (to_parent_, from_child_) = option::unwrap(stream); + let (to_parent_, from_child_) = option::unwrap(move stream); - from_child.push(from_child_); + from_child.push(move from_child_); let (to_child, from_parent) = pipes::stream(); - do task::spawn_with(from_parent) |from_parent| { + do task::spawn_with(move from_parent) |move to_parent_, from_parent| { make_sequence_processor(sz, from_parent, to_parent_); }; - to_child + move to_child }); diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index fa97e796bd1..a776c1322d3 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -34,15 +34,15 @@ fn fib(n: int) -> int { } else { let p = pipes::PortSet(); let ch = p.chan(); - task::spawn(|| pfib(ch, n - 1) ); + task::spawn(|move ch| pfib(ch, n - 1) ); let ch = p.chan(); - task::spawn(|| pfib(ch, n - 2) ); + task::spawn(|move ch| pfib(ch, n - 2) ); c.send(p.recv() + p.recv()); } } let (ch, p) = pipes::stream(); - let t = task::spawn(|| pfib(ch, n) ); + let _t = task::spawn(|move ch| pfib(ch, n) ); p.recv() } @@ -73,7 +73,7 @@ fn stress(num_tasks: int) { let mut results = ~[]; for range(0, num_tasks) |i| { do task::task().future_result(|+r| { - results.push(r); + results.push(move r); }).spawn { stress_task(i); } @@ -104,7 +104,7 @@ fn main() { let out = io::stdout(); for range(1, max + 1) |n| { - for range(0, num_trials) |i| { + for range(0, num_trials) |_i| { let start = time::precise_time_ns(); let fibn = fib(n); let stop = time::precise_time_ns(); diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 2e8ef0bac58..921aa8f0657 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -130,7 +130,7 @@ fn main() { let args = os::args(); let grid = if vec::len(args) == 1u { // FIXME create sudoku inline since nested vec consts dont work yet - // (#571) + // (#3733) let g = vec::from_fn(10u, |_i| { vec::to_mut(vec::from_elem(10u, 0 as u8)) }); diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs index f5b2bb1c1c3..55d75ff7c82 100644 --- a/src/test/bench/task-perf-alloc-unwind.rs +++ b/src/test/bench/task-perf-alloc-unwind.rs @@ -78,7 +78,8 @@ fn recurse_or_fail(depth: int, st: Option<st>) { box: @Cons((), st.box), unique: ~Cons((), @*st.unique), fn_box: fn@() -> @nillist { @Cons((), fn_box()) }, - fn_unique: fn~() -> ~nillist { ~Cons((), @*fn_unique()) }, + fn_unique: fn~(move fn_unique) -> ~nillist + { ~Cons((), @*fn_unique()) }, tuple: (@Cons((), st.tuple.first()), ~Cons((), @*st.tuple.second())), vec: st.vec + ~[@Cons((), st.vec.last())], @@ -87,6 +88,6 @@ fn recurse_or_fail(depth: int, st: Option<st>) { } }; - recurse_or_fail(depth, Some(st)); + recurse_or_fail(depth, Some(move st)); } } diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs index 2055993d441..09e6f23004a 100644 --- a/src/test/bench/task-perf-jargon-metal-smoke.rs +++ b/src/test/bench/task-perf-jargon-metal-smoke.rs @@ -9,14 +9,14 @@ fn child_generation(gens_left: uint, -c: pipes::Chan<()>) { // This used to be O(n^2) in the number of generations that ever existed. // With this code, only as many generations are alive at a time as tasks // alive at a time, - let c = ~mut Some(c); - do task::spawn_supervised { + let c = ~mut Some(move c); + do task::spawn_supervised |move c| { let c = option::swap_unwrap(c); if gens_left & 1 == 1 { task::yield(); // shake things up a bit } if gens_left > 0 { - child_generation(gens_left - 1, c); // recurse + child_generation(gens_left - 1, move c); // recurse } else { c.send(()) } @@ -27,14 +27,14 @@ fn main() { let args = os::args(); let args = if os::getenv(~"RUST_BENCH").is_some() { ~[~"", ~"100000"] - } else if args.len() <= 1u { + } else if args.len() <= 1 { ~[~"", ~"100"] } else { copy args }; let (c,p) = pipes::stream(); - child_generation(uint::from_str(args[1]).get(), c); + child_generation(uint::from_str(args[1]).get(), move c); if p.try_recv().is_none() { fail ~"it happened when we slumbered"; } diff --git a/src/test/bench/task-perf-linked-failure.rs b/src/test/bench/task-perf-linked-failure.rs index a692b2f3011..f148d595f9d 100644 --- a/src/test/bench/task-perf-linked-failure.rs +++ b/src/test/bench/task-perf-linked-failure.rs @@ -19,21 +19,21 @@ fn grandchild_group(num_tasks: uint) { comm::recv(comm::Port::<()>()); // block forever } } - #error["Grandchild group getting started"]; + error!("Grandchild group getting started"); for num_tasks.times { // Make sure all above children are fully spawned; i.e., enlisted in // their ancestor groups. comm::recv(po); } - #error["Grandchild group ready to go."]; + error!("Grandchild group ready to go."); // Master grandchild task exits early. } fn spawn_supervised_blocking(myname: &str, +f: fn~()) { let mut res = None; - task::task().future_result(|+r| res = Some(r)).supervised().spawn(f); - #error["%s group waiting", myname]; - let x = future::get(&option::unwrap(res)); + task::task().future_result(|+r| res = Some(move r)).supervised().spawn(move f); + error!("%s group waiting", myname); + let x = future::get(&option::unwrap(move res)); assert x == task::Success; } @@ -58,10 +58,10 @@ fn main() { grandchild_group(num_tasks); } // When grandchild group is ready to go, make the middle group exit. - #error["Middle group wakes up and exits"]; + error!("Middle group wakes up and exits"); } // Grandparent group waits for middle group to be gone, then fails - #error["Grandparent group wakes up and fails"]; + error!("Grandparent group wakes up and fails"); fail; }; assert x.is_err(); diff --git a/src/test/bench/task-perf-word-count-generic.rs b/src/test/bench/task-perf-word-count-generic.rs index 30add8c730c..3fe192ed363 100644 --- a/src/test/bench/task-perf-word-count-generic.rs +++ b/src/test/bench/task-perf-word-count-generic.rs @@ -30,7 +30,7 @@ use cmp::Eq; use to_bytes::IterBytes; macro_rules! move_out ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) trait word_reader { @@ -90,19 +90,19 @@ impl<T> box<T> { fn swap(f: fn(+v: T) -> T) { let mut tmp = None; self.contents <-> tmp; - self.contents = Some(f(option::unwrap(tmp))); + self.contents = Some(f(option::unwrap(move tmp))); } fn unwrap() -> T { let mut tmp = None; self.contents <-> tmp; - option::unwrap(tmp) + option::unwrap(move tmp) } } fn box<T>(+x: T) -> box<T> { box { - contents: Some(x) + contents: Some(move x) } } @@ -151,13 +151,13 @@ mod map_reduce { let mut tasks = ~[]; for inputs.each |i| { let (ctrl, ctrl_server) = ctrl_proto::init(); - let ctrl = box(ctrl); + let ctrl = box(move ctrl); let i = copy *i; let m = copy *map; - tasks.push(spawn_joinable(|move i| map_task(m, &ctrl, i))); - ctrls.push(ctrl_server); + tasks.push(spawn_joinable(|move ctrl, move i| map_task(m, &ctrl, i))); + ctrls.push(move ctrl_server); } - return tasks; + move tasks } fn map_task<K1: Copy Send, K2: Hash IterBytes Eq Const Copy Send, V: Copy Send>( @@ -177,8 +177,8 @@ mod map_reduce { Some(_c) => { c = Some(_c); } None => { do ctrl.swap |ctrl| { - let ctrl = ctrl_proto::client::find_reducer(ctrl, *key); - match pipes::recv(ctrl) { + let ctrl = ctrl_proto::client::find_reducer(move ctrl, *key); + match pipes::recv(move ctrl) { ctrl_proto::reducer(c_, ctrl) => { c = Some(c_); move_out!(ctrl) @@ -250,12 +250,12 @@ mod map_reduce { let mut num_mappers = vec::len(inputs) as int; while num_mappers > 0 { - let (_ready, message, ctrls) = pipes::select(ctrl); - match option::unwrap(message) { + let (_ready, message, ctrls) = pipes::select(move ctrl); + match option::unwrap(move message) { ctrl_proto::mapper_done => { // error!("received mapper terminated."); num_mappers -= 1; - ctrl = ctrls; + ctrl = move ctrls; } ctrl_proto::find_reducer(k, cc) => { let c; @@ -271,13 +271,13 @@ mod map_reduce { let p = Port(); let ch = Chan(&p); let r = reduce, kk = k; - tasks.push(spawn_joinable(|| reduce_task(~r, kk, ch) )); + tasks.push(spawn_joinable(|move r| reduce_task(~r, kk, ch) )); c = recv(p); reducers.insert(k, c); } } ctrl = vec::append_one( - ctrls, + move ctrls, ctrl_proto::server::reducer(move_out!(cc), c)); } } diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs index f539045108e..6cd22b7f535 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs @@ -1,6 +1,6 @@ struct defer { x: &[&str], - drop { #error["%?", self.x]; } + drop { error!("%?", self.x); } } fn defer(x: &r/[&r/str]) -> defer/&r { diff --git a/src/test/compile-fail/borrowck-imm-field-imm-base.rs b/src/test/compile-fail/borrowck-imm-field-imm-base.rs new file mode 100644 index 00000000000..69ff3b10378 --- /dev/null +++ b/src/test/compile-fail/borrowck-imm-field-imm-base.rs @@ -0,0 +1,17 @@ +struct Foo { + x: uint +} + +struct Bar { + foo: Foo +} + +fn main() { + let mut b = Bar { foo: Foo { x: 3 } }; + let p = &b; //~ NOTE prior loan as immutable granted here + let q = &mut b.foo.x; //~ ERROR loan of mutable local variable as mutable conflicts with prior loan + let r = &p.foo.x; + io::println(fmt!("*r = %u", *r)); + *q += 1; + io::println(fmt!("*r = %u", *r)); +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-imm-field-mut-base.rs b/src/test/compile-fail/borrowck-imm-field-mut-base.rs new file mode 100644 index 00000000000..6b9d93462d9 --- /dev/null +++ b/src/test/compile-fail/borrowck-imm-field-mut-base.rs @@ -0,0 +1,19 @@ +struct Foo { + mut x: uint +} + +struct Bar { + foo: Foo +} + +fn main() { + let mut b = Bar { foo: Foo { x: 3 } }; + let p = &b.foo.x; + let q = &mut b.foo; //~ ERROR loan of mutable field as mutable conflicts with prior loan + //~^ ERROR loan of mutable local variable as mutable conflicts with prior loan + let r = &mut b; //~ ERROR loan of mutable local variable as mutable conflicts with prior loan + io::println(fmt!("*p = %u", *p)); + q.x += 1; + r.foo.x += 1; + io::println(fmt!("*p = %u", *p)); +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-loan-blocks-move.rs b/src/test/compile-fail/borrowck-loan-blocks-move.rs index 5cecbf9284f..e48756bbbeb 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-move.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-move.rs @@ -4,7 +4,7 @@ fn take(-_v: ~int) { fn box_imm() { let v = ~3; let _w = &v; //~ NOTE loan of immutable local variable granted here - take(v); //~ ERROR moving out of immutable local variable prohibited due to outstanding loan + take(move v); //~ ERROR moving out of immutable local variable prohibited due to outstanding loan } fn main() { diff --git a/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs new file mode 100644 index 00000000000..54048ed2fd8 --- /dev/null +++ b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs @@ -0,0 +1,25 @@ +use core::either::{Either, Left, Right}; + + fn f(x: &mut Either<int,float>, y: &Either<int,float>) -> int { + match *y { + Left(ref z) => { + *x = Right(1.0); + *z + } + _ => fail + } + } + + fn g() { + let mut x: Either<int,float> = Left(3); + io::println(f(&mut x, &x).to_str()); //~ ERROR conflicts with prior loan + } + + fn h() { + let mut x: Either<int,float> = Left(3); + let y: &Either<int, float> = &x; + let z: &mut Either<int, float> = &mut x; //~ ERROR conflicts with prior loan + *z = *y; + } + + fn main() {} diff --git a/src/test/compile-fail/borrowck-mut-field-imm-base.rs b/src/test/compile-fail/borrowck-mut-field-imm-base.rs new file mode 100644 index 00000000000..f13637ab86a --- /dev/null +++ b/src/test/compile-fail/borrowck-mut-field-imm-base.rs @@ -0,0 +1,20 @@ +struct Foo { + mut x: uint +} + +struct Bar { + foo: Foo +} + +fn main() { + let mut b = Bar { foo: Foo { x: 3 } }; + let p = &b; + let q = &mut b.foo.x; + let r = &p.foo.x; //~ ERROR illegal borrow unless pure + let s = &b.foo.x; //~ ERROR loan of mutable field as immutable conflicts with prior loan + io::println(fmt!("*r = %u", *r)); + io::println(fmt!("*r = %u", *s)); + *q += 1; + io::println(fmt!("*r = %u", *r)); + io::println(fmt!("*r = %u", *s)); +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-unary-move-2.rs b/src/test/compile-fail/borrowck-unary-move-2.rs index 303415e4663..1d1595383ee 100644 --- a/src/test/compile-fail/borrowck-unary-move-2.rs +++ b/src/test/compile-fail/borrowck-unary-move-2.rs @@ -1,5 +1,5 @@ struct noncopyable { - i: (), drop { #error["dropped"]; } + i: (), drop { error!("dropped"); } } fn noncopyable() -> noncopyable { @@ -13,4 +13,4 @@ enum wrapper = noncopyable; fn main() { let x1 = wrapper(noncopyable()); let _x2 = move *x1; //~ ERROR moving out of enum content -} \ No newline at end of file +} diff --git a/src/test/compile-fail/cap-clause-use-after-move.rs b/src/test/compile-fail/cap-clause-use-after-move.rs index 7fb06ba5a23..a19dfc9e9f4 100644 --- a/src/test/compile-fail/cap-clause-use-after-move.rs +++ b/src/test/compile-fail/cap-clause-use-after-move.rs @@ -1,7 +1,5 @@ -// error-pattern:Unsatisfied precondition constraint - fn main() { let x = 5; - let _y = fn~(move x) { }; - let _z = x; //< error: Unsatisfied precondition constraint + let _y = fn~(move x) { }; //~ WARNING captured variable `x` not used in closure + let _z = x; //~ ERROR use of moved variable: `x` } diff --git a/src/test/compile-fail/copy-into-closure.rs b/src/test/compile-fail/copy-into-closure.rs index 8ee2a4fd3ae..51e0934bfe0 100644 --- a/src/test/compile-fail/copy-into-closure.rs +++ b/src/test/compile-fail/copy-into-closure.rs @@ -4,7 +4,7 @@ fn closure1(+x: ~str) -> (~str, fn@() -> ~str) { //~^ WARNING implicitly copying a non-implicitly-copyable value //~^^ NOTE to copy values into a @fn closure, use a capture clause }; - (x,f) + (move x,f) } fn closure2(+x: util::NonCopyable) -> (util::NonCopyable, @@ -15,7 +15,7 @@ fn closure2(+x: util::NonCopyable) -> (util::NonCopyable, //~^^ NOTE non-copyable value cannot be copied into a @fn closure //~^^^ ERROR copying a noncopyable value }; - (x,f) + (move x,f) } fn closure3(+x: util::NonCopyable) { do task::spawn { diff --git a/src/test/compile-fail/duplicate-visibility.rs b/src/test/compile-fail/duplicate-visibility.rs new file mode 100644 index 00000000000..32997fcce31 --- /dev/null +++ b/src/test/compile-fail/duplicate-visibility.rs @@ -0,0 +1,4 @@ +// error-pattern:unmatched visibility `pub` +extern { + pub pub fn foo(); +} diff --git a/src/test/compile-fail/estr-subtyping.rs b/src/test/compile-fail/estr-subtyping.rs index 7e3e29f2b8f..626e7eff3f7 100644 --- a/src/test/compile-fail/estr-subtyping.rs +++ b/src/test/compile-fail/estr-subtyping.rs @@ -1,29 +1,23 @@ fn wants_box(x: @str) { } fn wants_uniq(x: ~str) { } -fn wants_three(x: str/3) { } +fn wants_slice(x: &str) { } fn has_box(x: @str) { wants_box(x); wants_uniq(x); //~ ERROR str storage differs: expected ~ but found @ - wants_three(x); //~ ERROR str storage differs: expected 3 but found @ + wants_slice(x); } fn has_uniq(x: ~str) { wants_box(x); //~ ERROR str storage differs: expected @ but found ~ wants_uniq(x); - wants_three(x); //~ ERROR str storage differs: expected 3 but found ~ + wants_slice(x); } -fn has_three(x: str/3) { - wants_box(x); //~ ERROR str storage differs: expected @ but found 3 - wants_uniq(x); //~ ERROR str storage differs: expected ~ but found 3 - wants_three(x); -} - -fn has_four(x: str/4) { - wants_box(x); //~ ERROR str storage differs: expected @ but found 4 - wants_uniq(x); //~ ERROR str storage differs: expected ~ but found 4 - wants_three(x); //~ ERROR str storage differs: expected 3 but found 4 +fn has_slice(x: &str) { + wants_box(x); //~ ERROR str storage differs: expected @ but found & + wants_uniq(x); //~ ERROR str storage differs: expected ~ but found & + wants_slice(x); } fn main() { diff --git a/src/test/compile-fail/evec-subtyping.rs b/src/test/compile-fail/evec-subtyping.rs index 2eabfa0c48c..e5e9aa0c257 100644 --- a/src/test/compile-fail/evec-subtyping.rs +++ b/src/test/compile-fail/evec-subtyping.rs @@ -1,6 +1,6 @@ fn wants_box(x: @[uint]) { } fn wants_uniq(x: ~[uint]) { } -fn wants_three(x: [uint]/3) { } +fn wants_three(x: [uint * 3]) { } fn has_box(x: @[uint]) { wants_box(x); @@ -14,13 +14,13 @@ fn has_uniq(x: ~[uint]) { wants_three(x); //~ ERROR [] storage differs: expected 3 but found ~ } -fn has_three(x: [uint]/3) { +fn has_three(x: [uint * 3]) { wants_box(x); //~ ERROR [] storage differs: expected @ but found 3 wants_uniq(x); //~ ERROR [] storage differs: expected ~ but found 3 wants_three(x); } -fn has_four(x: [uint]/4) { +fn has_four(x: [uint * 4]) { wants_box(x); //~ ERROR [] storage differs: expected @ but found 4 wants_uniq(x); //~ ERROR [] storage differs: expected ~ but found 4 wants_three(x); //~ ERROR [] storage differs: expected 3 but found 4 diff --git a/src/test/compile-fail/extenv-no-args.rs b/src/test/compile-fail/extenv-no-args.rs index e169db23bf2..1db0e0a39ee 100644 --- a/src/test/compile-fail/extenv-no-args.rs +++ b/src/test/compile-fail/extenv-no-args.rs @@ -1,3 +1,3 @@ -// error-pattern:#env takes between 1 and 1 arguments +// error-pattern: env! takes between 1 and 1 arguments fn main() { env!(); } diff --git a/src/test/compile-fail/extenv-too-many-args.rs b/src/test/compile-fail/extenv-too-many-args.rs index ee5b1b4af74..4f0df2a090f 100644 --- a/src/test/compile-fail/extenv-too-many-args.rs +++ b/src/test/compile-fail/extenv-too-many-args.rs @@ -1,3 +1,3 @@ -// error-pattern:#env takes between 1 and 1 arguments +// error-pattern: env! takes between 1 and 1 arguments fn main() { env!("one", "two"); } diff --git a/src/test/compile-fail/extfmt-no-args.rs b/src/test/compile-fail/extfmt-no-args.rs index b291fbae225..1cca7e5b315 100644 --- a/src/test/compile-fail/extfmt-no-args.rs +++ b/src/test/compile-fail/extfmt-no-args.rs @@ -1,3 +1,3 @@ -// error-pattern:#fmt needs at least 1 arguments +// error-pattern:fmt! needs at least 1 arguments fn main() { fmt!(); } diff --git a/src/test/compile-fail/extfmt-non-literal.rs b/src/test/compile-fail/extfmt-non-literal.rs index 0e2109fac4f..7255bd84631 100644 --- a/src/test/compile-fail/extfmt-non-literal.rs +++ b/src/test/compile-fail/extfmt-non-literal.rs @@ -1,7 +1,7 @@ // error-pattern: literal fn main() { - // #fmt's first argument must be a literal. Hopefully this + // fmt!'s first argument must be a literal. Hopefully this // restriction can be eased eventually to just require a // compile-time constant. let x = fmt!("a" + "b"); diff --git a/src/test/compile-fail/extfmt-non-literal2.rs b/src/test/compile-fail/extfmt-non-literal2.rs index cc10845fd9f..0196c37c68e 100644 --- a/src/test/compile-fail/extfmt-non-literal2.rs +++ b/src/test/compile-fail/extfmt-non-literal2.rs @@ -1,7 +1,7 @@ // error-pattern: literal fn main() { - // #fmt's first argument must be a literal. Hopefully this + // fmt!'s first argument must be a literal. Hopefully this // restriction can be eased eventually to just require a // compile-time constant. let x = fmt!(20); diff --git a/src/test/compile-fail/extfmt-unsigned-plus.rs b/src/test/compile-fail/extfmt-unsigned-plus.rs index d8a9f4fa98d..1dd3ed390d5 100644 --- a/src/test/compile-fail/extfmt-unsigned-plus.rs +++ b/src/test/compile-fail/extfmt-unsigned-plus.rs @@ -1,4 +1,4 @@ -// error-pattern:only valid in signed #fmt conversion +// error-pattern:only valid in signed fmt! conversion fn main() { // Can't use a sign on unsigned conversions diff --git a/src/test/compile-fail/extfmt-unsigned-space.rs b/src/test/compile-fail/extfmt-unsigned-space.rs index 001adb521cc..a2ac54bea7d 100644 --- a/src/test/compile-fail/extfmt-unsigned-space.rs +++ b/src/test/compile-fail/extfmt-unsigned-space.rs @@ -1,4 +1,4 @@ -// error-pattern:only valid in signed #fmt conversion +// error-pattern:only valid in signed fmt! conversion fn main() { // Can't use a space on unsigned conversions diff --git a/src/test/compile-fail/functional-struct-update.rs b/src/test/compile-fail/functional-struct-update.rs new file mode 100644 index 00000000000..8d7913a62fa --- /dev/null +++ b/src/test/compile-fail/functional-struct-update.rs @@ -0,0 +1,16 @@ +struct Bar { + x: int, + drop { io::println("Goodbye, cruel world"); } +} + +struct Foo { + x: int, + y: Bar +} + +fn main() { + let a = Foo { x: 1, y: Bar { x: 5 } }; + let c = Foo { x: 4, .. a}; //~ ERROR copying a noncopyable value + io::println(fmt!("%?", c)); +} + diff --git a/src/test/compile-fail/issue-1965.rs b/src/test/compile-fail/issue-1965.rs index 9742acba1e3..ee318d7b02c 100644 --- a/src/test/compile-fail/issue-1965.rs +++ b/src/test/compile-fail/issue-1965.rs @@ -2,6 +2,6 @@ fn test(-x: uint) {} fn main() { - let i = 3u; - for uint::range(0u, 10u) |_x| {test(i)} + let i = 3; + for uint::range(0, 10) |_x| {test(move i)} } diff --git a/src/test/compile-fail/issue-2074.rs b/src/test/compile-fail/issue-2074.rs new file mode 100644 index 00000000000..d911b7db3dd --- /dev/null +++ b/src/test/compile-fail/issue-2074.rs @@ -0,0 +1,12 @@ +// xfail-test +fn main() { + let one = fn@() -> uint { + enum r { a }; + return a as uint; + }; + let two = fn@() -> uint { + enum r { a }; + return a as uint; + }; + one(); two(); +} diff --git a/src/test/compile-fail/issue-2548.rs b/src/test/compile-fail/issue-2548.rs index 61cfabc40d2..0d491fc8834 100644 --- a/src/test/compile-fail/issue-2548.rs +++ b/src/test/compile-fail/issue-2548.rs @@ -21,7 +21,7 @@ fn main() { let mut res = foo(x); let mut v = ~[mut]; - v <- ~[mut res] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `owned`, missing `copy`) + v <- ~[mut (move res)] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `owned`, missing `copy`) assert (v.len() == 2); } diff --git a/src/test/compile-fail/issue-2590.rs b/src/test/compile-fail/issue-2590.rs index f4ccd901fb3..0f4a4804c75 100644 --- a/src/test/compile-fail/issue-2590.rs +++ b/src/test/compile-fail/issue-2590.rs @@ -10,7 +10,7 @@ trait parse { impl parser: parse { fn parse() -> ~[int] { - dvec::unwrap(move self.tokens) //~ ERROR illegal move from self + dvec::unwrap(move self.tokens) //~ ERROR moving out of immutable field } } diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs index 75e524e27ac..590ea5e0b7c 100644 --- a/src/test/compile-fail/issue-2766-a.rs +++ b/src/test/compile-fail/issue-2766-a.rs @@ -1,13 +1,13 @@ mod stream { #[legacy_exports]; - enum stream<T: Send> { send(T, server::stream<T>), } + enum Stream<T: Send> { send(T, server::Stream<T>), } mod server { #[legacy_exports]; - impl<T: Send> stream<T> { - fn recv() -> extern fn(+v: stream<T>) -> stream::stream<T> { + impl<T: Send> Stream<T> { + fn recv() -> extern fn(+v: Stream<T>) -> stream::Stream<T> { // resolve really should report just one error here. // Change the test case when it changes. - fn recv(+pipe: stream<T>) -> stream::stream<T> { //~ ERROR attempt to use a type argument out of scope + fn recv(+pipe: Stream<T>) -> stream::Stream<T> { //~ ERROR attempt to use a type argument out of scope //~^ ERROR use of undeclared type name //~^^ ERROR attempt to use a type argument out of scope //~^^^ ERROR use of undeclared type name @@ -16,7 +16,7 @@ mod stream { recv } } - type stream<T: Send> = pipes::RecvPacket<stream::stream<T>>; + type Stream<T: Send> = pipes::RecvPacket<stream::Stream<T>>; } } diff --git a/src/test/compile-fail/issue-2823.rs b/src/test/compile-fail/issue-2823.rs new file mode 100644 index 00000000000..fd2c1758458 --- /dev/null +++ b/src/test/compile-fail/issue-2823.rs @@ -0,0 +1,12 @@ +struct C { + x: int, + drop { + #error("dropping: %?", self.x); + } +} + +fn main() { + let c = C{ x: 2}; + let d = copy c; //~ ERROR copying a noncopyable value + #error("%?", d.x); +} \ No newline at end of file diff --git a/src/test/compile-fail/issue-3099-a.rs b/src/test/compile-fail/issue-3099-a.rs index 2721186585b..fee676ed5e2 100644 --- a/src/test/compile-fail/issue-3099-a.rs +++ b/src/test/compile-fail/issue-3099-a.rs @@ -1,5 +1,5 @@ enum a { b, c } -enum a { d, e } //~ ERROR Duplicate definition of type a +enum a { d, e } //~ ERROR duplicate definition of type a fn main() {} diff --git a/src/test/compile-fail/issue-3099-b.rs b/src/test/compile-fail/issue-3099-b.rs index 997bb9e2557..dc393eb7520 100644 --- a/src/test/compile-fail/issue-3099-b.rs +++ b/src/test/compile-fail/issue-3099-b.rs @@ -2,6 +2,6 @@ mod a {} #[legacy_exports] -mod a {} //~ ERROR Duplicate definition of module a +mod a {} //~ ERROR duplicate definition of type a fn main() {} diff --git a/src/test/compile-fail/issue-3099.rs b/src/test/compile-fail/issue-3099.rs index 4f3bd89e7ef..79212686130 100644 --- a/src/test/compile-fail/issue-3099.rs +++ b/src/test/compile-fail/issue-3099.rs @@ -1,11 +1,11 @@ fn a(x: ~str) -> ~str { - #fmt("First function with %s", x) + fmt!("First function with %s", x) } -fn a(x: ~str, y: ~str) -> ~str { //~ ERROR Duplicate definition of value a - #fmt("Second function with %s and %s", x, y) +fn a(x: ~str, y: ~str) -> ~str { //~ ERROR duplicate definition of value a + fmt!("Second function with %s and %s", x, y) } fn main() { - #info("Result: "); + info!("Result: "); } diff --git a/src/test/compile-fail/issue-3214.rs b/src/test/compile-fail/issue-3214.rs new file mode 100644 index 00000000000..7008f8c4ce2 --- /dev/null +++ b/src/test/compile-fail/issue-3214.rs @@ -0,0 +1,8 @@ +fn foo<T>() { + struct foo { + mut x: T, //~ ERROR attempt to use a type argument out of scope + //~^ ERROR use of undeclared type name + drop { } + } +} +fn main() { } diff --git a/src/test/compile-fail/issue-3521-2.rs b/src/test/compile-fail/issue-3521-2.rs new file mode 100644 index 00000000000..5af0417af04 --- /dev/null +++ b/src/test/compile-fail/issue-3521-2.rs @@ -0,0 +1,7 @@ +fn main() { + let foo = 100; + + const y: int = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant + + log(error, y); +} diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs new file mode 100644 index 00000000000..9ad483367fe --- /dev/null +++ b/src/test/compile-fail/issue-3521.rs @@ -0,0 +1,9 @@ +fn main() { + let foo = 100; + + enum Stuff { + Bar = foo //~ ERROR attempt to use a non-constant value in a constant + } + + log(error, Bar); +} diff --git a/src/test/compile-fail/issue-3668-2.rs b/src/test/compile-fail/issue-3668-2.rs new file mode 100644 index 00000000000..89c9e2b2e91 --- /dev/null +++ b/src/test/compile-fail/issue-3668-2.rs @@ -0,0 +1,5 @@ +fn f(x:int) { + const child: int = x + 1; //~ ERROR attempt to use a non-constant value in a constant +} + +fn main() {} diff --git a/src/test/compile-fail/issue-3668.rs b/src/test/compile-fail/issue-3668.rs new file mode 100644 index 00000000000..6cbd64c6aa9 --- /dev/null +++ b/src/test/compile-fail/issue-3668.rs @@ -0,0 +1,13 @@ +struct P { child: Option<@mut P> } +trait PTrait { + fn getChildOption() -> Option<@P>; +} + +impl P: PTrait { + fn getChildOption() -> Option<@P> { + const childVal: @P = self.child.get(); //~ ERROR attempt to use a non-constant value in a constant + fail; + } +} + +fn main() {} diff --git a/src/test/compile-fail/liveness-move-from-args.rs b/src/test/compile-fail/liveness-move-from-args.rs index 27e9d3b60dc..48f72dd0d3e 100644 --- a/src/test/compile-fail/liveness-move-from-args.rs +++ b/src/test/compile-fail/liveness-move-from-args.rs @@ -1,19 +1,19 @@ fn take(-_x: int) { } fn from_by_value_arg(++x: int) { - take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode + take(move x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } fn from_by_ref_arg(&&x: int) { - take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode + take(move x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } fn from_copy_arg(+x: int) { - take(x); + take(move x); } fn from_move_arg(-x: int) { - take(x); + take(move x); } fn main() { diff --git a/src/test/compile-fail/liveness-move-from-mode.rs b/src/test/compile-fail/liveness-move-from-mode.rs index a837d337f98..959bda4e583 100644 --- a/src/test/compile-fail/liveness-move-from-mode.rs +++ b/src/test/compile-fail/liveness-move-from-mode.rs @@ -4,7 +4,7 @@ fn main() { let x: int = 25; loop { - take(x); //~ ERROR use of moved variable: `x` + take(move x); //~ ERROR use of moved variable: `x` //~^ NOTE move of variable occurred here } } diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 8b2fef7cd35..473a133730a 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -54,5 +54,5 @@ struct r { } fn main() { let x = r { x: () }; - fn@() { copy x; }; //~ ERROR copying a noncopyable value + fn@(move x) { copy x; }; //~ ERROR copying a noncopyable value } diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index 5447c88e567..13952dbe3c1 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -9,7 +9,7 @@ enum _chan<T> = int; // Tests that "log(debug, message);" is flagged as using // message after the send deinitializes it fn test00_start(ch: _chan<int>, message: int, _count: int) { - send(ch, message); //~ NOTE move of variable occurred here + send(ch, move message); //~ NOTE move of variable occurred here log(debug, message); //~ ERROR use of moved variable: `message` } diff --git a/src/test/compile-fail/obsolete-syntax.rs b/src/test/compile-fail/obsolete-syntax.rs index 9f57e08cdb2..c8a8bd85961 100644 --- a/src/test/compile-fail/obsolete-syntax.rs +++ b/src/test/compile-fail/obsolete-syntax.rs @@ -56,4 +56,15 @@ fn obsolete_with() { //~^ ERROR obsolete syntax: with } +fn obsolete_fixed_length_vec() { + let foo: [int]/1; + //~^ ERROR obsolete syntax: fixed-length vector + foo = [1]/_; + //~^ ERROR obsolete syntax: fixed-length vector + let foo: [int]/1; + //~^ ERROR obsolete syntax: fixed-length vector + foo = [1]/1; + //~^ ERROR obsolete syntax: fixed-length vector +} + fn main() { } diff --git a/src/test/compile-fail/regions-freevar.rs b/src/test/compile-fail/regions-freevar.rs index dc2a43cc7db..b163006c50a 100644 --- a/src/test/compile-fail/regions-freevar.rs +++ b/src/test/compile-fail/regions-freevar.rs @@ -3,7 +3,7 @@ fn wants_static_fn(_x: &static/fn()) {} fn main() { let i = 3; do wants_static_fn { - #debug("i=%d", i); + debug!("i=%d", i); //~^ ERROR captured variable does not outlive the enclosing closure } } diff --git a/src/test/compile-fail/regions-glb-free-free.rs b/src/test/compile-fail/regions-glb-free-free.rs index 223665381da..e4913f7056e 100644 --- a/src/test/compile-fail/regions-glb-free-free.rs +++ b/src/test/compile-fail/regions-glb-free-free.rs @@ -19,7 +19,7 @@ mod argparse { fn set_desc(self, s: &str) -> Flag { Flag { //~ ERROR cannot infer an appropriate lifetime name: self.name, - desc: s, + desc: s, //~ ERROR cannot infer an appropriate lifetime max_count: self.max_count, value: self.value } diff --git a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs index 80a36945097..f5bd208f00f 100644 --- a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs +++ b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs @@ -5,7 +5,7 @@ extern mod core; -fn last<T: Copy>(v: ~[const T]) -> core::Option<T> { +fn last<T>(v: ~[const &T]) -> core::Option<T> { fail; } diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs index eea832c91a4..b31583724d2 100644 --- a/src/test/compile-fail/unique-unique-kind.rs +++ b/src/test/compile-fail/unique-unique-kind.rs @@ -3,5 +3,5 @@ fn f<T: Send>(_i: T) { fn main() { let i = ~@100; - f(i); //~ ERROR missing `send` + f(move i); //~ ERROR missing `send` } diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs index a47a8b76e56..a84c1397319 100644 --- a/src/test/compile-fail/unsendable-class.rs +++ b/src/test/compile-fail/unsendable-class.rs @@ -17,5 +17,5 @@ fn main() { let cat = ~"kitty"; let po = comm::Port(); //~ ERROR missing `send` let ch = comm::Chan(&po); //~ ERROR missing `send` - comm::send(ch, foo(42, @cat)); //~ ERROR missing `send` + comm::send(ch, foo(42, @(move cat))); //~ ERROR missing `send` } diff --git a/src/test/pretty/blank-lines.rs b/src/test/pretty/blank-lines.rs index 3ef46a721ae..d677577e442 100644 --- a/src/test/pretty/blank-lines.rs +++ b/src/test/pretty/blank-lines.rs @@ -1,5 +1,5 @@ // pp-exact -fn f() -> [int]/3 { +fn f() -> [int * 3] { let picard = 0; let data = 1; @@ -7,7 +7,7 @@ fn f() -> [int]/3 { let worf = 2; - let enterprise = [picard, data, worf]/_; + let enterprise = [picard, data, worf]; diff --git a/src/test/run-fail/doublefail.rs b/src/test/run-fail/doublefail.rs new file mode 100644 index 00000000000..37beb7b895e --- /dev/null +++ b/src/test/run-fail/doublefail.rs @@ -0,0 +1,5 @@ +//error-pattern:One +fn main() { + fail ~"One"; + fail ~"Two"; +} \ No newline at end of file diff --git a/src/test/run-fail/port-type.rs b/src/test/run-fail/port-type.rs index 30714413c53..9f2974d2cc2 100644 --- a/src/test/run-fail/port-type.rs +++ b/src/test/run-fail/port-type.rs @@ -12,7 +12,7 @@ fn echo<T: Send>(c: Chan<T>, oc: Chan<Chan<T>>) { send(oc, Chan(&p)); let x = recv(p); - send(c, x); + send(c, move x); } fn main() { fail ~"meep"; } diff --git a/src/test/run-fail/unwind-box-res.rs b/src/test/run-fail/unwind-box-res.rs index 0bea0f934f4..ca85aa97017 100644 --- a/src/test/run-fail/unwind-box-res.rs +++ b/src/test/run-fail/unwind-box-res.rs @@ -20,7 +20,7 @@ fn r(v: *int) -> r { fn main() unsafe { let i1 = ~0; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let x = @r(i1p); failfn(); log(error, x); diff --git a/src/test/run-fail/unwind-move.rs b/src/test/run-fail/unwind-move.rs index 311cb52b134..995edbcc05b 100644 --- a/src/test/run-fail/unwind-move.rs +++ b/src/test/run-fail/unwind-move.rs @@ -1,9 +1,9 @@ // error-pattern:fail -fn f(-a: @int) { +fn f(-_a: @int) { fail; } fn main() { let a = @0; - f(a); + f(move a); } \ No newline at end of file diff --git a/src/test/run-pass/anon-trait-static-method.rs b/src/test/run-pass/anon-trait-static-method.rs new file mode 100644 index 00000000000..6c4e9abc5ff --- /dev/null +++ b/src/test/run-pass/anon-trait-static-method.rs @@ -0,0 +1,15 @@ +struct Foo { + x: int +} + +impl Foo { + static fn new() -> Foo { + Foo { x: 3 } + } +} + +fn main() { + let x = Foo::new(); + io::println(x.x.to_str()); +} + diff --git a/src/test/run-pass/anon_trait_static_method_exe.rs b/src/test/run-pass/anon_trait_static_method_exe.rs new file mode 100644 index 00000000000..052f95ed3b5 --- /dev/null +++ b/src/test/run-pass/anon_trait_static_method_exe.rs @@ -0,0 +1,13 @@ +// xfail-fast - check-fast doesn't understand aux-build +// aux-build:anon_trait_static_method_lib.rs + +extern mod anon_trait_static_method_lib; +use anon_trait_static_method_lib::Foo; + +fn main() { + let x = Foo::new(); + io::println(x.x.to_str()); +} + + + diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs index e8aaf88374f..dc861829c11 100644 --- a/src/test/run-pass/argument-passing.rs +++ b/src/test/run-pass/argument-passing.rs @@ -12,7 +12,7 @@ fn f2(a: int, f: fn(int)) -> int { f(1); return a; } fn main() { let mut a = {mut x: 1}, b = 2, c = 3; - assert (f1(a, &mut b, c) == 6); + assert (f1(a, &mut b, move c) == 6); assert (a.x == 0); assert (b == 10); assert (f2(a.x, |x| a.x = 50 ) == 0); diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs index 4652212ce5f..16e7473fb78 100644 --- a/src/test/run-pass/assignability-trait.rs +++ b/src/test/run-pass/assignability-trait.rs @@ -39,7 +39,7 @@ fn main() { assert length::<int, &[int]>(x) == vec::len(x); // Now try it with a type that *needs* to be borrowed - let z = [0,1,2,3]/_; + let z = [0,1,2,3]; // Call a method for z.iterate() |y| { assert z[*y] == *y; } // Call a parameterized function diff --git a/src/test/run-pass/auto-ref-sliceable.rs b/src/test/run-pass/auto-ref-sliceable.rs index 48d83da74ad..a8e6832d33c 100644 --- a/src/test/run-pass/auto-ref-sliceable.rs +++ b/src/test/run-pass/auto-ref-sliceable.rs @@ -4,7 +4,7 @@ trait Pushable<T> { impl<T> ~[T]: Pushable<T> { fn push_val(&mut self, +t: T) { - self.push(t); + self.push(move t); } } diff --git a/src/test/run-pass/auto_serialize.rs b/src/test/run-pass/auto_serialize.rs index 3a07faa75c5..b63d1dcab7e 100644 --- a/src/test/run-pass/auto_serialize.rs +++ b/src/test/run-pass/auto_serialize.rs @@ -1,6 +1,3 @@ -// xfail-fast -#[legacy_modes]; - extern mod std; // These tests used to be separate files, but I wanted to refactor all @@ -9,200 +6,178 @@ extern mod std; use cmp::Eq; use std::ebml; use io::Writer; -use std::serialization::{serialize_uint, deserialize_uint}; - -fn test_ser_and_deser<A:Eq>(a1: A, - expected: ~str, - ebml_ser_fn: fn(ebml::Writer, A), - ebml_deser_fn: fn(ebml::EbmlDeserializer) -> A, - io_ser_fn: fn(io::Writer, A)) { - - // check the pretty printer: - io_ser_fn(io::stdout(), a1); - let s = io::with_str_writer(|w| io_ser_fn(w, a1) ); +use std::serialization::{Serializable, Deserializable, deserialize}; +use std::prettyprint; + +fn test_prettyprint<A: Serializable<prettyprint::Serializer>>( + a: &A, + expected: &~str +) { + let s = do io::with_str_writer |w| { + a.serialize(&prettyprint::Serializer(w)) + }; debug!("s == %?", s); - assert s == expected; + assert s == *expected; +} - // check the EBML serializer: +fn test_ebml<A: + Eq + Serializable<ebml::Serializer> + Deserializable<ebml::Deserializer> +>(a1: &A) { let bytes = do io::with_bytes_writer |wr| { - let w = ebml::Writer(wr); - ebml_ser_fn(w, a1); + let ebml_w = &ebml::Serializer(wr); + a1.serialize(ebml_w) }; let d = ebml::Doc(@bytes); - let a2 = ebml_deser_fn(ebml::ebml_deserializer(d)); - io::print(~"\na1 = "); - io_ser_fn(io::stdout(), a1); - io::print(~"\na2 = "); - io_ser_fn(io::stdout(), a2); - io::print(~"\n"); - assert a1 == a2; - + let a2: A = deserialize(&ebml::Deserializer(d)); + assert *a1 == a2; } #[auto_serialize] -enum expr { - val(uint), - plus(@expr, @expr), - minus(@expr, @expr) +#[auto_deserialize] +enum Expr { + Val(uint), + Plus(@Expr, @Expr), + Minus(@Expr, @Expr) } -impl an_enum : cmp::Eq { - pure fn eq(other: &an_enum) -> bool { - self.v == (*other).v - } - pure fn ne(other: &an_enum) -> bool { !self.eq(other) } -} - -impl point : cmp::Eq { - pure fn eq(other: &point) -> bool { - self.x == (*other).x && self.y == (*other).y - } - pure fn ne(other: &point) -> bool { !self.eq(other) } -} - -impl<T:cmp::Eq> quark<T> : cmp::Eq { - pure fn eq(other: &quark<T>) -> bool { +impl Expr : cmp::Eq { + pure fn eq(other: &Expr) -> bool { match self { - top(ref q) => match (*other) { - top(ref r) => q == r, - bottom(_) => false - }, - bottom(ref q) => match (*other) { - top(_) => false, - bottom(ref r) => q == r - } + Val(e0a) => { + match *other { + Val(e0b) => e0a == e0b, + _ => false + } + } + Plus(e0a, e1a) => { + match *other { + Plus(e0b, e1b) => e0a == e0b && e1a == e1b, + _ => false + } + } + Minus(e0a, e1a) => { + match *other { + Minus(e0b, e1b) => e0a == e0b && e1a == e1b, + _ => false + } + } } } - pure fn ne(other: &quark<T>) -> bool { !self.eq(other) } + pure fn ne(other: &Expr) -> bool { !self.eq(other) } } +impl AnEnum : cmp::Eq { + pure fn eq(other: &AnEnum) -> bool { + self.v == other.v + } + pure fn ne(other: &AnEnum) -> bool { !self.eq(other) } +} -impl c_like : cmp::Eq { - pure fn eq(other: &c_like) -> bool { - self as int == (*other) as int +impl Point : cmp::Eq { + pure fn eq(other: &Point) -> bool { + self.x == other.x && self.y == other.y } - pure fn ne(other: &c_like) -> bool { !self.eq(other) } + pure fn ne(other: &Point) -> bool { !self.eq(other) } } -impl expr : cmp::Eq { - pure fn eq(other: &expr) -> bool { +impl<T:cmp::Eq> Quark<T> : cmp::Eq { + pure fn eq(other: &Quark<T>) -> bool { match self { - val(e0a) => { - match (*other) { - val(e0b) => e0a == e0b, - _ => false + Top(ref q) => { + match *other { + Top(ref r) => q == r, + Bottom(_) => false } - } - plus(e0a, e1a) => { - match (*other) { - plus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - minus(e0a, e1a) => { - match (*other) { - minus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false + }, + Bottom(ref q) => { + match *other { + Top(_) => false, + Bottom(ref r) => q == r } - } + }, } } - pure fn ne(other: &expr) -> bool { !self.eq(other) } + pure fn ne(other: &Quark<T>) -> bool { !self.eq(other) } } -#[auto_serialize] -type spanned<T> = {lo: uint, hi: uint, node: T}; - -impl<T:cmp::Eq> spanned<T> : cmp::Eq { - pure fn eq(other: &spanned<T>) -> bool { - self.lo == (*other).lo && self.hi == (*other).hi && - self.node.eq(&(*other).node) +impl CLike : cmp::Eq { + pure fn eq(other: &CLike) -> bool { + self as int == *other as int } - pure fn ne(other: &spanned<T>) -> bool { !self.eq(other) } + pure fn ne(other: &CLike) -> bool { !self.eq(other) } } #[auto_serialize] -type spanned_uint = spanned<uint>; +#[auto_deserialize] +type Spanned<T> = {lo: uint, hi: uint, node: T}; -#[auto_serialize] -type some_rec = {v: uint_vec}; +impl<T:cmp::Eq> Spanned<T> : cmp::Eq { + pure fn eq(other: &Spanned<T>) -> bool { + self.lo == other.lo && self.hi == other.hi && self.node == other.node + } + pure fn ne(other: &Spanned<T>) -> bool { !self.eq(other) } +} #[auto_serialize] -enum an_enum = some_rec; +#[auto_deserialize] +type SomeRec = {v: ~[uint]}; #[auto_serialize] -type uint_vec = ~[uint]; +#[auto_deserialize] +enum AnEnum = SomeRec; #[auto_serialize] -type point = {x: uint, y: uint}; +#[auto_deserialize] +struct Point {x: uint, y: uint} #[auto_serialize] -enum quark<T> { - top(T), - bottom(T) +#[auto_deserialize] +enum Quark<T> { + Top(T), + Bottom(T) } #[auto_serialize] -type uint_quark = quark<uint>; - -#[auto_serialize] -enum c_like { a, b, c } +#[auto_deserialize] +enum CLike { A, B, C } fn main() { - - test_ser_and_deser(plus(@minus(@val(3u), @val(10u)), - @plus(@val(22u), @val(5u))), - ~"plus(@minus(@val(3u), @val(10u)), \ - @plus(@val(22u), @val(5u)))", - serialize_expr, - deserialize_expr, - serialize_expr); - - test_ser_and_deser({lo: 0u, hi: 5u, node: 22u}, - ~"{lo: 0u, hi: 5u, node: 22u}", - serialize_spanned_uint, - deserialize_spanned_uint, - serialize_spanned_uint); - - test_ser_and_deser(an_enum({v: ~[1u, 2u, 3u]}), - ~"an_enum({v: [1u, 2u, 3u]})", - serialize_an_enum, - deserialize_an_enum, - serialize_an_enum); - - test_ser_and_deser({x: 3u, y: 5u}, - ~"{x: 3u, y: 5u}", - serialize_point, - deserialize_point, - serialize_point); - - test_ser_and_deser(~[1u, 2u, 3u], - ~"[1u, 2u, 3u]", - serialize_uint_vec, - deserialize_uint_vec, - serialize_uint_vec); - - test_ser_and_deser(top(22u), - ~"top(22u)", - serialize_uint_quark, - deserialize_uint_quark, - serialize_uint_quark); - - test_ser_and_deser(bottom(222u), - ~"bottom(222u)", - serialize_uint_quark, - deserialize_uint_quark, - serialize_uint_quark); - - test_ser_and_deser(a, - ~"a", - serialize_c_like, - deserialize_c_like, - serialize_c_like); - - test_ser_and_deser(b, - ~"b", - serialize_c_like, - deserialize_c_like, - serialize_c_like); + let a = &Plus(@Minus(@Val(3u), @Val(10u)), @Plus(@Val(22u), @Val(5u))); + test_prettyprint(a, &~"Plus(@Minus(@Val(3u), @Val(10u)), \ + @Plus(@Val(22u), @Val(5u)))"); + test_ebml(a); + + let a = &{lo: 0u, hi: 5u, node: 22u}; + test_prettyprint(a, &~"{lo: 0u, hi: 5u, node: 22u}"); + test_ebml(a); + + let a = &AnEnum({v: ~[1u, 2u, 3u]}); + test_prettyprint(a, &~"AnEnum({v: ~[1u, 2u, 3u]})"); + test_ebml(a); + + let a = &Point {x: 3u, y: 5u}; + test_prettyprint(a, &~"Point {x: 3u, y: 5u}"); + test_ebml(a); + + let a = &@[1u, 2u, 3u]; + test_prettyprint(a, &~"@[1u, 2u, 3u]"); + test_ebml(a); + + let a = &Top(22u); + test_prettyprint(a, &~"Top(22u)"); + test_ebml(a); + + let a = &Bottom(222u); + test_prettyprint(a, &~"Bottom(222u)"); + test_ebml(a); + + let a = &A; + test_prettyprint(a, &~"A"); + test_ebml(a); + + let a = &B; + test_prettyprint(a, &~"B"); + test_ebml(a); } diff --git a/src/test/run-pass/auto_serialize2.rs b/src/test/run-pass/auto_serialize2.rs deleted file mode 100644 index 4503ea6c7e0..00000000000 --- a/src/test/run-pass/auto_serialize2.rs +++ /dev/null @@ -1,163 +0,0 @@ -extern mod std; - -// These tests used to be separate files, but I wanted to refactor all -// the common code. - -use cmp::Eq; -use std::ebml2; -use io::Writer; -use std::serialization2::{Serializable, Deserializable, deserialize}; -use std::prettyprint2; - -fn test_ser_and_deser<A:Eq Serializable Deserializable>( - a1: &A, - +expected: ~str -) { - // check the pretty printer: - let s = do io::with_str_writer |w| { - a1.serialize(&prettyprint2::Serializer(w)) - }; - debug!("s == %?", s); - assert s == expected; - - // check the EBML serializer: - let bytes = do io::with_bytes_writer |wr| { - let ebml_w = &ebml2::Serializer(wr); - a1.serialize(ebml_w) - }; - let d = ebml2::Doc(@bytes); - let a2: A = deserialize(&ebml2::Deserializer(d)); - assert *a1 == a2; -} - -#[auto_serialize2] -#[auto_deserialize2] -enum Expr { - Val(uint), - Plus(@Expr, @Expr), - Minus(@Expr, @Expr) -} - -impl Expr : cmp::Eq { - pure fn eq(other: &Expr) -> bool { - match self { - Val(e0a) => { - match *other { - Val(e0b) => e0a == e0b, - _ => false - } - } - Plus(e0a, e1a) => { - match *other { - Plus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - Minus(e0a, e1a) => { - match *other { - Minus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - } - } - pure fn ne(other: &Expr) -> bool { !self.eq(other) } -} - -impl AnEnum : cmp::Eq { - pure fn eq(other: &AnEnum) -> bool { - self.v == other.v - } - pure fn ne(other: &AnEnum) -> bool { !self.eq(other) } -} - -impl Point : cmp::Eq { - pure fn eq(other: &Point) -> bool { - self.x == other.x && self.y == other.y - } - pure fn ne(other: &Point) -> bool { !self.eq(other) } -} - -impl<T:cmp::Eq> Quark<T> : cmp::Eq { - pure fn eq(other: &Quark<T>) -> bool { - match self { - Top(ref q) => { - match *other { - Top(ref r) => q == r, - Bottom(_) => false - } - }, - Bottom(ref q) => { - match *other { - Top(_) => false, - Bottom(ref r) => q == r - } - }, - } - } - pure fn ne(other: &Quark<T>) -> bool { !self.eq(other) } -} - -impl CLike : cmp::Eq { - pure fn eq(other: &CLike) -> bool { - self as int == *other as int - } - pure fn ne(other: &CLike) -> bool { !self.eq(other) } -} - -#[auto_serialize2] -#[auto_deserialize2] -type Spanned<T> = {lo: uint, hi: uint, node: T}; - -impl<T:cmp::Eq> Spanned<T> : cmp::Eq { - pure fn eq(other: &Spanned<T>) -> bool { - self.lo == other.lo && self.hi == other.hi && self.node == other.node - } - pure fn ne(other: &Spanned<T>) -> bool { !self.eq(other) } -} - -#[auto_serialize2] -#[auto_deserialize2] -type SomeRec = {v: ~[uint]}; - -#[auto_serialize2] -#[auto_deserialize2] -enum AnEnum = SomeRec; - -#[auto_serialize2] -#[auto_deserialize2] -struct Point {x: uint, y: uint} - -#[auto_serialize2] -#[auto_deserialize2] -enum Quark<T> { - Top(T), - Bottom(T) -} - -#[auto_serialize2] -#[auto_deserialize2] -enum CLike { A, B, C } - -fn main() { - test_ser_and_deser(&Plus(@Minus(@Val(3u), @Val(10u)), - @Plus(@Val(22u), @Val(5u))), - ~"Plus(@Minus(@Val(3u), @Val(10u)), \ - @Plus(@Val(22u), @Val(5u)))"); - - test_ser_and_deser(&{lo: 0u, hi: 5u, node: 22u}, - ~"{lo: 0u, hi: 5u, node: 22u}"); - - test_ser_and_deser(&AnEnum({v: ~[1u, 2u, 3u]}), - ~"AnEnum({v: ~[1u, 2u, 3u]})"); - - test_ser_and_deser(&Point {x: 3u, y: 5u}, ~"Point {x: 3u, y: 5u}"); - - test_ser_and_deser(&@[1u, 2u, 3u], ~"@[1u, 2u, 3u]"); - - test_ser_and_deser(&Top(22u), ~"Top(22u)"); - test_ser_and_deser(&Bottom(222u), ~"Bottom(222u)"); - - test_ser_and_deser(&A, ~"A"); - test_ser_and_deser(&B, ~"B"); -} diff --git a/src/test/run-pass/borrowck-fixed-length-vecs.rs b/src/test/run-pass/borrowck-fixed-length-vecs.rs index 9d79e28b219..22862d7e58f 100644 --- a/src/test/run-pass/borrowck-fixed-length-vecs.rs +++ b/src/test/run-pass/borrowck-fixed-length-vecs.rs @@ -1,5 +1,5 @@ fn main() { - let x = [22]/1; + let x = [22]; let y = &x[0]; assert *y == 22; -} \ No newline at end of file +} diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index c7517ab1b3d..8a51eb33857 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -45,7 +45,7 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { } impl cat: ToStr { - fn to_str() -> ~str { self.name } + pure fn to_str() -> ~str { self.name } } fn print_out<T: ToStr>(thing: T, expected: ~str) { diff --git a/src/test/run-pass/const-fields-and-indexing.rs b/src/test/run-pass/const-fields-and-indexing.rs index 387ca032f6a..a5bcfc93c79 100644 --- a/src/test/run-pass/const-fields-and-indexing.rs +++ b/src/test/run-pass/const-fields-and-indexing.rs @@ -1,4 +1,4 @@ -const x : [int]/4 = [1,2,3,4]; +const x : [int * 4] = [1,2,3,4]; const p : int = x[2]; const y : &[int] = &[1,2,3,4]; const q : int = y[2]; @@ -17,4 +17,4 @@ fn main() { assert p == 3; assert q == 3; assert t == 20; -} \ No newline at end of file +} diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs index 9cfee2d5dff..36327172fab 100644 --- a/src/test/run-pass/const-vecs-and-slices.rs +++ b/src/test/run-pass/const-vecs-and-slices.rs @@ -1,4 +1,4 @@ -const x : [int]/4 = [1,2,3,4]; +const x : [int * 4] = [1,2,3,4]; const y : &[int] = &[1,2,3,4]; fn main() { @@ -7,4 +7,4 @@ fn main() { assert x[1] == 2; assert x[3] == 4; assert x[3] == y[3]; -} \ No newline at end of file +} diff --git a/src/test/run-pass/default-method-simple.rs b/src/test/run-pass/default-method-simple.rs new file mode 100644 index 00000000000..6a05d958913 --- /dev/null +++ b/src/test/run-pass/default-method-simple.rs @@ -0,0 +1,23 @@ +trait Foo { + fn f() { + io::println("Hello!"); + self.g(); + } + fn g(); +} + +struct A { + x: int +} + +impl A : Foo { + fn g() { + io::println("Goodbye!"); + } +} + +fn main() { + let a = A { x: 1 }; + a.f(); +} + diff --git a/src/test/run-pass/early-vtbl-resolution.rs b/src/test/run-pass/early-vtbl-resolution.rs index 2bbbbf7ef17..002d8b27ca7 100644 --- a/src/test/run-pass/early-vtbl-resolution.rs +++ b/src/test/run-pass/early-vtbl-resolution.rs @@ -10,7 +10,7 @@ fn foo_func<A, B: thing<A>>(x: B) -> Option<A> { x.foo() } fn main() { for iter::eachi(&(Some({a: 0}))) |i, a| { - #debug["%u %d", i, a.a]; + debug!("%u %d", i, a.a); } let _x: Option<float> = foo_func(0); diff --git a/src/test/run-pass/evec-internal-boxes.rs b/src/test/run-pass/evec-internal-boxes.rs index ce0fe172cf8..5ad12510b38 100644 --- a/src/test/run-pass/evec-internal-boxes.rs +++ b/src/test/run-pass/evec-internal-boxes.rs @@ -1,7 +1,7 @@ fn main() { - let x : [@int]/5 = [@1,@2,@3,@4,@5]/5; - let _y : [@int]/5 = [@1,@2,@3,@4,@5]/_; - let mut z = [@1,@2,@3,@4,@5]/_; + let x : [@int * 5] = [@1,@2,@3,@4,@5]; + let _y : [@int * 5] = [@1,@2,@3,@4,@5]; + let mut z = [@1,@2,@3,@4,@5]; z = x; assert *z[0] == 1; assert *z[4] == 5; diff --git a/src/test/run-pass/evec-internal.rs b/src/test/run-pass/evec-internal.rs index 789660c11f0..7ee72272e0b 100644 --- a/src/test/run-pass/evec-internal.rs +++ b/src/test/run-pass/evec-internal.rs @@ -4,16 +4,16 @@ // Doesn't work; needs a design decision. fn main() { - let x : [int]/5 = [1,2,3,4,5]/5; - let _y : [int]/5 = [1,2,3,4,5]/_; - let mut z = [1,2,3,4,5]/_; + let x : [int * 5] = [1,2,3,4,5]; + let _y : [int * 5] = [1,2,3,4,5]; + let mut z = [1,2,3,4,5]; z = x; assert z[0] == 1; assert z[4] == 5; - let a : [int]/5 = [1,1,1,1,1]/_; - let b : [int]/5 = [2,2,2,2,2]/_; - let c : [int]/5 = [2,2,2,2,3]/_; + let a : [int * 5] = [1,1,1,1,1]; + let b : [int * 5] = [2,2,2,2,2]; + let c : [int * 5] = [2,2,2,2,3]; log(debug, a); diff --git a/src/test/run-pass/fixed_length_copy.rs b/src/test/run-pass/fixed_length_copy.rs index 5bf6eb9a44d..ca42fc35f2b 100644 --- a/src/test/run-pass/fixed_length_copy.rs +++ b/src/test/run-pass/fixed_length_copy.rs @@ -3,7 +3,7 @@ // are implicitly copyable #[deny(implicit_copies)] fn main() { - let arr = [1,2,3]/3; + let arr = [1,2,3]; let arr2 = arr; assert(arr[1] == 2); assert(arr2[2] == 3); diff --git a/src/test/run-pass/fixed_length_vec_glue.rs b/src/test/run-pass/fixed_length_vec_glue.rs index 8be0b1b0c43..d9488c5abd8 100644 --- a/src/test/run-pass/fixed_length_vec_glue.rs +++ b/src/test/run-pass/fixed_length_vec_glue.rs @@ -1,5 +1,5 @@ fn main() { - let arr = [1,2,3]/3; + let arr = [1,2,3]; let struc = {a: 13u8, b: arr, c: 42}; let s = sys::log_str(&struc); assert(s == ~"{ a: 13, b: [ 1, 2, 3 ], c: 42 }"); diff --git a/src/test/run-pass/fn-bare-spawn.rs b/src/test/run-pass/fn-bare-spawn.rs index 2655b0260fd..f50d74a2df2 100644 --- a/src/test/run-pass/fn-bare-spawn.rs +++ b/src/test/run-pass/fn-bare-spawn.rs @@ -1,7 +1,7 @@ // This is what the signature to spawn should look like with bare functions fn spawn<T: Send>(val: T, f: extern fn(T)) { - f(val); + f(move val); } fn f(+i: int) { diff --git a/src/test/run-pass/functional-struct-update.rs b/src/test/run-pass/functional-struct-update.rs index ce6198c8d24..e95027a4246 100644 --- a/src/test/run-pass/functional-struct-update.rs +++ b/src/test/run-pass/functional-struct-update.rs @@ -5,7 +5,7 @@ struct Foo { fn main() { let a = Foo { x: 1, y: 2 }; - let c = Foo { x: 4, .. a }; + let c = Foo { x: 4, .. a}; io::println(fmt!("%?", c)); } diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index 683321aac3d..e32656894a8 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -8,6 +8,6 @@ extern mod rusti { fn main() { let mut x = @1; let mut y = @2; - rusti::move_val(&mut y, x); + rusti::move_val(&mut y, move x); assert *y == 1; } \ No newline at end of file diff --git a/src/test/run-pass/issue-2185.rs b/src/test/run-pass/issue-2185.rs index 3b3b63308cd..cda85fb166a 100644 --- a/src/test/run-pass/issue-2185.rs +++ b/src/test/run-pass/issue-2185.rs @@ -28,7 +28,7 @@ fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B { do self.iter |a| { b <- blk(b, a); } - return b; + move b } fn range(lo: uint, hi: uint, it: fn(uint)) { diff --git a/src/test/run-pass/issue-2216.rs b/src/test/run-pass/issue-2216.rs new file mode 100644 index 00000000000..11815db1763 --- /dev/null +++ b/src/test/run-pass/issue-2216.rs @@ -0,0 +1,22 @@ +fn main() { + let mut x = 0; + + loop foo: { + loop bar: { + loop quux: { + if 1 == 2 { + break foo; + } + else { + break bar; + } + } + loop foo; + } + x = 42; + break; + } + + error!("%?", x); + assert(x == 42); +} \ No newline at end of file diff --git a/src/test/run-pass/issue-2284.rs b/src/test/run-pass/issue-2284.rs new file mode 100644 index 00000000000..c2c4c03fb8f --- /dev/null +++ b/src/test/run-pass/issue-2284.rs @@ -0,0 +1,10 @@ +trait Send { + fn f(); +} + +fn f<T: Send>(t: T) { + t.f(); +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/run-pass/issue-2428.rs b/src/test/run-pass/issue-2428.rs new file mode 100644 index 00000000000..76fc674e734 --- /dev/null +++ b/src/test/run-pass/issue-2428.rs @@ -0,0 +1,10 @@ +fn main() { + let foo = 100; + const quux: int = 5; + + enum Stuff { + Bar = quux + } + + assert (Bar as int == quux); +} diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index b887b86cf2f..e91194b009a 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -1,3 +1,5 @@ +// tjc: I don't know why +// xfail-pretty mod pipes { #[legacy_exports]; use cast::{forget, transmute}; @@ -42,18 +44,18 @@ mod pipes { // We should consider moving this to core::unsafe, although I // suspect graydon would want us to use void pointers instead. unsafe fn uniquify<T>(+x: *T) -> ~T { - unsafe { cast::transmute(x) } + unsafe { cast::transmute(move x) } } fn swap_state_acq(+dst: &mut state, src: state) -> state { unsafe { - transmute(rusti::atomic_xchg_acq(transmute(dst), src as int)) + transmute(rusti::atomic_xchg_acq(transmute(move dst), src as int)) } } fn swap_state_rel(+dst: &mut state, src: state) -> state { unsafe { - transmute(rusti::atomic_xchg_rel(transmute(dst), src as int)) + transmute(rusti::atomic_xchg_rel(transmute(move dst), src as int)) } } @@ -61,20 +63,20 @@ mod pipes { let p = p.unwrap(); let p = unsafe { uniquify(p) }; assert (*p).payload.is_none(); - (*p).payload <- Some(payload); + (*p).payload <- Some(move payload); let old_state = swap_state_rel(&mut (*p).state, full); match old_state { empty => { // Yay, fastpath. // The receiver will eventually clean this up. - unsafe { forget(p); } + unsafe { forget(move p); } } full => { fail ~"duplicate send" } blocked => { // The receiver will eventually clean this up. - unsafe { forget(p); } + unsafe { forget(move p); } } terminated => { // The receiver will never receive this. Rely on drop_glue @@ -94,7 +96,7 @@ mod pipes { full => { let mut payload = None; payload <-> (*p).payload; - return Some(option::unwrap(payload)) + return Some(option::unwrap(move payload)) } terminated => { assert old_state == terminated; @@ -109,7 +111,7 @@ mod pipes { match swap_state_rel(&mut (*p).state, terminated) { empty | blocked => { // The receiver will eventually clean up. - unsafe { forget(p) } + unsafe { forget(move p) } } full => { // This is impossible @@ -126,7 +128,7 @@ mod pipes { match swap_state_rel(&mut (*p).state, terminated) { empty => { // the sender will clean up - unsafe { forget(p) } + unsafe { forget(move p) } } blocked => { // this shouldn't happen. @@ -144,7 +146,7 @@ mod pipes { if self.p != None { let mut p = None; p <-> self.p; - sender_terminate(option::unwrap(p)) + sender_terminate(option::unwrap(move p)) } } } @@ -153,7 +155,7 @@ mod pipes { fn unwrap() -> *packet<T> { let mut p = None; p <-> self.p; - option::unwrap(p) + option::unwrap(move p) } } @@ -169,7 +171,7 @@ mod pipes { if self.p != None { let mut p = None; p <-> self.p; - receiver_terminate(option::unwrap(p)) + receiver_terminate(option::unwrap(move p)) } } } @@ -178,7 +180,7 @@ mod pipes { fn unwrap() -> *packet<T> { let mut p = None; p <-> self.p; - option::unwrap(p) + option::unwrap(move p) } } @@ -204,8 +206,8 @@ mod pingpong { ping(x) => { cast::transmute(ptr::addr_of(&x)) } }; let liberated_value <- *addr; - cast::forget(p); - liberated_value + cast::forget(move p); + move liberated_value } fn liberate_pong(-p: pong) -> pipes::send_packet<ping> unsafe { @@ -213,8 +215,8 @@ mod pingpong { pong(x) => { cast::transmute(ptr::addr_of(&x)) } }; let liberated_value <- *addr; - cast::forget(p); - liberated_value + cast::forget(move p); + move liberated_value } fn init() -> (client::ping, server::ping) { @@ -229,16 +231,16 @@ mod pingpong { fn do_ping(-c: ping) -> pong { let (sp, rp) = pipes::entangle(); - pipes::send(c, ping(sp)); - rp + pipes::send(move c, ping(move sp)); + move rp } fn do_pong(-c: pong) -> (ping, ()) { - let packet = pipes::recv(c); + let packet = pipes::recv(move c); if packet.is_none() { fail ~"sender closed the connection" } - (liberate_pong(option::unwrap(packet)), ()) + (liberate_pong(option::unwrap(move packet)), ()) } } @@ -248,32 +250,32 @@ mod pingpong { type pong = pipes::send_packet<pingpong::pong>; fn do_ping(-c: ping) -> (pong, ()) { - let packet = pipes::recv(c); + let packet = pipes::recv(move c); if packet.is_none() { fail ~"sender closed the connection" } - (liberate_ping(option::unwrap(packet)), ()) + (liberate_ping(option::unwrap(move packet)), ()) } fn do_pong(-c: pong) -> ping { let (sp, rp) = pipes::entangle(); - pipes::send(c, pong(sp)); - rp + pipes::send(move c, pong(move sp)); + move rp } } } fn client(-chan: pingpong::client::ping) { - let chan = pingpong::client::do_ping(chan); + let chan = pingpong::client::do_ping(move chan); log(error, ~"Sent ping"); - let (chan, _data) = pingpong::client::do_pong(chan); + let (_chan, _data) = pingpong::client::do_pong(move chan); log(error, ~"Received pong"); } fn server(-chan: pingpong::server::ping) { - let (chan, _data) = pingpong::server::do_ping(chan); + let (chan, _data) = pingpong::server::do_ping(move chan); log(error, ~"Received ping"); - let chan = pingpong::server::do_pong(chan); + let _chan = pingpong::server::do_pong(move chan); log(error, ~"Sent pong"); } diff --git a/src/test/run-pass/issue-2834.rs b/src/test/run-pass/issue-2834.rs index b61169ee5f6..096ee2eed48 100644 --- a/src/test/run-pass/issue-2834.rs +++ b/src/test/run-pass/issue-2834.rs @@ -9,7 +9,7 @@ proto! streamp ( fn rendezvous() { let (c, s) = streamp::init(); - let streams: ~[streamp::client::open<int>] = ~[c]; + let streams: ~[streamp::client::open<int>] = ~[move c]; error!("%?", streams[0]); } diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs new file mode 100644 index 00000000000..1765e8638a6 --- /dev/null +++ b/src/test/run-pass/issue-2895.rs @@ -0,0 +1,23 @@ +use sys::size_of; +extern mod std; + +struct Cat { + x: int +} + +struct Kitty { + x: int, + drop {} +} + +#[cfg(target_arch = "x86_64")] +fn main() { + assert (size_of::<Cat>() == 8 as uint); + assert (size_of::<Kitty>() == 16 as uint); +} + +#[cfg(target_arch = "x86")] +fn main() { + assert (size_of::<Cat>() == 4 as uint); + assert (size_of::<Kitty>() == 8 as uint); +} diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 6d771dc7386..5cc39f4d683 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -16,7 +16,7 @@ enum square { } impl square: to_str::ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { match self { bot => { ~"R" } wall => { ~"#" } @@ -41,14 +41,14 @@ fn square_from_char(c: char) -> square { '.' => { earth } ' ' => { empty } _ => { - #error("invalid square: %?", c); + error!("invalid square: %?", c); fail } } } fn read_board_grid<rdr: Owned io::Reader>(+in: rdr) -> ~[~[square]] { - let in = in as io::Reader; + let in = (move in) as io::Reader; let mut grid = ~[]; for in.each_line |line| { let mut row = ~[]; diff --git a/src/test/run-pass/issue-2930.rs b/src/test/run-pass/issue-2930.rs index 98cfaded04a..bccaeeaf18d 100644 --- a/src/test/run-pass/issue-2930.rs +++ b/src/test/run-pass/issue-2930.rs @@ -1,11 +1,11 @@ proto! stream ( - stream:send<T:Send> { - send(T) -> stream<T> + Stream:send<T:Send> { + send(T) -> Stream<T> } ) fn main() { let (bc, _bp) = stream::init(); - stream::client::send(bc, ~"abc"); + stream::client::send(move bc, ~"abc"); } diff --git a/src/test/run-pass/issue-2935.rs b/src/test/run-pass/issue-2935.rs index 855f5caf9a0..86ba11560b2 100644 --- a/src/test/run-pass/issue-2935.rs +++ b/src/test/run-pass/issue-2935.rs @@ -19,6 +19,6 @@ fn main() { // x.f(); // y.f(); // (*z).f(); - #error["ok so far..."]; + error!("ok so far..."); z.f(); //segfault } diff --git a/src/test/run-pass/issue-2989.rs b/src/test/run-pass/issue-2989.rs index 0dd383e4039..0cabe1adb28 100644 --- a/src/test/run-pass/issue-2989.rs +++ b/src/test/run-pass/issue-2989.rs @@ -26,8 +26,8 @@ fn main() { let bools2 = to_bools({storage: ~[0b01100100]}); for uint::range(0, 8) |i| { - io::println(#fmt("%u => %u vs %u", i, bools[i] as uint, bools2[i] as uint)); + io::println(fmt!("%u => %u vs %u", i, bools[i] as uint, bools2[i] as uint)); } assert bools == bools2; -} \ No newline at end of file +} diff --git a/src/test/run-pass/issue-3168.rs b/src/test/run-pass/issue-3168.rs index 0da0ade0892..44a96a276ea 100644 --- a/src/test/run-pass/issue-3168.rs +++ b/src/test/run-pass/issue-3168.rs @@ -2,20 +2,20 @@ fn main() { let (c,p) = pipes::stream(); - do task::try { + do task::try |move c| { let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move p2| { p2.recv(); - #error["brother fails"]; + error!("sibling fails"); fail; } let (c3,p3) = pipes::stream(); - c.send(c3); + c.send(move c3); c2.send(()); - #error["child blocks"]; + error!("child blocks"); p3.recv(); }; - #error["parent tries"]; + error!("parent tries"); assert !p.recv().try_send(()); - #error("all done!"); + error!("all done!"); } diff --git a/src/test/run-pass/issue-3176.rs b/src/test/run-pass/issue-3176.rs index 002c7d4c518..17e6c03c954 100644 --- a/src/test/run-pass/issue-3176.rs +++ b/src/test/run-pass/issue-3176.rs @@ -4,22 +4,22 @@ use pipes::{Select2, Selectable}; fn main() { let (c,p) = pipes::stream(); - do task::try { + do task::try |move c| { let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move p2| { p2.recv(); - #error["brother fails"]; + error!("sibling fails"); fail; } let (c3,p3) = pipes::stream(); - c.send(c3); + c.send(move c3); c2.send(()); - #error["child blocks"]; + error!("child blocks"); let (c, p) = pipes::stream(); - (p, p3).select(); + (move p, move p3).select(); c.send(()); }; - #error["parent tries"]; + error!("parent tries"); assert !p.recv().try_send(()); - #error("all done!"); + error!("all done!"); } diff --git a/src/test/run-pass/issue-3447.rs b/src/test/run-pass/issue-3447.rs new file mode 100644 index 00000000000..7302163a312 --- /dev/null +++ b/src/test/run-pass/issue-3447.rs @@ -0,0 +1,24 @@ +struct list<T> { + element: &self/T, + mut next: Option<@list<T>> +} + +impl<T> list<T>{ + fn addEnd(&self, element: &self/T) { + let newList = list { + element: element, + next: option::None + }; + + self.next = Some(@(move newList)); + } +} + +fn main() { + let s = @"str"; + let ls = list { + element: &s, + next: option::None + }; + io::println(*ls.element); +} diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs new file mode 100644 index 00000000000..5e9835b4f6f --- /dev/null +++ b/src/test/run-pass/issue-3656.rs @@ -0,0 +1,21 @@ +// xfail-fast Can't redeclare malloc with wrong signature because bugs +// Issue #3656 +// Incorrect struct size computation in the FFI, because of not taking +// the alignment of elements into account. + +use libc::*; + +struct KEYGEN { + hash_algorithm: [c_uint * 2], + count: uint32_t, + salt: *c_void, + salt_size: uint32_t, +} + +extern { + // Bogus signature, just need to test if it compiles. + pub fn malloc(++data: KEYGEN); +} + +fn main() { +} diff --git a/src/test/run-pass/issue_3136_b.rs b/src/test/run-pass/issue_3136_b.rs new file mode 100644 index 00000000000..ef8e1af56d7 --- /dev/null +++ b/src/test/run-pass/issue_3136_b.rs @@ -0,0 +1,6 @@ +// xfail-fast - check-fast doesn't understand aux-build +// aux-build:issue_3136_a.rc + +extern mod issue_3136_a; +fn main() {} + diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index a3451da6f9a..225ba63e6a5 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -75,7 +75,6 @@ mod test_stmt_single_attr_outer { #[attr = "val"] fn f() { } - /* FIXME: Issue #493 #[attr = "val"] mod mod1 { #[legacy_exports]; @@ -86,7 +85,6 @@ mod test_stmt_single_attr_outer { extern mod rustrt { #[legacy_exports]; } - */ } } diff --git a/src/test/run-pass/iter-all.rs b/src/test/run-pass/iter-all.rs index 75334db86cc..b5c10fd2c81 100644 --- a/src/test/run-pass/iter-all.rs +++ b/src/test/run-pass/iter-all.rs @@ -1,9 +1,9 @@ fn is_even(x: &uint) -> bool { (*x % 2) == 0 } fn main() { - assert ![1u, 2u]/_.all(is_even); - assert [2u, 4u]/_.all(is_even); - assert []/_.all(is_even); + assert ![1u, 2u].all(is_even); + assert [2u, 4u].all(is_even); + assert [].all(is_even); assert !Some(1u).all(is_even); assert Some(2u).all(is_even); diff --git a/src/test/run-pass/iter-any.rs b/src/test/run-pass/iter-any.rs index 22057b74a41..f964eda54a5 100644 --- a/src/test/run-pass/iter-any.rs +++ b/src/test/run-pass/iter-any.rs @@ -1,9 +1,9 @@ fn is_even(x: &uint) -> bool { (*x % 2) == 0 } fn main() { - assert ![1u, 3u]/_.any(is_even); - assert [1u, 2u]/_.any(is_even); - assert ![]/_.any(is_even); + assert ![1u, 3u].any(is_even); + assert [1u, 2u].any(is_even); + assert ![].any(is_even); assert !Some(1).any(is_even); assert Some(2).any(is_even); diff --git a/src/test/run-pass/iter-contains.rs b/src/test/run-pass/iter-contains.rs index 6036b5b2d24..31fa52175aa 100644 --- a/src/test/run-pass/iter-contains.rs +++ b/src/test/run-pass/iter-contains.rs @@ -1,9 +1,9 @@ fn main() { - assert []/_.contains(&22u) == false; - assert [1u, 3u]/_.contains(&22u) == false; - assert [22u, 1u, 3u]/_.contains(&22u) == true; - assert [1u, 22u, 3u]/_.contains(&22u) == true; - assert [1u, 3u, 22u]/_.contains(&22u) == true; + assert [].contains(&22u) == false; + assert [1u, 3u].contains(&22u) == false; + assert [22u, 1u, 3u].contains(&22u) == true; + assert [1u, 22u, 3u].contains(&22u) == true; + assert [1u, 3u, 22u].contains(&22u) == true; assert None.contains(&22u) == false; assert Some(1u).contains(&22u) == false; assert Some(22u).contains(&22u) == true; diff --git a/src/test/run-pass/iter-count.rs b/src/test/run-pass/iter-count.rs index 0b6f94367be..26aa26b4c8d 100644 --- a/src/test/run-pass/iter-count.rs +++ b/src/test/run-pass/iter-count.rs @@ -1,8 +1,8 @@ fn main() { - assert []/_.count(&22u) == 0u; - assert [1u, 3u]/_.count(&22u) == 0u; - assert [22u, 1u, 3u]/_.count(&22u) == 1u; - assert [22u, 1u, 22u]/_.count(&22u) == 2u; + assert [].count(&22u) == 0u; + assert [1u, 3u].count(&22u) == 0u; + assert [22u, 1u, 3u].count(&22u) == 1u; + assert [22u, 1u, 22u].count(&22u) == 2u; assert None.count(&22u) == 0u; assert Some(1u).count(&22u) == 0u; assert Some(22u).count(&22u) == 1u; diff --git a/src/test/run-pass/iter-eachi.rs b/src/test/run-pass/iter-eachi.rs index 9ae3cc43913..4c85e6ca3af 100644 --- a/src/test/run-pass/iter-eachi.rs +++ b/src/test/run-pass/iter-eachi.rs @@ -1,6 +1,6 @@ fn main() { let mut c = 0u; - for [1u, 2u, 3u, 4u, 5u]/_.eachi |i, v| { + for [1u, 2u, 3u, 4u, 5u].eachi |i, v| { assert (i + 1u) == *v; c += 1u; } diff --git a/src/test/run-pass/iter-filter-to-vec.rs b/src/test/run-pass/iter-filter-to-vec.rs index f96b18f140a..000e7c491be 100644 --- a/src/test/run-pass/iter-filter-to-vec.rs +++ b/src/test/run-pass/iter-filter-to-vec.rs @@ -1,8 +1,8 @@ fn is_even(+x: uint) -> bool { (x % 2) == 0 } fn main() { - assert [1, 3]/_.filter_to_vec(is_even) == ~[]; - assert [1, 2, 3]/_.filter_to_vec(is_even) == ~[2]; + assert [1, 3].filter_to_vec(is_even) == ~[]; + assert [1, 2, 3].filter_to_vec(is_even) == ~[2]; assert None.filter_to_vec(is_even) == ~[]; assert Some(1).filter_to_vec(is_even) == ~[]; assert Some(2).filter_to_vec(is_even) == ~[2]; diff --git a/src/test/run-pass/iter-foldl.rs b/src/test/run-pass/iter-foldl.rs index bbc1673f686..65b517acf1c 100644 --- a/src/test/run-pass/iter-foldl.rs +++ b/src/test/run-pass/iter-foldl.rs @@ -1,8 +1,8 @@ fn add(x: &float, y: &uint) -> float { *x + ((*y) as float) } fn main() { - assert [1u, 3u]/_.foldl(20f, add) == 24f; - assert []/_.foldl(20f, add) == 20f; + assert [1u, 3u].foldl(20f, add) == 24f; + assert [].foldl(20f, add) == 20f; assert None.foldl(20f, add) == 20f; assert Some(1u).foldl(20f, add) == 21f; assert Some(2u).foldl(20f, add) == 22f; diff --git a/src/test/run-pass/iter-map-to-vec.rs b/src/test/run-pass/iter-map-to-vec.rs index 2f5359f197f..208fc5d127e 100644 --- a/src/test/run-pass/iter-map-to-vec.rs +++ b/src/test/run-pass/iter-map-to-vec.rs @@ -1,8 +1,8 @@ fn inc(+x: uint) -> uint { x + 1 } fn main() { - assert [1, 3]/_.map_to_vec(inc) == ~[2, 4]; - assert [1, 2, 3]/_.map_to_vec(inc) == ~[2, 3, 4]; + assert [1, 3].map_to_vec(inc) == ~[2, 4]; + assert [1, 2, 3].map_to_vec(inc) == ~[2, 3, 4]; assert None.map_to_vec(inc) == ~[]; assert Some(1).map_to_vec(inc) == ~[2]; assert Some(2).map_to_vec(inc) == ~[3]; diff --git a/src/test/run-pass/iter-min-max.rs b/src/test/run-pass/iter-min-max.rs index 23bd7fb05af..60001c8f7e5 100644 --- a/src/test/run-pass/iter-min-max.rs +++ b/src/test/run-pass/iter-min-max.rs @@ -1,11 +1,11 @@ fn is_even(&&x: uint) -> bool { (x % 2u) == 0u } fn main() { - assert [1u, 3u]/_.min() == 1u; - assert [3u, 1u]/_.min() == 1u; + assert [1u, 3u].min() == 1u; + assert [3u, 1u].min() == 1u; assert Some(1u).min() == 1u; - assert [1u, 3u]/_.max() == 3u; - assert [3u, 1u]/_.max() == 3u; + assert [1u, 3u].max() == 3u; + assert [3u, 1u].max() == 3u; assert Some(3u).max() == 3u; } diff --git a/src/test/run-pass/iter-to-vec.rs b/src/test/run-pass/iter-to-vec.rs index c2f1330b721..358f484464d 100644 --- a/src/test/run-pass/iter-to-vec.rs +++ b/src/test/run-pass/iter-to-vec.rs @@ -1,5 +1,5 @@ fn main() { - assert [1u, 3u]/_.to_vec() == ~[1u, 3u]; + assert [1u, 3u].to_vec() == ~[1u, 3u]; let e: ~[uint] = ~[]; assert e.to_vec() == ~[]; assert None::<uint>.to_vec() == ~[]; diff --git a/src/test/run-pass/last-use-corner-cases.rs b/src/test/run-pass/last-use-corner-cases.rs index a3088a2c125..510fc8ddeaa 100644 --- a/src/test/run-pass/last-use-corner-cases.rs +++ b/src/test/run-pass/last-use-corner-cases.rs @@ -5,7 +5,7 @@ fn main() { // Make sure closing over can be a last use let q = ~10; let addr = ptr::addr_of(&(*q)); - let f = fn@() -> *int { ptr::addr_of(&(*q)) }; + let f = fn@(move q) -> *int { ptr::addr_of(&(*q)) }; assert addr == f(); // But only when it really is the last use diff --git a/src/test/run-pass/last-use-in-block.rs b/src/test/run-pass/last-use-in-block.rs index c1dc0b76a10..56c6659743d 100644 --- a/src/test/run-pass/last-use-in-block.rs +++ b/src/test/run-pass/last-use-in-block.rs @@ -3,14 +3,14 @@ fn lp<T>(s: ~str, f: fn(~str) -> T) -> T { while false { let r = f(s); - return r; + return (move r); } fail; } fn apply<T>(s: ~str, f: fn(~str) -> T) -> T { fn g<T>(s: ~str, f: fn(~str) -> T) -> T {f(s)} - g(s, |v| { let r = f(v); r }) + g(s, |v| { let r = f(v); move r }) } fn main() {} diff --git a/src/test/run-pass/liveness-move-in-loop.rs b/src/test/run-pass/liveness-move-in-loop.rs index e0a05c9b297..d52395b4c7c 100644 --- a/src/test/run-pass/liveness-move-in-loop.rs +++ b/src/test/run-pass/liveness-move-in-loop.rs @@ -5,7 +5,7 @@ fn the_loop() { loop { let x = 5; if x > 3 { - list += ~[take(x)]; + list += ~[take(move x)]; } else { break; } diff --git a/src/test/run-pass/log-linearized.rs b/src/test/run-pass/log-linearized.rs index bb042f2359b..bb9a4278467 100644 --- a/src/test/run-pass/log-linearized.rs +++ b/src/test/run-pass/log-linearized.rs @@ -9,7 +9,7 @@ type smallintmap<T> = @{mut v: ~[mut option<T>]}; fn mk<T>() -> smallintmap<T> { let v: ~[mut option<T>] = ~[mut]; - return @{mut v: v}; + return @{mut v: move v}; } fn f<T,U>() { diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index c771249c9ed..eed871ce4b8 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -15,7 +15,7 @@ struct F<A> { a: A } impl<A: Copy Serializable> F<A>: Serializable { fn serialize<S: Serializer>(s: S) { - self.a.serialize(s); + self.a.serialize(move s); } } diff --git a/src/test/run-pass/move-arg-2-unique.rs b/src/test/run-pass/move-arg-2-unique.rs index e312d2afb4b..fded13293f3 100644 --- a/src/test/run-pass/move-arg-2-unique.rs +++ b/src/test/run-pass/move-arg-2-unique.rs @@ -3,7 +3,7 @@ fn test(-foo: ~~[int]) { assert (foo[0] == 10); } fn main() { let x = ~~[10]; // Test forgetting a local by move-in - test(x); + test(move x); // Test forgetting a temporary by move-in. test(~~[10]); diff --git a/src/test/run-pass/move-arg-2.rs b/src/test/run-pass/move-arg-2.rs index 01e287c0db0..1f2f3b9ad3b 100644 --- a/src/test/run-pass/move-arg-2.rs +++ b/src/test/run-pass/move-arg-2.rs @@ -3,7 +3,7 @@ fn test(-foo: @~[int]) { assert (foo[0] == 10); } fn main() { let x = @~[10]; // Test forgetting a local by move-in - test(x); + test(move x); // Test forgetting a temporary by move-in. test(@~[10]); diff --git a/src/test/run-pass/move-arg.rs b/src/test/run-pass/move-arg.rs index 286b7c6cb6d..1db4d9cef74 100644 --- a/src/test/run-pass/move-arg.rs +++ b/src/test/run-pass/move-arg.rs @@ -1,3 +1,3 @@ fn test(-foo: int) { assert (foo == 10); } -fn main() { let x = 10; test(x); } +fn main() { let x = 10; test(move x); } diff --git a/src/test/run-pass/move-nullary-fn.rs b/src/test/run-pass/move-nullary-fn.rs index e5331a11556..0c02affb1c5 100644 --- a/src/test/run-pass/move-nullary-fn.rs +++ b/src/test/run-pass/move-nullary-fn.rs @@ -2,7 +2,7 @@ fn f2(-thing: fn@()) { } fn f(-thing: fn@()) { - f2(thing); + f2(move thing); } fn main() { diff --git a/src/test/run-pass/non-legacy-modes.rs b/src/test/run-pass/non-legacy-modes.rs index 8fb843d8564..d6ece2c19c3 100644 --- a/src/test/run-pass/non-legacy-modes.rs +++ b/src/test/run-pass/non-legacy-modes.rs @@ -3,7 +3,7 @@ struct X { } fn apply<T>(x: T, f: fn(T)) { - f(x); + f(move x); } fn check_int(x: int) { diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs index 06b87794e59..7481b06d873 100644 --- a/src/test/run-pass/option-unwrap.rs +++ b/src/test/run-pass/option-unwrap.rs @@ -9,7 +9,7 @@ struct dtor { fn unwrap<T>(+o: Option<T>) -> T { match move o { - Some(move v) => v, + Some(move v) => move v, None => fail } } @@ -19,7 +19,7 @@ fn main() { { let b = Some(dtor { x:x }); - let c = unwrap(b); + let c = unwrap(move b); } assert *x == 0; diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs index 899b74b2866..e59634ad089 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -33,15 +33,15 @@ proto! bank ( ) macro_rules! move_it ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) fn switch<T: Send, U>(+endp: pipes::RecvPacket<T>, f: fn(+v: Option<T>) -> U) -> U { - f(pipes::try_recv(endp)) + f(pipes::try_recv(move endp)) } -fn move_it<T>(-x: T) -> T { x } +fn move_it<T>(-x: T) -> T { move x } macro_rules! follow ( { @@ -59,15 +59,15 @@ macro_rules! follow ( fn client_follow(+bank: bank::client::login) { use bank::*; - let bank = client::login(bank, ~"theincredibleholk", ~"1234"); - let bank = switch(bank, follow! ( - ok -> connected { connected } + let bank = client::login(move bank, ~"theincredibleholk", ~"1234"); + let bank = switch(move bank, follow! ( + ok -> connected { move connected } invalid -> _next { fail ~"bank closed the connected" } )); - let bank = client::deposit(bank, 100.00); - let bank = client::withdrawal(bank, 50.00); - switch(bank, follow! ( + let bank = client::deposit(move bank, 100.00); + let bank = client::withdrawal(move bank, 50.00); + switch(move bank, follow! ( money(m) -> _next { io::println(~"Yay! I got money!"); } @@ -80,8 +80,8 @@ fn client_follow(+bank: bank::client::login) { fn bank_client(+bank: bank::client::login) { use bank::*; - let bank = client::login(bank, ~"theincredibleholk", ~"1234"); - let bank = match try_recv(bank) { + let bank = client::login(move bank, ~"theincredibleholk", ~"1234"); + let bank = match try_recv(move bank) { Some(ok(connected)) => { move_it!(connected) } @@ -89,10 +89,10 @@ fn bank_client(+bank: bank::client::login) { None => { fail ~"bank closed the connection" } }; - let bank = client::deposit(bank, 100.00); - let bank = client::withdrawal(bank, 50.00); - match try_recv(bank) { - Some(money(m, _)) => { + let bank = client::deposit(move bank, 100.00); + let bank = client::withdrawal(move bank, 50.00); + match try_recv(move bank) { + Some(money(*)) => { io::println(~"Yay! I got money!"); } Some(insufficient_funds(_)) => { diff --git a/src/test/run-pass/pipe-detect-term.rs b/src/test/run-pass/pipe-detect-term.rs index 93c12449f2e..524541780c0 100644 --- a/src/test/run-pass/pipe-detect-term.rs +++ b/src/test/run-pass/pipe-detect-term.rs @@ -19,7 +19,7 @@ fn main() { let iotask = uv::global_loop::get(); pipes::spawn_service(oneshot::init, |p| { - match try_recv(p) { + match try_recv(move p) { Some(*) => { fail } None => { } } @@ -34,11 +34,11 @@ fn main() { fn failtest() { let (c, p) = oneshot::init(); - do task::spawn_with(c) |_c| { + do task::spawn_with(move c) |_c| { fail; } - error!("%?", recv(p)); + error!("%?", recv(move p)); // make sure we get killed if we missed it in the receive. loop { task::yield() } } diff --git a/src/test/run-pass/pipe-peek.rs b/src/test/run-pass/pipe-peek.rs index e8b2aa1a791..e3a2d29747b 100644 --- a/src/test/run-pass/pipe-peek.rs +++ b/src/test/run-pass/pipe-peek.rs @@ -15,7 +15,7 @@ fn main() { assert !pipes::peek(&p); - oneshot::client::signal(c); + oneshot::client::signal(move c); assert pipes::peek(&p); } diff --git a/src/test/run-pass/pipe-pingpong-bounded.rs b/src/test/run-pass/pipe-pingpong-bounded.rs index 9bfbbe338e7..0db7d6cf123 100644 --- a/src/test/run-pass/pipe-pingpong-bounded.rs +++ b/src/test/run-pass/pipe-pingpong-bounded.rs @@ -25,7 +25,7 @@ mod pingpong { pong: mk_packet::<pong>() } }; - do pipes::entangle_buffer(buffer) |buffer, data| { + do pipes::entangle_buffer(move buffer) |buffer, data| { data.ping.set_buffer_(buffer); data.pong.set_buffer_(buffer); ptr::addr_of(&(data.ping)) @@ -40,9 +40,9 @@ mod pingpong { let b = pipe.reuse_buffer(); let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.pong))); let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.pong))); - let message = pingpong::ping(s); - pipes::send(pipe, message); - c + let message = pingpong::ping(move s); + pipes::send(move pipe, move message); + move c } } type ping = pipes::SendPacketBuffered<pingpong::ping, @@ -59,9 +59,9 @@ mod pingpong { let b = pipe.reuse_buffer(); let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.ping))); let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.ping))); - let message = pingpong::pong(s); - pipes::send(pipe, message); - c + let message = pingpong::pong(move s); + pipes::send(move pipe, move message); + move c } } type pong = pipes::SendPacketBuffered<pingpong::pong, @@ -77,34 +77,34 @@ mod test { fn client(-chan: pingpong::client::ping) { use pingpong::client; - let chan = client::ping(chan); return; + let chan = client::ping(move chan); return; log(error, "Sent ping"); - let pong(_chan) = recv(chan); + let pong(_chan) = recv(move chan); log(error, "Received pong"); } fn server(-chan: pingpong::server::ping) { use pingpong::server; - let ping(chan) = recv(chan); return; + let ping(chan) = recv(move chan); return; log(error, "Received ping"); - let _chan = server::pong(chan); + let _chan = server::pong(move chan); log(error, "Sent pong"); } } fn main() { let (client_, server_) = pingpong::init(); - let client_ = ~mut Some(client_); - let server_ = ~mut Some(server_); + let client_ = ~mut Some(move client_); + let server_ = ~mut Some(move server_); do task::spawn |move client_| { let mut client__ = None; *client_ <-> client__; - test::client(option::unwrap(client__)); + test::client(option::unwrap(move client__)); }; do task::spawn |move server_| { let mut server_ˊ = None; *server_ <-> server_ˊ; - test::server(option::unwrap(server_ˊ)); + test::server(option::unwrap(move server_ˊ)); }; } diff --git a/src/test/run-pass/pipe-pingpong-proto.rs b/src/test/run-pass/pipe-pingpong-proto.rs index 7af00e8dbf2..c1c74aefa9c 100644 --- a/src/test/run-pass/pipe-pingpong-proto.rs +++ b/src/test/run-pass/pipe-pingpong-proto.rs @@ -20,35 +20,35 @@ mod test { fn client(-chan: pingpong::client::ping) { use pingpong::client; - let chan = client::ping(chan); + let chan = client::ping(move chan); log(error, ~"Sent ping"); - let pong(_chan) = recv(chan); + let pong(_chan) = recv(move chan); log(error, ~"Received pong"); } fn server(-chan: pingpong::server::ping) { use pingpong::server; - let ping(chan) = recv(chan); + let ping(chan) = recv(move chan); log(error, ~"Received ping"); - let _chan = server::pong(chan); + let _chan = server::pong(move chan); log(error, ~"Sent pong"); } } fn main() { let (client_, server_) = pingpong::init(); - let client_ = ~mut Some(client_); - let server_ = ~mut Some(server_); + let client_ = ~mut Some(move client_); + let server_ = ~mut Some(move server_); do task::spawn |move client_| { let mut client__ = None; *client_ <-> client__; - test::client(option::unwrap(client__)); + test::client(option::unwrap(move client__)); }; do task::spawn |move server_| { let mut server_ˊ = None; *server_ <-> server_ˊ; - test::server(option::unwrap(server_ˊ)); + test::server(option::unwrap(move server_ˊ)); }; } diff --git a/src/test/run-pass/pipe-presentation-examples.rs b/src/test/run-pass/pipe-presentation-examples.rs index f485148d79e..853aba53eda 100644 --- a/src/test/run-pass/pipe-presentation-examples.rs +++ b/src/test/run-pass/pipe-presentation-examples.rs @@ -22,10 +22,10 @@ macro_rules! select_if ( ], )* } => { if $index == $count { - match move pipes::try_recv($port) { + match move pipes::try_recv(move $port) { $(Some($message($($(move $x,)+)* move next)) => { - let $next = next; - $e + let $next = move next; + move $e })+ _ => fail } @@ -56,7 +56,7 @@ macro_rules! select ( -> $next:ident $e:expr),+ } )+ } => { - let index = pipes::selecti([$(($port).header()),+]/_); + let index = pipes::selecti([$(($port).header()),+]); select_if!(index, 0, $( $port => [ $($message$(($($x),+))dont_type_this* -> $next $e),+ ], )+) @@ -90,33 +90,33 @@ fn render(_buffer: &Buffer) { } fn draw_frame(+channel: double_buffer::client::acquire) { - let channel = request(channel); + let channel = request(move channel); select! ( channel => { give_buffer(buffer) -> channel { render(&buffer); - release(channel, move buffer) + release(move channel, move buffer) } } ); } fn draw_two_frames(+channel: double_buffer::client::acquire) { - let channel = request(channel); + let channel = request(move channel); let channel = select! ( channel => { give_buffer(buffer) -> channel { render(&buffer); - release(channel, move buffer) + release(move channel, move buffer) } } ); - let channel = request(channel); + let channel = request(move channel); select! ( channel => { give_buffer(buffer) -> channel { render(&buffer); - release(channel, move buffer) + release(move channel, move buffer) } } ); diff --git a/src/test/run-pass/pipe-select-macro.rs b/src/test/run-pass/pipe-select-macro.rs index 8554659a2ee..e3842c86c4c 100644 --- a/src/test/run-pass/pipe-select-macro.rs +++ b/src/test/run-pass/pipe-select-macro.rs @@ -1,3 +1,5 @@ +// tjc: un-xfail after snapshot +// xfail-test // xfail-pretty // Protocols @@ -42,7 +44,7 @@ fn test(+foo: foo::client::foo, +bar: bar::client::bar) { }, do_baz(b) -> _next { - if *b { debug!("true") } else { debug!("false") } + if b { debug!("true") } else { debug!("false") } } } ) diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 4d70eb62e94..23588de2eca 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -14,8 +14,8 @@ proto! oneshot ( ) proto! stream ( - stream:send<T:Send> { - send(T) -> stream<T> + Stream:send<T:Send> { + send(T) -> Stream<T> } ) @@ -27,24 +27,24 @@ fn main() { let c = pipes::spawn_service(stream::init, |p| { error!("waiting for pipes"); - let stream::send(x, p) = recv(p); + let stream::send(x, p) = recv(move p); error!("got pipes"); let (left, right) : (oneshot::server::waiting, oneshot::server::waiting) - = x; + = move x; error!("selecting"); - let (i, _, _) = select(~[left, right]); + let (i, _, _) = select(~[move left, move right]); error!("selected"); assert i == 0; error!("waiting for pipes"); - let stream::send(x, _) = recv(p); + let stream::send(x, _) = recv(move p); error!("got pipes"); let (left, right) : (oneshot::server::waiting, oneshot::server::waiting) - = x; + = move x; error!("selecting"); - let (i, m, _) = select(~[left, right]); + let (i, m, _) = select(~[move left, move right]); error!("selected %?", i); if m.is_some() { assert i == 1; @@ -54,20 +54,20 @@ fn main() { let (c1, p1) = oneshot::init(); let (_c2, p2) = oneshot::init(); - let c = send(c, (p1, p2)); + let c = send(move c, (move p1, move p2)); sleep(iotask, 100); - signal(c1); + signal(move c1); let (_c1, p1) = oneshot::init(); let (c2, p2) = oneshot::init(); - send(c, (p1, p2)); + send(move c, (move p1, move p2)); sleep(iotask, 100); - signal(c2); + signal(move c2); test_select2(); } @@ -76,26 +76,26 @@ fn test_select2() { let (ac, ap) = stream::init(); let (bc, bp) = stream::init(); - stream::client::send(ac, 42); + stream::client::send(move ac, 42); - match pipes::select2(ap, bp) { + match pipes::select2(move ap, move bp) { either::Left(*) => { } either::Right(*) => { fail } } - stream::client::send(bc, ~"abc"); + stream::client::send(move bc, ~"abc"); error!("done with first select2"); let (ac, ap) = stream::init(); let (bc, bp) = stream::init(); - stream::client::send(bc, ~"abc"); + stream::client::send(move bc, ~"abc"); - match pipes::select2(ap, bp) { + match pipes::select2(move ap, move bp) { either::Left(*) => { fail } either::Right(*) => { } } - stream::client::send(ac, 42); + stream::client::send(move ac, 42); } diff --git a/src/test/run-pass/pipe-sleep.rs b/src/test/run-pass/pipe-sleep.rs index 4e901c69d29..c9975bec946 100644 --- a/src/test/run-pass/pipe-sleep.rs +++ b/src/test/run-pass/pipe-sleep.rs @@ -14,10 +14,10 @@ proto! oneshot ( fn main() { use oneshot::client::*; - let c = pipes::spawn_service(oneshot::init, |p| { recv(p); }); + let c = pipes::spawn_service(oneshot::init, |p| { recv(move p); }); let iotask = uv::global_loop::get(); sleep(iotask, 500); - signal(c); + signal(move c); } \ No newline at end of file diff --git a/src/test/run-pass/pure-fmt.rs b/src/test/run-pass/pure-fmt.rs index 1671c3369ff..d757d0311b4 100644 --- a/src/test/run-pass/pure-fmt.rs +++ b/src/test/run-pass/pure-fmt.rs @@ -1,4 +1,4 @@ -// Testing that calling #fmt (via #debug) doesn't complain about impure borrows +// Testing that calling fmt! (via debug!) doesn't complain about impure borrows pure fn foo() { let a = { @@ -18,4 +18,4 @@ pure fn foo() { } fn main() { -} \ No newline at end of file +} diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index e27aaa618ac..24ae16f25e1 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -3,13 +3,7 @@ use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; use libc::c_void; - -// FIXME: this is a near-duplicate of code in core::vec. -type unboxed_vec_repr = { - mut fill: uint, - mut alloc: uint, - data: u8 -}; +use vec::UnboxedVecRepr; #[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."] @@ -238,8 +232,8 @@ impl<V: TyVisitor movable_ptr> ptr_visit_adaptor<V>: TyVisitor { } fn visit_unboxed_vec(mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<unboxed_vec_repr>(); - // FIXME: Inner really has to move its own pointers on this one. + self.align_to::<UnboxedVecRepr>(); + // FIXME (#3732): Inner really has to move its own pointers on this one. // or else possibly we could have some weird interface wherein we // read-off a word from inner's pointers, but the read-word has to // always be the same in all sub-pointers? Dubious. @@ -570,7 +564,7 @@ impl my_visitor: TyVisitor { fn visit_enter_enum(_n_variants: uint, _sz: uint, _align: uint) -> bool { - // FIXME: this needs to rewind between enum variants, or something. + // FIXME (#3732): this needs to rewind between enum variants, or something. true } fn visit_enter_enum_variant(_variant: uint, diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index f7eb2c01315..4d2d2a7170e 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -1,37 +1,35 @@ -// FIXME: un-xfail after snapshot // xfail-test - -use intrinsic::{tydesc, get_tydesc, visit_tydesc, ty_visitor}; +use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; enum my_visitor = @{ mut types: ~[str] }; -impl of ty_visitor for my_visitor { +impl my_visitor: TyVisitor { fn visit_bot() -> bool { - self.types += ["bot"]; + self.types += ~["bot"]; error!("visited bot type"); true } fn visit_nil() -> bool { - self.types += ["nil"]; + self.types += ~["nil"]; error!("visited nil type"); true } fn visit_bool() -> bool { - self.types += ["bool"]; + self.types += ~["bool"]; error!("visited bool type"); true } fn visit_int() -> bool { - self.types += ["int"]; + self.types += ~["int"]; error!("visited int type"); true } fn visit_i8() -> bool { - self.types += ["i8"]; + self.types += ~["i8"]; error!("visited i8 type"); true } fn visit_i16() -> bool { - self.types += ["i16"]; + self.types += ~["i16"]; error!("visited i16 type"); true } @@ -57,41 +55,41 @@ impl of ty_visitor for my_visitor { fn visit_estr_fixed(_sz: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_box(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_ptr(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_rptr(_mtbl: uint, _inner: *tydesc) -> bool { true } + fn visit_box(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_uniq(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_ptr(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_rptr(_mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_vec(_mtbl: uint, inner: *tydesc) -> bool { - self.types += ["["]; - visit_tydesc(inner, my_visitor(*self) as ty_visitor); - self.types += ["]"]; + fn visit_vec(_mtbl: uint, inner: *TyDesc) -> bool { + self.types += ~["["]; + visit_tydesc(inner, my_visitor(*self) as TyVisitor); + self.types += ~["]"]; true } - fn visit_unboxed_vec(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_evec_box(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_evec_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_evec_slice(_mtbl: uint, _inner: *tydesc) -> bool { true } + fn visit_unboxed_vec(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_box(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_uniq(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_slice(_mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_evec_fixed(_n: uint, _sz: uint, _align: uint, - _mtbl: uint, _inner: *tydesc) -> bool { true } + _mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_enter_rec(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_rec_field(_i: uint, _name: &str, - _mtbl: uint, _inner: *tydesc) -> bool { true } + _mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_rec(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_enter_class(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_class_field(_i: uint, _name: &str, - _mtbl: uint, _inner: *tydesc) -> bool { true } + _mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_class(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_enter_tup(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_tup_field(_i: uint, _inner: *tydesc) -> bool { true } + fn visit_tup_field(_i: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_tup(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } @@ -101,7 +99,7 @@ impl of ty_visitor for my_visitor { _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_enum_variant_field(_i: uint, _inner: *tydesc) -> bool { true } + fn visit_enum_variant_field(_i: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_enum_variant(_variant: uint, _disr_val: int, _n_fields: uint, @@ -111,8 +109,8 @@ impl of ty_visitor for my_visitor { fn visit_enter_fn(_purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(_i: uint, _mode: uint, _inner: *tydesc) -> bool { true } - fn visit_fn_output(_retstyle: uint, _inner: *tydesc) -> bool { true } + fn visit_fn_input(_i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } + fn visit_fn_output(_retstyle: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_fn(_purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } @@ -124,17 +122,17 @@ impl of ty_visitor for my_visitor { fn visit_self() -> bool { true } fn visit_type() -> bool { true } fn visit_opaque_box() -> bool { true } - fn visit_constr(_inner: *tydesc) -> bool { true } + fn visit_constr(_inner: *TyDesc) -> bool { true } fn visit_closure_ptr(_ck: uint) -> bool { true } } -fn visit_ty<T>(v: ty_visitor) { +fn visit_ty<T>(v: TyVisitor) { visit_tydesc(get_tydesc::<T>(), v); } fn main() { let v = my_visitor(@{mut types: ~[]}); - let vv = v as ty_visitor; + let vv = v as TyVisitor; visit_ty::<bool>(vv); visit_ty::<int>(vv); diff --git a/src/test/run-pass/regions-borrow-evec-fixed.rs b/src/test/run-pass/regions-borrow-evec-fixed.rs index 5a0875109f6..2526540bde1 100644 --- a/src/test/run-pass/regions-borrow-evec-fixed.rs +++ b/src/test/run-pass/regions-borrow-evec-fixed.rs @@ -5,6 +5,6 @@ fn foo(x: &[int]) -> int { } fn main() { - let p = [1,2,3,4,5]/_; + let p = [1,2,3,4,5]; assert foo(p) == 1; } diff --git a/src/test/run-pass/regions-copy-closure.rs b/src/test/run-pass/regions-copy-closure.rs index 2e03c5f82c4..834272ca920 100644 --- a/src/test/run-pass/regions-copy-closure.rs +++ b/src/test/run-pass/regions-copy-closure.rs @@ -2,8 +2,8 @@ struct closure_box { cl: &fn(), } -fn box_it(x: &r/fn()) -> closure_box/&r { - closure_box {cl: x} +fn box_it(+x: &r/fn()) -> closure_box/&r { + closure_box {cl: move x} } fn main() { diff --git a/src/test/run-pass/regions-static-closure.rs b/src/test/run-pass/regions-static-closure.rs index 61e04c4e776..6622a6aa569 100644 --- a/src/test/run-pass/regions-static-closure.rs +++ b/src/test/run-pass/regions-static-closure.rs @@ -2,8 +2,8 @@ struct closure_box { cl: &fn(), } -fn box_it(x: &r/fn()) -> closure_box/&r { - closure_box {cl: x} +fn box_it(+x: &r/fn()) -> closure_box/&r { + closure_box {cl: move x} } fn call_static_closure(cl: closure_box/&static) { @@ -12,5 +12,5 @@ fn call_static_closure(cl: closure_box/&static) { fn main() { let cl_box = box_it(|| debug!("Hello, world!")); - call_static_closure(cl_box); + call_static_closure(move cl_box); } diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs index 7f3bc016a6a..f0bea875df9 100644 --- a/src/test/run-pass/resource-assign-is-not-copy.rs +++ b/src/test/run-pass/resource-assign-is-not-copy.rs @@ -14,8 +14,8 @@ fn main() { // Even though these look like copies, they are guaranteed not to be { let a = r(i); - let b = (a, 10); - let (c, _d) = b; + let b = (move a, 10); + let (c, _d) = move b; log(debug, c); } assert *i == 1; diff --git a/src/test/run-pass/resource-cycle.rs b/src/test/run-pass/resource-cycle.rs index 26e19ee1b0c..893042842d0 100644 --- a/src/test/run-pass/resource-cycle.rs +++ b/src/test/run-pass/resource-cycle.rs @@ -24,10 +24,10 @@ enum t = { fn main() unsafe { let i1 = ~0; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let i2 = ~0; let i2p = cast::reinterpret_cast(&i2); - cast::forget(i2); + cast::forget(move i2); let x1 = @t({ mut next: None, @@ -35,7 +35,7 @@ fn main() unsafe { let rs = r(i1p); debug!("r = %x", cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); - rs } + move rs } }); debug!("x1 = %x, x1.r = %x", @@ -48,7 +48,7 @@ fn main() unsafe { let rs = r(i2p); debug!("r2 = %x", cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); - rs + move rs } }); diff --git a/src/test/run-pass/resource-cycle2.rs b/src/test/run-pass/resource-cycle2.rs index b522808c494..a38950e17e3 100644 --- a/src/test/run-pass/resource-cycle2.rs +++ b/src/test/run-pass/resource-cycle2.rs @@ -27,10 +27,10 @@ enum t = { fn main() unsafe { let i1 = ~0xA; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let i2 = ~0xA; let i2p = cast::reinterpret_cast(&i2); - cast::forget(i2); + cast::forget(move i2); let u1 = {a: 0xB, b: 0xC, c: i1p}; let u2 = {a: 0xB, b: 0xC, c: i2p}; diff --git a/src/test/run-pass/resource-cycle3.rs b/src/test/run-pass/resource-cycle3.rs index efb1915799c..aa0f18089d9 100644 --- a/src/test/run-pass/resource-cycle3.rs +++ b/src/test/run-pass/resource-cycle3.rs @@ -34,10 +34,10 @@ enum t = { fn main() unsafe { let i1 = ~0xA; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let i2 = ~0xA; let i2p = cast::reinterpret_cast(&i2); - cast::forget(i2); + cast::forget(move i2); let u1 = {a: 0xB, b: 0xC, c: i1p}; let u2 = {a: 0xB, b: 0xC, c: i2p}; diff --git a/src/test/run-pass/rt-sched-1.rs b/src/test/run-pass/rt-sched-1.rs index 690d93172eb..976225c0e23 100644 --- a/src/test/run-pass/rt-sched-1.rs +++ b/src/test/run-pass/rt-sched-1.rs @@ -35,6 +35,6 @@ fn main() unsafe { }; let fptr = cast::reinterpret_cast(&ptr::addr_of(&f)); rustrt::start_task(new_task_id, fptr); - cast::forget(f); + cast::forget(move f); comm::recv(po); } diff --git a/src/test/run-pass/select-macro.rs b/src/test/run-pass/select-macro.rs index 78bddffcc1d..271ed99057f 100644 --- a/src/test/run-pass/select-macro.rs +++ b/src/test/run-pass/select-macro.rs @@ -17,19 +17,18 @@ macro_rules! select_if ( $count:expr, $port:path => [ $(type_this $message:path$(($(x $x: ident),+))dont_type_this* - -> $next:ident => { $e:expr }),+ + -> $next:ident => { move $e:expr }),+ ] $(, $ports:path => [ $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this* - -> $nexts:ident => { $es:expr }),+ + -> $nexts:ident => { move $es:expr }),+ ] )* } => { if $index == $count { match move pipes::try_recv($port) { - $(Some($message($($(ref $x,)+)* ref next)) => { - // FIXME (#2329) we really want move out of enum here. - let $next = unsafe { let x <- *ptr::addr_of(&(*next)); x }; - $e + $(Some($message($($(move $x,)+)* move next)) => { + let $next = move next; + move $e })+ _ => fail } @@ -39,7 +38,7 @@ macro_rules! select_if ( $count + 1 $(, $ports => [ $(type_this $messages$(($(x $xs),+))dont_type_this* - -> $nexts => { $es }),+ + -> $nexts => { move $es }),+ ])* ) } @@ -53,9 +52,9 @@ macro_rules! select ( -> $next:ident $e:expr),+ } )+ } => { - let index = pipes::selecti([$(($port).header()),+]/_); + let index = pipes::selecti([$(($port).header()),+]); select_if!(index, 0 $(, $port => [ - $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+ + $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { move $e }),+ ])+) } ) diff --git a/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs new file mode 100644 index 00000000000..ac00f6a645b --- /dev/null +++ b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs @@ -0,0 +1,25 @@ +trait Deserializer { + fn read_int() -> int; +} + +trait Deserializable<D: Deserializer> { + static fn deserialize(d: &D) -> self; +} + +impl<D: Deserializer> int: Deserializable<D> { + static fn deserialize(d: &D) -> int { + return d.read_int(); + } +} + +struct FromThinAir { dummy: () } + +impl FromThinAir: Deserializer { + fn read_int() -> int { 22 } +} + +fn main() { + let d = FromThinAir { dummy: () }; + let i: int = deserialize(&d); + assert i == 22; +} \ No newline at end of file diff --git a/src/test/run-pass/static-method-test.rs b/src/test/run-pass/static-method-test.rs index 57d6558dd77..6ce4ff34815 100644 --- a/src/test/run-pass/static-method-test.rs +++ b/src/test/run-pass/static-method-test.rs @@ -13,13 +13,13 @@ fn andand<T: bool_like Copy>(x1: T, x2: T) -> T { impl bool: bool_like { static fn select<A>(&&b: bool, +x1: A, +x2: A) -> A { - if b { x1 } else { x2 } + if b { move x1 } else { move x2 } } } impl int: bool_like { static fn select<A>(&&b: int, +x1: A, +x2: A) -> A { - if b != 0 { x1 } else { x2 } + if b != 0 { move x1 } else { move x2 } } } diff --git a/src/test/run-pass/struct-literal-dtor.rs b/src/test/run-pass/struct-literal-dtor.rs index e182fa67cf0..2b56cee9f6b 100644 --- a/src/test/run-pass/struct-literal-dtor.rs +++ b/src/test/run-pass/struct-literal-dtor.rs @@ -1,6 +1,6 @@ struct foo { x: ~str, - drop { #error["%s", self.x]; } + drop { error!("%s", self.x); } } fn main() { diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index d8586e7ef39..1244af227f4 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -19,7 +19,7 @@ fn test05_start(ch : Chan<int>) { fn test05() { let (ch, po) = pipes::stream(); - task::spawn(|| test05_start(ch) ); + task::spawn(|move ch| test05_start(ch) ); let mut value = po.recv(); log(error, value); value = po.recv(); diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index 0c69f414cc8..55fff5422e3 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -5,7 +5,7 @@ extern mod std; fn start(c: pipes::Chan<pipes::Chan<~str>>) { let (ch, p) = pipes::stream(); - c.send(ch); + c.send(move ch); let mut a; let mut b; @@ -14,12 +14,12 @@ fn start(c: pipes::Chan<pipes::Chan<~str>>) { log(error, a); b = p.recv(); assert b == ~"B"; - log(error, b); + log(error, move b); } fn main() { let (ch, p) = pipes::stream(); - let child = task::spawn(|| start(ch) ); + let child = task::spawn(|move ch| start(ch) ); let c = p.recv(); c.send(~"A"); diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index c660ecd3a92..86fb20ad818 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -5,11 +5,11 @@ extern mod std; fn start(c: pipes::Chan<pipes::Chan<int>>) { let (ch, p) = pipes::stream(); - c.send(ch); + c.send(move ch); } fn main() { let (ch, p) = pipes::stream(); - let child = task::spawn(|| start(ch) ); + let child = task::spawn(|move ch| start(ch) ); let c = p.recv(); } diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index c0f97c85bce..64ea3fb9d0e 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -7,7 +7,7 @@ fn start(&&task_number: int) { debug!("Started / Finished task."); } fn test00() { let i: int = 0; let mut result = None; - do task::task().future_result(|+r| { result = Some(r); }).spawn { + do task::task().future_result(|+r| { result = Some(move r); }).spawn { start(i) } @@ -19,7 +19,7 @@ fn test00() { } // Try joining tasks that have already finished. - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); debug!("Joined task."); } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index 7302bcdaa94..9827b3c36b9 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -12,6 +12,6 @@ fn start(c: pipes::Chan<int>, start: int, number_of_messages: int) { fn main() { debug!("Check that we don't deadlock."); let (ch, p) = pipes::stream(); - task::try(|| start(ch, 0, 10) ); + task::try(|move ch| start(ch, 0, 10) ); debug!("Joined task"); } diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 14f8e3bfa2b..7f63d22be47 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -9,8 +9,8 @@ fn main() { while (i > 0) { log(debug, i); let (ch, p) = pipes::stream(); - po.add(p); - task::spawn(|copy i| child(i, ch) ); + po.add(move p); + task::spawn(|move ch, copy i| child(i, ch) ); i = i - 1; } diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 98b095426ea..c3734cb5d9c 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -18,6 +18,6 @@ fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (ch, p) = pipes::stream(); - task::spawn(|| start(ch, 10)); + task::spawn(|move ch| start(ch, 10)); p.recv(); } diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index a69b7b0c15b..47bc99b53f4 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -91,7 +91,7 @@ fn test_tag() { fn test_chan() { let (ch, po) = pipes::stream(); let (ch0, po0) = pipes::stream(); - ch.send(ch0); + ch.send(move ch0); let ch1 = po.recv(); // Does the transmitted channel still work? diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 4faac4fdac1..7082cd55ac8 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -34,8 +34,8 @@ fn test00() { while i < number_of_tasks { let ch = po.chan(); do task::task().future_result(|+r| { - results.push(r); - }).spawn |copy i| { + results.push(move r); + }).spawn |move ch, copy i| { test00_start(ch, i, number_of_messages) } i = i + 1; diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index d4cba9f71ab..c34dfb319d8 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -17,19 +17,19 @@ fn test00() { let number_of_messages: int = 10; let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 0, number_of_messages); } let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 1, number_of_messages); } let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 2, number_of_messages); } let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 3, number_of_messages); } diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index c159b7b77e5..5ed5899658d 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -18,7 +18,8 @@ fn test00() { let ch = p.chan(); let mut result = None; - do task::task().future_result(|+r| { result = Some(r); }).spawn { + do task::task().future_result(|+r| { result = Some(move r); }).spawn + |move ch| { test00_start(ch, number_of_messages); } @@ -29,7 +30,7 @@ fn test00() { i += 1; } - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); assert (sum == number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-comm.rs b/src/test/run-pass/task-comm.rs index c88b556fd53..aba0bd66005 100644 --- a/src/test/run-pass/task-comm.rs +++ b/src/test/run-pass/task-comm.rs @@ -40,7 +40,7 @@ fn test00() { while i < number_of_tasks { i = i + 1; do task::task().future_result(|+r| { - results.push(r); + results.push(move r); }).spawn |copy i| { test00_start(ch, i, number_of_messages); } @@ -127,7 +127,7 @@ fn test06() { while i < number_of_tasks { i = i + 1; do task::task().future_result(|+r| { - results.push(r); + results.push(move r); }).spawn |copy i| { test06_start(i); }; diff --git a/src/test/run-pass/task-compare.rs b/src/test/run-pass/task-compare.rs index 652d131584f..4b5852a1d97 100644 --- a/src/test/run-pass/task-compare.rs +++ b/src/test/run-pass/task-compare.rs @@ -1,23 +1,60 @@ +// xfail-test /** A test case for issue #577, which also exposes #588 */ -// FIXME: This won't work until we can compare resources (#2601) -// xfail-test - extern mod std; -use task::join; fn child() { } +struct notify { + ch: comm::Chan<bool>, v: @mut bool, + drop { + error!("notify: task=%? v=%x unwinding=%b b=%b", + task::get_task(), + ptr::addr_of(&(*(self.v))) as uint, + task::failing(), + *(self.v)); + let b = *(self.v); + comm::send(self.ch, b); + } +} + +fn notify(ch: comm::Chan<bool>, v: @mut bool) -> notify { + notify { + ch: ch, + v: v + } +} + +fn joinable(+f: fn~()) -> comm::Port<bool> { + fn wrapper(+c: comm::Chan<bool>, +f: fn()) { + let b = @mut false; + error!("wrapper: task=%? allocated v=%x", + task::get_task(), + ptr::addr_of(&(*b)) as uint); + let _r = notify(c, b); + f(); + *b = true; + } + let p = comm::Port(); + let c = comm::Chan(&p); + do task::spawn_unlinked { wrapper(c, copy f) }; + p +} + +fn join(port: comm::Port<bool>) -> bool { + comm::recv(port) +} + fn main() { // tasks let t1; let t2; let c1 = child, c2 = child; - t1 = task::spawn_joinable(c1); - t2 = task::spawn_joinable(c2); + t1 = joinable(c1); + t2 = joinable(c2); assert (t1 == t1); assert (t1 != t2); @@ -26,15 +63,15 @@ fn main() { let p1; let p2; - p1 = comm::port::<int>(); - p2 = comm::port::<int>(); + p1 = comm::Port::<int>(); + p2 = comm::Port::<int>(); assert (p1 == p1); assert (p1 != p2); // channels - let c1 = comm::chan(p1); - let c2 = comm::chan(p2); + let c1 = comm::Chan(p1); + let c2 = comm::Chan(p2); assert (c1 == c1); assert (c1 != c2); diff --git a/src/test/run-pass/test-ignore-cfg.rs b/src/test/run-pass/test-ignore-cfg.rs index 0482fc278c8..0baabecb0ab 100644 --- a/src/test/run-pass/test-ignore-cfg.rs +++ b/src/test/run-pass/test-ignore-cfg.rs @@ -20,10 +20,10 @@ fn checktests() { let tests = __test::tests(); let shouldignore = option::get( - &vec::find(tests, |t| t.name == ~"shouldignore" )); + vec::find(tests, |t| t.name == ~"shouldignore" )); assert shouldignore.ignore == true; let shouldnotignore = option::get( - &vec::find(tests, |t| t.name == ~"shouldnotignore" )); + vec::find(tests, |t| t.name == ~"shouldnotignore" )); assert shouldnotignore.ignore == false; } \ No newline at end of file diff --git a/src/test/run-pass/trait-to-str.rs b/src/test/run-pass/trait-to-str.rs index 14ca4df66a0..2dfe48c4951 100644 --- a/src/test/run-pass/trait-to-str.rs +++ b/src/test/run-pass/trait-to-str.rs @@ -30,7 +30,7 @@ fn main() { assert indirect(~[10, 20]) == ~"[10, 20]!"; fn indirect2<T: to_str>(x: T) -> ~str { - indirect(x) + indirect(move x) } assert indirect2(~[1]) == ~"[1]!"; } diff --git a/src/test/run-pass/unique-fn-arg-move.rs b/src/test/run-pass/unique-fn-arg-move.rs index 2126e329247..3e162e13d78 100644 --- a/src/test/run-pass/unique-fn-arg-move.rs +++ b/src/test/run-pass/unique-fn-arg-move.rs @@ -4,5 +4,5 @@ fn f(-i: ~int) { fn main() { let i = ~100; - f(i); + f(move i); } \ No newline at end of file diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 10c9fcae8e7..850adcf6746 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -1,7 +1,7 @@ #[no_core]; extern mod core; extern mod zed(name = "core"); -extern mod bar(name = "core", vers = "0.4"); +extern mod bar(name = "core", vers = "0.5"); use core::str; diff --git a/src/test/run-pass/yield.rs b/src/test/run-pass/yield.rs index f9c2ad2547d..11208a969db 100644 --- a/src/test/run-pass/yield.rs +++ b/src/test/run-pass/yield.rs @@ -4,13 +4,13 @@ use task::*; fn main() { let mut result = None; - task::task().future_result(|+r| { result = Some(r); }).spawn(child); + task::task().future_result(|+r| { result = Some(move r); }).spawn(child); error!("1"); yield(); error!("2"); yield(); error!("3"); - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); } fn child() { diff --git a/src/test/run-pass/yield1.rs b/src/test/run-pass/yield1.rs index 05c5e833bab..ec77a686324 100644 --- a/src/test/run-pass/yield1.rs +++ b/src/test/run-pass/yield1.rs @@ -4,10 +4,10 @@ use task::*; fn main() { let mut result = None; - task::task().future_result(|+r| { result = Some(r); }).spawn(child); + task::task().future_result(|+r| { result = Some(move r); }).spawn(child); error!("1"); yield(); - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); } fn child() { error!("2"); } |
