]> git.lizzy.rs Git - rust.git/commitdiff
Merge pull request #605 from wilsonk/target
authorGraydon Hoare <graydon@pobox.com>
Mon, 4 Jul 2011 20:45:59 +0000 (13:45 -0700)
committerGraydon Hoare <graydon@pobox.com>
Mon, 4 Jul 2011 20:45:59 +0000 (13:45 -0700)
Update RustWrapper.cpp so that LLVM revision 134231 from June 30, 2011 at

48 files changed:
AUTHORS.txt
Makefile.in
mk/fuzzer.mk
mk/stage1.mk
src/comp/back/link.rs
src/comp/driver/rustc.rs
src/comp/driver/session.rs
src/comp/front/ast.rs
src/comp/front/attr.rs
src/comp/front/eval.rs
src/comp/front/fold.rs
src/comp/front/parser.rs
src/comp/front/token.rs
src/comp/lib/llvm.rs
src/comp/metadata/creader.rs
src/comp/metadata/decoder.rs
src/comp/metadata/encoder.rs
src/comp/metadata/tydecode.rs
src/comp/metadata/tyencode.rs
src/comp/middle/alias.rs
src/comp/middle/resolve.rs
src/comp/middle/trans.rs
src/comp/middle/tstate/pre_post_conditions.rs
src/comp/middle/tstate/states.rs
src/comp/middle/ty.rs
src/comp/middle/typeck.rs
src/comp/middle/visit.rs
src/comp/middle/walk.rs
src/comp/pretty/ppaux.rs
src/comp/pretty/pprust.rs
src/fuzzer/fuzzer.rc
src/fuzzer/fuzzer.rs
src/rt/rust_chan.cpp
src/rt/rust_chan.h
src/rt/rust_internal.h
src/rt/rust_upcall.cpp
src/test/compile-fail/auto-deref-bind.rs [new file with mode: 0644]
src/test/compile-fail/ext-noname.rs [new file with mode: 0644]
src/test/compile-fail/fail-expr.rs [new file with mode: 0644]
src/test/compile-fail/fail-simple.rs
src/test/compile-fail/use-meta-mismatch.rs [new file with mode: 0644]
src/test/run-fail/args-fail.rs [new file with mode: 0644]
src/test/run-fail/explicit-fail-msg.rs
src/test/run-fail/fail-arg.rs [new file with mode: 0644]
src/test/run-fail/fmt-fail.rs [new file with mode: 0644]
src/test/run-pass/auto-deref-fn.rs [new file with mode: 0644]
src/test/run-pass/newtype-polymorphic.rs [new file with mode: 0644]
src/test/run-pass/newtype.rs [new file with mode: 0644]

index 9ff5cfd37ab31cd8d9545a9d3e3c867ce86df4f4..98971e8d90585e55242ff76479dc374db6165158 100644 (file)
@@ -30,5 +30,6 @@ Paul Stansifer <paul.stansifer@gmail.com>
 Peter Hull <peterhull90@gmail.com>
 Ralph Giles <giles@thaumas.net>
 Rafael Ávila de Espíndola <respindola@mozilla.com>
+Rob Arnold <robarnold@cs.cmu.edu>
 Roy Frostig <rfrostig@mozilla.com>
 Tim Chevalier <chevalier@alum.wellesley.edu>
index ecaf7718548daca8eae8d6a97a1e62331a17e254..2a21feaa12e0fa8b4a01034c772108bece600bfa 100644 (file)
@@ -47,6 +47,7 @@ endif
 CFG_RUNTIME :=$(call CFG_LIB_NAME,rustrt)
 CFG_RUSTLLVM :=$(call CFG_LIB_NAME,rustllvm)
 CFG_STDLIB :=$(call CFG_LIB_NAME,std)
+CFG_LIBRUSTC :=$(call CFG_LIB_NAME,rustc)
 
 # version-string calculation
 CFG_GIT_DIR := $(CFG_SRC_DIR).git
index 566d9b0d657a953c95c1f85d88d268f6579118f8..bdab57248d0dc966ab0c856dbaa74f7f2d767ee9 100644 (file)
@@ -1,19 +1,8 @@
-# At the moment the fuzzer only exists in stage2.  That's the first
-# stage built by the non-snapshot compiler so it seems a convenient
-# stage to work at.
+# At the moment the fuzzer only exists in stage1.
 
 FUZZER_CRATE := $(S)src/fuzzer/fuzzer.rc
 FUZZER_INPUTS := $(wildcard $(addprefix $(S)src/fuzzer/, *.rs))
 
-stage2/fuzzer.o: $(FUZZER_CRATE) $(FUZZER_INPUTS) $(SREQ1)
-       @$(call E, compile: $@)
-       $(STAGE1) -c -o $@ $<
-
-stage2/fuzzer$(X): stage2/fuzzer.o $(SREQ1)
-       @$(call E, link [gcc]: $@)
-       $(Q)gcc $(CFG_GCCISH_CFLAGS) rt/main.o stage2/glue.o -o $@ $< \
-      -Lstage2 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm -lrustc
-       @# dsymutil sometimes fails or prints a warning, but the
-       @# program still runs.  Since it simplifies debugging other
-       @# programs, I\'ll live with the noise.
-       -$(Q)$(CFG_DSYMUTIL) $@
+stage1/fuzzer$(X): $(FUZZER_CRATE) $(FUZZER_INPUTS) $(SREQ1)
+       @$(call E, compile_and_link: $@)
+       $(STAGE1) -o $@ $<
index a7a5e4b1c0d237b051448cdc2c85eb30132c1480..883c5e07f54178f56c2fd5ff90e43ec53894ef55 100644 (file)
@@ -29,3 +29,8 @@ stage1/%.o: stage1/%.s
 stage1/%$(X): $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ0) stage0/intrinsics.bc
        @$(call E, compile_and_link: $@)
        $(STAGE0) -o $@ $<
+
+stage1/lib/$(CFG_LIBRUSTC): $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ1) \
+                            stage1/intrinsics.bc
+       @$(call E, compile_and_link: $@)
+       $(STAGE1) --shared -o $@ $<
index 0c016afd97504612dde70ca86204e05a289f1d7a..562b029dfe8eb01a817104ff26946b85a06cb71b 100644 (file)
@@ -332,6 +332,7 @@ fn len_and_str(&str s) -> str {
                     sha.input_str(len_and_str(name));
                 }
                 case (ast::meta_list(_, _)) {
+                    // FIXME (#607): Implement this
                     fail "unimplemented meta_item variant";
                 }
             }
index 55dcc35a637a9f7a31a2c5be4fb6d111f3c61712..fc3cb7ce542c241c2c0466683df31d8466769d91 100644 (file)
@@ -6,6 +6,7 @@
 import front::token;
 import front::eval;
 import front::ast;
+import front::attr;
 import middle::trans;
 import middle::resolve;
 import middle::ty;
@@ -35,8 +36,8 @@
 
 tag pp_mode { ppm_normal; ppm_typed; ppm_identified; }
 
-fn default_environment(session::session sess, str argv0, str input) ->
-   eval::env {
+fn default_configuration(session::session sess, str argv0, str input) ->
+    ast::crate_cfg {
     auto libc =
         alt (sess.get_targ_cfg().os) {
             case (session::os_win32) { "msvcrt.dll" }
@@ -44,13 +45,33 @@ fn default_environment(session::session sess, str argv0, str input) ->
             case (session::os_linux) { "libc.so.6" }
             case (_) { "libc.so" }
         };
+
+    auto mk = attr::mk_name_value_item;
+
     ret [ // Target bindings.
-         tup("target_os", eval::val_str(std::os::target_os())),
-         tup("target_arch", eval::val_str("x86")),
-         tup("target_libc", eval::val_str(libc)),
+         mk("target_os", std::os::target_os()),
+         mk("target_arch", "x86"),
+         mk("target_libc", libc),
          // Build bindings.
-         tup("build_compiler", eval::val_str(argv0)),
-         tup("build_input", eval::val_str(input))];
+         mk("build_compiler", argv0),
+         mk("build_input", input)];
+}
+
+fn build_configuration(session::session sess, str argv0,
+                       str input) -> ast::crate_cfg {
+    // Combine the configuration requested by the session (command line) with
+    // some default configuration items
+    ret sess.get_opts().cfg + default_configuration(sess, argv0, input);
+}
+
+// Convert strings provided as --cfg [cfgspec] into a crate_cfg
+fn parse_cfgspecs(&vec[str] cfgspecs) -> ast::crate_cfg {
+    // FIXME: It would be nice to use the parser to parse all varieties of
+    // meta_item here. At the moment we just support the meta_word variant.
+    fn to_meta_word(&str cfgspec) -> @ast::meta_item {
+        attr::mk_word_item(cfgspec)
+    }
+    ret vec::map(to_meta_word, cfgspecs);
 }
 
 fn parse_input(session::session sess, parser::parser p, str input) ->
@@ -73,10 +94,10 @@ fn time[T](bool do_it, str what, fn() -> T  thunk) -> T {
     ret rv;
 }
 
-fn compile_input(session::session sess, eval::env env, str input,
+fn compile_input(session::session sess, ast::crate_cfg cfg, str input,
                  str output) {
     auto time_passes = sess.get_opts().time_passes;
-    auto p = parser::new_parser(sess, env, input, 0u, 0);
+    auto p = parser::new_parser(sess, cfg, input, 0u, 0);
     auto crate =
         time(time_passes, "parsing", bind parse_input(sess, p, input));
     if (sess.get_opts().output_type == link::output_type_none) { ret; }
@@ -104,9 +125,9 @@ fn compile_input(session::session sess, eval::env env, str input,
              bind link::write::run_passes(sess, llmod, output));
 }
 
-fn pretty_print_input(session::session sess, eval::env env, str input,
-                      pp_mode ppm) {
-    auto p = front::parser::new_parser(sess, env, input, 0u, 0);
+fn pretty_print_input(session::session sess, ast::crate_cfg cfg,
+                      str input, pp_mode ppm) {
+    auto p = front::parser::new_parser(sess, cfg, input, 0u, 0);
     auto crate = parse_input(sess, p, input);
     auto mode;
     alt (ppm) {
@@ -156,6 +177,7 @@ fn usage(str argv0) {
     --emit-llvm        produce an LLVM bitcode file
     --save-temps       write intermediate files in addition to normal output
     --stats            gather and report various compilation statistics
+    --cfg [cfgspec]    configure the compilation environment
     --time-passes      time the individual phases of the compiler
     --time-llvm-passes time the individual phases of the LLVM backend
     --sysroot <path>   override the system root (default: rustc's directory)
@@ -253,6 +275,7 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
             case (none) { get_default_sysroot(binary) }
             case (some(?s)) { s }
         };
+    auto cfg = parse_cfgspecs(getopts::opt_strs(match, "cfg"));
     let @session::options sopts =
         @rec(shared=shared,
              optimize=opt_level,
@@ -265,7 +288,8 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
              time_llvm_passes=time_llvm_passes,
              output_type=output_type,
              library_search_paths=library_search_paths,
-             sysroot=sysroot);
+             sysroot=sysroot,
+             cfg=cfg);
     ret sopts;
 }
 
@@ -275,7 +299,7 @@ fn build_session(@session::options sopts) -> session::session {
     auto target_crate_num = 0;
     auto sess =
         session::session(target_crate_num, target_cfg, sopts, crate_cache, [],
-                         [], front::codemap::new_codemap(), 0u);
+                         [], [], front::codemap::new_codemap(), 0u);
     ret sess;
 }
 
@@ -298,7 +322,7 @@ fn main(vec[str] args) {
          optflag("c"), optopt("o"), optflag("g"), optflag("save-temps"),
          optopt("sysroot"), optflag("stats"), optflag("time-passes"),
          optflag("time-llvm-passes"), optflag("no-typestate"),
-         optflag("noverify")];
+         optflag("noverify"), optmulti("cfg")];
     auto binary = vec::shift[str](args);
     auto binary_dir = fs::dirname(binary);
     auto match =
@@ -337,7 +361,7 @@ fn main(vec[str] args) {
     }
     auto ifile = match.free.(0);
     let str saved_out_filename = "";
-    auto env = default_environment(sess, binary, ifile);
+    auto cfg = build_configuration(sess, binary, ifile);
     auto pretty =
         option::map[str,
                     pp_mode](bind parse_pretty(sess, _),
@@ -345,7 +369,7 @@ fn main(vec[str] args) {
     auto ls = opt_present(match, "ls");
     alt (pretty) {
         case (some[pp_mode](?ppm)) {
-            pretty_print_input(sess, env, ifile, ppm);
+            pretty_print_input(sess, cfg, ifile, ppm);
             ret;
         }
         case (none[pp_mode]) {/* continue */ }
@@ -371,7 +395,7 @@ fn main(vec[str] args) {
                 case (link::output_type_exe) { parts += ["o"]; }
             }
             auto ofile = str::connect(parts, ".");
-            compile_input(sess, env, ifile, ofile);
+            compile_input(sess, cfg, ifile, ofile);
         }
         case (some(?ofile)) {
             // FIXME: what about windows? This will create a foo.exe.o.
@@ -386,7 +410,7 @@ fn main(vec[str] args) {
                 }
                 case (_) { temp_filename = ofile; }
             }
-            compile_input(sess, env, ifile, temp_filename);
+            compile_input(sess, cfg, ifile, temp_filename);
         }
     }
 
@@ -406,16 +430,11 @@ fn main(vec[str] args) {
              saved_out_filename, saved_out_filename + ".o"];
         auto shared_cmd;
 
-        alt (sess.get_targ_cfg().os) {
-            case (session::os_win32) {
-                shared_cmd = "-shared";
-            }
-            case (session::os_macos) {
+        auto os = sess.get_targ_cfg().os;
+        if (os == session::os_macos) {
                 shared_cmd = "-dynamiclib";
-            }
-            case (session::os_linux) {
+        } else {
                 shared_cmd = "-shared";
-            }
         }
 
         // Converts a library file name into a gcc -l argument
@@ -441,7 +460,7 @@ fn rmext(str filename) -> str {
                 case (_) { rmext(filename) }
             };
         }
-        
+
         for (str cratepath in sess.get_used_crate_files()) {
             auto dir = fs::dirname(cratepath);
             if (dir != "") {
@@ -451,6 +470,7 @@ fn rmext(str filename) -> str {
             gcc_args += ["-l" + libarg];
         }
 
+        gcc_args += sess.get_used_link_args();
         auto used_libs = sess.get_used_libraries();
         for (str l in used_libs) {
             gcc_args += ["-l" + l];
@@ -459,9 +479,8 @@ fn rmext(str filename) -> str {
         if (sopts.shared) {
             gcc_args += [shared_cmd];
         } else {
-            // FIXME: having -Lrustllvm hardcoded in here is hack
-            // FIXME: same for -lm
-            gcc_args += ["-Lrustllvm", "-lm", main];
+            // FIXME: why do we hardcode -lm?
+            gcc_args += ["-lm", main];
         }
         // We run 'gcc' here
 
index e1067b2cb861a343ca98d7d10c8ded12c1306507..8d296f355ae57b3e40e31d0515375ae9c2dba86e 100644 (file)
@@ -10,6 +10,7 @@
 import std::option;
 import std::option::some;
 import std::option::none;
+import std::str;
 
 tag os { os_win32; os_macos; os_linux; }
 
         bool time_llvm_passes,
         back::link::output_type output_type,
         vec[str] library_search_paths,
-        str sysroot);
+        str sysroot,
+        // The crate config requested for the session, which may be combined
+        // with additional crate configurations during the compile process
+        ast::crate_cfg cfg);
 
 type crate_metadata = rec(str name, vec[u8] data);
 
@@ -68,6 +72,7 @@ fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
             map::hashmap[int, crate_metadata] crates,
             mutable vec[str] used_crate_files,
             mutable vec[str] used_libraries,
+            mutable vec[str] used_link_args,
             codemap::codemap cm,
             mutable uint err_count) {
     fn get_targ_cfg() -> @config { ret targ_cfg; }
@@ -127,18 +132,25 @@ fn set_external_crate(int num, &crate_metadata metadata) {
         crates.insert(num, metadata);
     }
     fn has_external_crate(int num) -> bool { ret crates.contains_key(num); }
-    fn add_used_library(&str lib) {
+    fn add_used_link_args(&str args) {
+        used_link_args += str::split(args, ' ' as u8);
+    }
+    fn get_used_link_args() -> vec[str] {
+        ret used_link_args;
+    }
+    fn add_used_library(&str lib) -> bool {
         if (lib == "") {
-            ret;
+            ret false;
         }
         // A program has a small number of libraries, so a vector is probably
         // a good data structure in here.
         for (str l in used_libraries) {
             if (l == lib) {
-                ret;
+                ret false;
             }
         }
         used_libraries += [lib];
+        ret true;
     }
     fn get_used_libraries() -> vec[str] {
        ret used_libraries;
index c120535d1d01492b3fc3977a797d4a881d6fc540..600a76c0738bf37619a36caf50088fcc5a3601c9 100644 (file)
@@ -88,12 +88,6 @@ fn def_id_of_def(def d) -> def_id {
                   crate_cfg config);
 
 tag crate_directive_ {
-    cdir_expr(@expr);
-
-    // FIXME: cdir_let should be eliminated
-    // and redirected to the use of const stmt_decls inside
-    // crate directive blocks.
-    cdir_let(ident, @expr, vec[@crate_directive]);
     cdir_src_mod(ident, option::t[filename], vec[attribute]);
     cdir_dir_mod(ident, option::t[filename],
                  vec[@crate_directive], vec[attribute]);
@@ -116,13 +110,15 @@ fn def_id_of_def(def d) -> def_id {
 
 type block_ = rec(vec[@stmt] stmts, option::t[@expr] expr, node_id id);
 
-type pat = spanned[pat_];
+type pat = rec(node_id id,
+               pat_ node,
+               span span);
 
 tag pat_ {
-    pat_wild(node_id);
-    pat_bind(ident, node_id);
-    pat_lit(@lit, node_id);
-    pat_tag(path, vec[@pat], node_id);
+    pat_wild;
+    pat_bind(ident);
+    pat_lit(@lit);
+    pat_tag(path, vec[@pat]);
 }
 
 tag mutability { mut; imm; maybe_mut; }
@@ -281,7 +277,7 @@ fn unop_to_str(unop op) -> str {
     expr_index(@expr, @expr);
     expr_path(path);
     expr_ext(path, vec[@expr], option::t[str], @expr);
-    expr_fail(option::t[str]);
+    expr_fail(option::t[@expr]);
     expr_break;
     expr_cont;
     expr_ret(option::t[@expr]);
@@ -604,6 +600,19 @@ fn ternary_to_if(&@expr e) -> @ast::expr {
     }
 }
 
+// Path stringification
+fn path_to_str(&ast::path pth) -> str {
+    auto result = str::connect(pth.node.idents, "::");
+    if (vec::len[@ast::ty](pth.node.types) > 0u) {
+        fn f(&@ast::ty t) -> str { ret pretty::pprust::ty_to_str(*t); }
+        result += "[";
+        result += str::connect(vec::map(f, pth.node.types), ",");
+        result += "]";
+    }
+    ret result;
+}
+
+
 //
 // Local Variables:
 // mode: rust
index 4fe0b814165bb35a5a09c2c88280f52d7fcd4e41..1312851c5f01931b0ebc541123411105f22562dd 100644 (file)
@@ -3,6 +3,7 @@
 import std::vec;
 import std::option;
 import front::ast;
+import util::common;
 
 export attr_metas;
 export find_linkage_metas;
 export sort_meta_items;
 export remove_meta_items_by_name;
 export get_attr_name;
+export mk_name_value_item;
+export mk_list_item;
+export mk_word_item;
+export mk_attr;
 
 // From a list of crate attributes get only the meta_items that impact crate
 // linkage
@@ -23,8 +28,7 @@ fn find_linkage_metas(vec[ast::attribute] attrs) -> vec[@ast::meta_item] {
                 metas += items;
             }
             case (_) {
-                // FIXME: Maybe need a warning that this attr isn't
-                // being used for linkage
+                log "ignoring link attribute that has incorrect type";
             }
         }
     }
@@ -92,7 +96,9 @@ fn eq(@ast::meta_item a, @ast::meta_item b) -> bool {
             }
         }
         case (ast::meta_list(?na, ?la)) {
-            // FIXME (#487): This involves probably sorting the list by name
+            // FIXME (#607): Needs implementing
+            // This involves probably sorting the list by name and
+            // meta_item variant
             fail "unimplemented meta_item variant"
         }
     }
@@ -111,6 +117,7 @@ fn contains(&vec[@ast::meta_item] haystack, @ast::meta_item needle) -> bool {
     ret false;
 }
 
+// FIXME: This needs to sort by meta_item variant in addition to the item name
 fn sort_meta_items(&vec[@ast::meta_item] items) -> vec[@ast::meta_item] {
     fn lteq(&@ast::meta_item ma, &@ast::meta_item mb) -> bool {
         fn key(&@ast::meta_item m) -> ast::ident {
@@ -159,6 +166,28 @@ fn remove_meta_items_by_name(&vec[@ast::meta_item] items,
     ret vec::filter_map(filter, items);
 }
 
+fn span[T](&T item) -> common::spanned[T] {
+    ret rec(node=item, span=rec(lo=0u, hi=0u));
+}
+
+fn mk_name_value_item(ast::ident name, str value) -> @ast::meta_item {
+    ret @span(ast::meta_name_value(name, value));
+}
+
+fn mk_list_item(ast::ident name,
+                &vec[@ast::meta_item] items) -> @ast::meta_item {
+    ret @span(ast::meta_list(name, items));
+}
+
+fn mk_word_item(ast::ident name) -> @ast::meta_item {
+    ret @span(ast::meta_word(name));
+}
+
+fn mk_attr(@ast::meta_item item) -> ast::attribute {
+    ret span(rec(style = ast::attr_inner,
+                 value = *item));
+}
+
 //
 // Local Variables:
 // mode: rust
index 2dc76bd793bbf2ea1d52ffd90c45ca300c8a42d9..95b9a85c09f29d496101288fd34757bb5b16be33 100644 (file)
 import std::option;
 import std::option::some;
 import std::option::none;
-import std::map::hashmap;
 import driver::session;
-import ast::ident;
 import front::parser::parser;
-import front::parser::spanned;
 import front::parser::new_parser;
 import front::parser::parse_inner_attrs_and_next;
 import front::parser::parse_mod_items;
-import util::common;
-import util::common::filename;
-import util::common::span;
-import util::common::new_str_hash;
 
-
-// Simple dynamic-typed value type for eval_expr.
-tag val { val_bool(bool); val_int(int); val_str(str); }
+export eval_crate_directives_to_mod;
+export mode_parse;
 
 tag eval_mode { mode_depend; mode_parse; }
 
-type env = vec[tup(ident, val)];
-
 type ctx =
     @rec(parser p,
          eval_mode mode,
          mutable vec[str] deps,
          session::session sess,
          mutable uint chpos,
-         mutable int next_id);
-
-fn mk_env() -> env { ret []; }
-
-fn val_is_bool(val v) -> bool {
-    alt (v) { case (val_bool(_)) { true } case (_) { false } }
-}
-
-fn val_is_int(val v) -> bool {
-    alt (v) { case (val_int(_)) { true } case (_) { false } }
-}
-
-fn val_is_str(val v) -> bool {
-    alt (v) { case (val_str(_)) { true } case (_) { false } }
-}
-
-fn val_as_bool(val v) -> bool {
-    alt (v) { case (val_bool(?b)) { b } case (_) { fail } }
-}
-
-fn val_as_int(val v) -> int {
-    alt (v) { case (val_int(?i)) { i } case (_) { fail } }
-}
-
-fn val_as_str(val v) -> str {
-    alt (v) { case (val_str(?s)) { s } case (_) { fail } }
-}
-
-fn lookup(session::session sess, env e, span sp, ident i) -> val {
-    for (tup(ident, val) pair in e) {
-        if (str::eq(i, pair._0)) { ret pair._1; }
-    }
-    sess.span_fatal(sp, "unknown variable: " + i)
-}
-
-fn eval_lit(ctx cx, span sp, @ast::lit lit) -> val {
-    alt (lit.node) {
-        case (ast::lit_bool(?b)) { val_bool(b) }
-        case (ast::lit_int(?i)) { val_int(i) }
-        case (ast::lit_str(?s, _)) { val_str(s) }
-        case (_) { cx.sess.span_fatal(sp, "evaluating unsupported literal") }
-    }
-}
-
-fn eval_expr(ctx cx, env e, @ast::expr x) -> val {
-    alt (x.node) {
-        case (ast::expr_path(?pth)) {
-            if (vec::len[ident](pth.node.idents) == 1u &&
-                    vec::len[@ast::ty](pth.node.types) == 0u) {
-                ret lookup(cx.sess, e, x.span, pth.node.idents.(0));
-            }
-            cx.sess.span_fatal(x.span, "evaluating structured path-name");
-        }
-        case (ast::expr_lit(?lit)) { ret eval_lit(cx, x.span, lit); }
-        case (ast::expr_unary(?op, ?a)) {
-            auto av = eval_expr(cx, e, a);
-            alt (op) {
-                case (ast::not) {
-                    if (val_is_bool(av)) { ret val_bool(!val_as_bool(av)); }
-                    cx.sess.span_fatal(x.span, "bad types in '!' expression");
-                }
-                case (_) {
-                    cx.sess.span_fatal(x.span, "evaluating unsupported unop");
-                }
-            }
-        }
-        case (ast::expr_binary(?op, ?a, ?b)) {
-            auto av = eval_expr(cx, e, a);
-            auto bv = eval_expr(cx, e, b);
-            alt (op) {
-                case (ast::add) {
-                    if (val_is_int(av) && val_is_int(bv)) {
-                        ret val_int(val_as_int(av) + val_as_int(bv));
-                    }
-                    if (val_is_str(av) && val_is_str(bv)) {
-                        ret val_str(val_as_str(av) + val_as_str(bv));
-                    }
-                    cx.sess.span_fatal(x.span, "bad types in '+' expression");
-                }
-                case (ast::sub) {
-                    if (val_is_int(av) && val_is_int(bv)) {
-                        ret val_int(val_as_int(av) - val_as_int(bv));
-                    }
-                    cx.sess.span_fatal(x.span, "bad types in '-' expression");
-                }
-                case (ast::mul) {
-                    if (val_is_int(av) && val_is_int(bv)) {
-                        ret val_int(val_as_int(av) * val_as_int(bv));
-                    }
-                    cx.sess.span_fatal(x.span, "bad types in '*' expression");
-                }
-                case (ast::div) {
-                    if (val_is_int(av) && val_is_int(bv)) {
-                        ret val_int(val_as_int(av) / val_as_int(bv));
-                    }
-                    cx.sess.span_fatal(x.span, "bad types in '/' expression");
-                }
-                case (ast::rem) {
-                    if (val_is_int(av) && val_is_int(bv)) {
-                        ret val_int(val_as_int(av) % val_as_int(bv));
-                    }
-                    cx.sess.span_fatal(x.span, "bad types in '%' expression");
-                }
-                case (ast::and) {
-                    if (val_is_bool(av) && val_is_bool(bv)) {
-                        ret val_bool(val_as_bool(av) && val_as_bool(bv));
-                    }
-                    cx.sess.span_fatal(x.span,
-                                       "bad types in '&&' expression");
-                }
-                case (ast::or) {
-                    if (val_is_bool(av) && val_is_bool(bv)) {
-                        ret val_bool(val_as_bool(av) || val_as_bool(bv));
-                    }
-                    cx.sess.span_fatal(x.span,
-                                       "bad types in '||' expression");
-                }
-                case (ast::eq) {
-                    ret val_bool(val_eq(cx.sess, x.span, av, bv));
-                }
-                case (ast::ne) {
-                    ret val_bool(!val_eq(cx.sess, x.span, av, bv));
-                }
-                case (_) {
-                    cx.sess.span_fatal(x.span,
-                                       "evaluating unsupported binop");
-                }
-            }
-        }
-        case (_) {
-            cx.sess.span_fatal(x.span, "evaluating unsupported expression");
-        }
-    }
-    fail;
-}
-
-fn val_eq(session::session sess, span sp, val av, val bv) -> bool {
-    if (val_is_bool(av) && val_is_bool(bv)) {
-        val_as_bool(av) == val_as_bool(bv)
-    } else if (val_is_int(av) && val_is_int(bv)) {
-        val_as_int(av) == val_as_int(bv)
-    } else if (val_is_str(av) && val_is_str(bv)) {
-        str::eq(val_as_str(av), val_as_str(bv))
-    } else { sess.span_fatal(sp, "bad types in comparison") }
-}
+         mutable int next_id,
+         ast::crate_cfg cfg);
 
-fn eval_crate_directives(ctx cx, env e, vec[@ast::crate_directive] cdirs,
+fn eval_crate_directives(ctx cx, vec[@ast::crate_directive] cdirs,
                          str prefix, &mutable vec[@ast::view_item] view_items,
                          &mutable vec[@ast::item] items) {
     for (@ast::crate_directive sub_cdir in cdirs) {
-        eval_crate_directive(cx, e, sub_cdir, prefix, view_items, items);
+        eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
     }
 }
 
-fn eval_crate_directives_to_mod(ctx cx, env e,
+fn eval_crate_directives_to_mod(ctx cx,
                                 vec[@ast::crate_directive] cdirs, str prefix)
    -> ast::_mod {
     let vec[@ast::view_item] view_items = [];
     let vec[@ast::item] items = [];
-    eval_crate_directives(cx, e, cdirs, prefix, view_items, items);
+    eval_crate_directives(cx, cdirs, prefix, view_items, items);
     ret rec(view_items=view_items, items=items);
 }
 
-fn eval_crate_directive_block(ctx cx, env e, &ast::block blk, str prefix,
+fn eval_crate_directive_block(ctx cx, &ast::block blk, str prefix,
                               &mutable vec[@ast::view_item] view_items,
                               &mutable vec[@ast::item] items) {
     for (@ast::stmt s in blk.node.stmts) {
         alt (s.node) {
             case (ast::stmt_crate_directive(?cdir)) {
-                eval_crate_directive(cx, e, cdir, prefix, view_items, items);
+                eval_crate_directive(cx, cdir, prefix, view_items, items);
             }
             case (_) {
                 cx.sess.span_fatal(s.span,
@@ -210,75 +57,10 @@ fn eval_crate_directive_block(ctx cx, env e, &ast::block blk, str prefix,
     }
 }
 
-fn eval_crate_directive_expr(ctx cx, env e, @ast::expr x, str prefix,
-                             &mutable vec[@ast::view_item] view_items,
-                             &mutable vec[@ast::item] items) {
-    alt (x.node) {
-        case (ast::expr_if(?cond, ?thn, ?elopt)) {
-            auto cv = eval_expr(cx, e, cond);
-            if (!val_is_bool(cv)) {
-                cx.sess.span_fatal(x.span, "bad cond type in 'if'");
-            }
-            if (val_as_bool(cv)) {
-                ret eval_crate_directive_block(cx, e, thn, prefix, view_items,
-                                               items);
-            }
-            alt (elopt) {
-                case (some(?els)) {
-                    ret eval_crate_directive_expr(cx, e, els, prefix,
-                                                  view_items, items);
-                }
-                case (_) {
-                    // Absent-else is ok.
-
-                }
-            }
-        }
-        case (ast::expr_alt(?v, ?arms)) {
-            auto vv = eval_expr(cx, e, v);
-            for (ast::arm arm in arms) {
-                alt (arm.pat.node) {
-                    case (ast::pat_lit(?lit, _)) {
-                        auto pv = eval_lit(cx, arm.pat.span, lit);
-                        if (val_eq(cx.sess, arm.pat.span, vv, pv)) {
-                            ret eval_crate_directive_block(cx, e, arm.block,
-                                                           prefix, view_items,
-                                                           items);
-                        }
-                    }
-                    case (ast::pat_wild(_)) {
-                        ret eval_crate_directive_block(cx, e, arm.block,
-                                                       prefix, view_items,
-                                                       items);
-                    }
-                    case (_) {
-                        cx.sess.span_fatal(arm.pat.span,
-                                         "bad pattern type in 'alt'");
-                    }
-                }
-            }
-            cx.sess.span_fatal(x.span, "no cases matched in 'alt'");
-        }
-        case (ast::expr_block(?block)) {
-            ret eval_crate_directive_block(cx, e, block, prefix, view_items,
-                                           items);
-        }
-        case (_) { cx.sess.span_fatal(x.span, "unsupported expr type"); }
-    }
-}
-
-fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
+fn eval_crate_directive(ctx cx, @ast::crate_directive cdir, str prefix,
                         &mutable vec[@ast::view_item] view_items,
                         &mutable vec[@ast::item] items) {
     alt (cdir.node) {
-        case (ast::cdir_let(?id, ?x, ?cdirs)) {
-            auto v = eval_expr(cx, e, x);
-            auto e0 = [tup(id, v)] + e;
-            eval_crate_directives(cx, e0, cdirs, prefix, view_items, items);
-        }
-        case (ast::cdir_expr(?x)) {
-            eval_crate_directive_expr(cx, e, x, prefix, view_items, items);
-        }
         case (ast::cdir_src_mod(?id, ?file_opt, ?attrs)) {
             auto file_path = id + ".rs";
             alt (file_opt) {
@@ -292,7 +74,7 @@ fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
             };
             if (cx.mode == mode_depend) { cx.deps += [full_path]; ret; }
             auto p0 =
-                new_parser(cx.sess, e, full_path, cx.chpos,
+                new_parser(cx.sess, cx.cfg, full_path, cx.chpos,
                            cx.next_id);
             auto inner_attrs = parse_inner_attrs_and_next(p0);
             auto mod_attrs = attrs + inner_attrs._0;
@@ -315,7 +97,7 @@ fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
             } else {
                 prefix + std::fs::path_sep() + path
             };
-            auto m0 = eval_crate_directives_to_mod(cx, e, cdirs, full_path);
+            auto m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
             auto i = @rec(ident=id,
                           attrs=attrs,
                           id=cx.next_id,
index 340793b9f237cac6264cee26ebe6517c466871da..0fc884d67c3626404a5c3f34fb24881cdcf20a10 100644 (file)
@@ -139,11 +139,6 @@ fn noop_fold_crate(&crate_ c, ast_fold fld) -> crate_ {
 fn noop_fold_crate_directive(&crate_directive_ cd, ast_fold fld) 
     -> crate_directive_ {
     ret alt(cd) {
-        case(cdir_expr(?e)) { cdir_expr(fld.fold_expr(e)) }
-        case(cdir_let(?id, ?e, ?cds)) {
-            cdir_let(fld.fold_ident(id), fld.fold_expr(e),
-                     map(fld.fold_crate_directive, cds))
-                }
         case(cdir_src_mod(?id,?fname,?attrs)) { 
             cdir_src_mod(fld.fold_ident(id), fname, attrs)
                 }
@@ -257,12 +252,12 @@ fn noop_fold_arm(&arm a, ast_fold fld) -> arm {
 
 fn noop_fold_pat(&pat_ p, ast_fold fld) -> pat_ {
     ret alt (p) {
-        case (pat_wild(_)) { p }
-        case (pat_bind(?id, ?d)) { pat_bind(fld.fold_ident(id), d)}
-        case (pat_lit(_, _)) { p }
-        case (pat_tag(?pth, ?pats, ?nid)) {
-            pat_tag(fld.fold_path(pth), map(fld.fold_pat, pats), nid)
-                }
+        case (pat_wild) { p }
+        case (pat_bind(?ident)) { pat_bind(fld.fold_ident(ident))}
+        case (pat_lit(_)) { p }
+        case (pat_tag(?pth, ?pats)) {
+            pat_tag(fld.fold_path(pth), map(fld.fold_pat, pats))
+        }
     };
 }
 
@@ -621,7 +616,7 @@ fn f_arm(&ast_fold_precursor afp, ast_fold f, &arm x) -> arm {
         ret afp.fold_arm(x, f);
     }
     fn f_pat(&ast_fold_precursor afp, ast_fold f, &@pat x) -> @pat {
-        ret @rec(node=afp.fold_pat(x.node, f), span=x.span);
+        ret @rec(id=x.id, node=afp.fold_pat(x.node, f), span=x.span);
     }
     fn f_decl(&ast_fold_precursor afp, ast_fold f, &@decl x) -> @decl {
         ret @rec(node=afp.fold_decl(x.node, f), span=x.span);
index a3d20d23b6b3272f9cf0b626ffc5041df41c9207..ce68be6b24645f65bf0611dde3cc20dd50945062 100644 (file)
@@ -9,6 +9,7 @@
 import std::either::left;
 import std::either::right;
 import std::map::hashmap;
+import token::can_begin_expr;
 import driver::session;
 import util::common;
 import util::common::filename;
@@ -32,7 +33,6 @@
         fn restrict(restriction) ;
         fn get_restriction() -> restriction ;
         fn get_file_type() -> file_type ;
-        fn get_env() -> eval::env ;
         fn get_cfg() -> ast::crate_cfg;
         fn get_session() -> session::session ;
         fn get_span() -> common::span ;
         fn next_id() -> ast::node_id ;
     };
 
-fn new_parser(session::session sess, eval::env env,
+fn new_parser(session::session sess, ast::crate_cfg cfg,
               str path, uint pos, ast::node_id next_id) -> parser {
     obj stdio_parser(session::session sess,
-                     eval::env env,
                      ast::crate_cfg cfg,
                      file_type ftype,
                      mutable token::token tok,
@@ -85,7 +84,6 @@ fn bump() {
         fn get_hi_pos() -> uint { ret hi; }
         fn get_last_lo_pos() -> uint { ret last_lo; }
         fn get_file_type() -> file_type { ret ftype; }
-        fn get_env() -> eval::env { ret env; }
         fn get_cfg() -> ast::crate_cfg { ret cfg; }
         fn get_prec_table() -> vec[op_spec] { ret precs; }
         fn get_str(token::str_num i) -> str {
@@ -106,17 +104,6 @@ fn get_id() -> ast::node_id {
         fn next_id() -> ast::node_id { ret next_id_var; }
     }
 
-    auto cfg = {
-        fn m(&tup(ast::ident, eval::val) item) -> @ast::meta_item {
-            auto name = item._0;
-            auto value = eval::val_as_str(item._1);
-            auto meta_item_ = ast::meta_name_value(name, value);
-            ret @rec(node=meta_item_,
-                     span=rec(lo=0u,hi=0u));
-        }
-        vec::map(m, env)
-    };
-
     auto ftype = SOURCE_FILE;
     if (str::ends_with(path, ".rc")) { ftype = CRATE_FILE; }
     auto srdr = io::file_reader(path);
@@ -128,13 +115,12 @@ fn m(&tup(ast::ident, eval::val) item) -> @ast::meta_item {
 
     lexer::consume_whitespace_and_comments(rdr);
     auto npos = rdr.get_chpos();
-    ret stdio_parser(sess, env, cfg, ftype, lexer::next_token(rdr),
+    ret stdio_parser(sess, cfg, ftype, lexer::next_token(rdr),
                      npos, npos, npos, UNRESTRICTED, rdr,
                      prec_table(), next_id, bad_expr_word_table(),
                      ext::syntax_expander_table());
 }
 
-
 // These are the words that shouldn't be allowed as value identifiers,
 // because, if used at the start of a line, they will cause the line to be
 // interpreted as a specific kind of statement, which would be confusing.
@@ -855,12 +841,14 @@ fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
         lo = ex_ext.span.lo;
         ex = ex_ext.node;
     } else if (eat_word(p, "fail")) {
-        auto msg;
-        alt (p.peek()) {
-            case (token::LIT_STR(?s)) { msg = some(p.get_str(s)); p.bump(); }
-            case (_) { msg = none; }
+        if (can_begin_expr(p.peek())) {
+            auto e = parse_expr(p);
+            hi = e.span.hi;
+            ex = ast::expr_fail(some(e));
+        }
+        else {
+            ex = ast::expr_fail(none);
         }
-        ex = ast::expr_fail(msg);
     } else if (eat_word(p, "log")) {
         auto e = parse_expr(p);
         ex = ast::expr_log(1, e);
@@ -945,7 +933,7 @@ fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
         hi = es.span.hi;
         ex = ast::expr_call(f, es.node);
     } else if (is_ident(p.peek()) && !is_word(p, "true") &&
-                   !is_word(p, "false")) {
+               !is_word(p, "false")) {
         check_bad_word(p);
         auto pth = parse_path_and_ty_param_substs(p);
         hi = pth.span.hi;
@@ -966,6 +954,9 @@ fn parse_syntax_ext(&parser p) -> @ast::expr {
 
 fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr {
     auto pth = parse_path(p);
+    if (vec::len(pth.node.idents) == 0u) {
+        p.fatal("expected a syntax expander name");
+    }
     auto es = parse_seq(token::LPAREN, token::RPAREN,
                         some(token::COMMA), parse_expr, p);
     auto hi = es.span.hi;
@@ -1405,7 +1396,7 @@ fn parse_pat(&parser p) -> @ast::pat {
     alt (p.peek()) {
         case (token::UNDERSCORE) {
             p.bump();
-            pat = ast::pat_wild(p.get_id());
+            pat = ast::pat_wild;
         }
         case (token::QUES) {
             p.bump();
@@ -1413,8 +1404,7 @@ fn parse_pat(&parser p) -> @ast::pat {
                 case (token::IDENT(?id, _)) {
                     hi = p.get_hi_pos();
                     p.bump();
-                    pat =
-                        ast::pat_bind(p.get_str(id), p.get_id());
+                    pat = ast::pat_bind(p.get_str(id));
                 }
                 case (?tok) {
                     p.fatal("expected identifier after '?' in pattern but " +
@@ -1427,7 +1417,7 @@ fn parse_pat(&parser p) -> @ast::pat {
             if (!is_ident(tok) || is_word(p, "true") || is_word(p, "false")) {
                 auto lit = parse_lit(p);
                 hi = lit.span.hi;
-                pat = ast::pat_lit(@lit, p.get_id());
+                pat = ast::pat_lit(@lit);
             } else {
                 auto tag_path = parse_path_and_ty_param_substs(p);
                 hi = tag_path.span.hi;
@@ -1443,11 +1433,11 @@ fn parse_pat(&parser p) -> @ast::pat {
                     }
                     case (_) { args = []; }
                 }
-                pat = ast::pat_tag(tag_path, args, p.get_id());
+                pat = ast::pat_tag(tag_path, args);
             }
         }
     }
-    ret @spanned(lo, hi, pat);
+    ret @rec(id=p.get_id(), node=pat, span=rec(lo=lo, hi=hi));
 }
 
 fn parse_local_full(&option::t[@ast::ty] tyopt, &parser p)
@@ -1979,6 +1969,21 @@ fn parse_item_tag(&parser p, vec[ast::attribute] attrs) -> @ast::item {
     auto id = parse_ident(p);
     auto ty_params = parse_ty_params(p);
     let vec[ast::variant] variants = [];
+    // Newtype syntax
+    if (p.peek() == token::EQ) {
+        if (p.get_bad_expr_words().contains_key(id)) {
+            p.fatal("found " + id + " in tag constructor position");
+        }
+        p.bump();
+        auto ty = parse_ty(p);
+        expect(p, token::SEMI);
+        auto variant = spanned(ty.span.lo, ty.span.hi,
+                               rec(name=id,
+                                   args=[rec(ty=ty, id=p.get_id())],
+                                   id=p.get_id()));
+        ret mk_item(p, lo, ty.span.hi, id,
+                    ast::item_tag([variant], ty_params), attrs);
+    }
     expect(p, token::LBRACE);
     while (p.peek() != token::RBRACE) {
         auto tok = p.peek();
@@ -2396,25 +2401,12 @@ fn parse_crate_directive(&parser p, vec[ast::attribute] first_outer_attr)
         auto hi = p.get_hi_pos();
         expect(p, token::SEMI);
         ret spanned(lo, hi, ast::cdir_auth(n, a));
-    } else if (eat_word(p, "let")) {
-        expect(p, token::LPAREN);
-        auto id = parse_value_ident(p);
-        expect(p, token::EQ);
-        auto x = parse_expr(p);
-        expect(p, token::RPAREN);
-        expect(p, token::LBRACE);
-        auto v = parse_crate_directives(p, token::RBRACE, []);
-        auto hi = p.get_hi_pos();
-        expect(p, token::RBRACE);
-        ret spanned(lo, hi, ast::cdir_let(id, x, v));
     } else if (is_view_item(p)) {
         auto vi = parse_view_item(p);
         ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
     } else {
-        auto x = parse_expr(p);
-        ret spanned(lo, x.span.hi, ast::cdir_expr(x));
+        ret p.fatal("expected crate directive");
     }
-    fail;
 }
 
 fn parse_crate_directives(&parser p, token::token term,
@@ -2450,9 +2442,10 @@ fn parse_crate_from_crate_file(&parser p) -> @ast::crate {
              mutable deps=deps,
              sess=p.get_session(),
              mutable chpos=p.get_chpos(),
-             mutable next_id=p.next_id());
+             mutable next_id=p.next_id(),
+             cfg = p.get_cfg());
     auto m =
-        eval::eval_crate_directives_to_mod(cx, p.get_env(), cdirs, prefix);
+        eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
     auto hi = p.get_hi_pos();
     expect(p, token::EOF);
     ret @spanned(lo, hi, rec(directives=cdirs,
index 50686d5093f8f0ef8e75f4057954601f32ab3088..664a5db5e82ed59266ee1d6a93f1867ae82197ae 100644 (file)
@@ -172,6 +172,27 @@ fn to_str(lexer::reader r, token t) -> str {
         case (EOF) { ret "<eof>"; }
     }
 }
+
+
+pred can_begin_expr(token t) -> bool {
+    alt (t) {
+        case (LPAREN) { true }
+        case (LBRACE) { true }
+        case (IDENT(_,_)) { true }
+        case (UNDERSCORE) { true }
+        case (TILDE) { true }
+        case (LIT_INT(_)) { true }
+        case (LIT_UINT(_)) { true }
+        case (LIT_MACH_INT(_,_)) { true }
+        case (LIT_FLOAT(_)) { true }
+        case (LIT_MACH_FLOAT(_,_)) { true }
+        case (LIT_STR(_)) { true }
+        case (LIT_CHAR(_)) { true }
+        case (POUND) { true }
+        case (AT) { true }
+        case (_) { false }
+    }
+}
 // Local Variables:
 // fill-column: 78;
 // indent-tabs-mode: nil
index b671b2485c00c850e3de8f54eed1928b284e9cad..1cbd4c0a98cefa988866836807a6abf0d07ea441 100644 (file)
 const uint LLVMRealULE = 13u;
 const uint LLVMRealUNE = 14u;
 
+#[link_args = "-Lrustllvm"]
 native mod llvm = "rustllvm" {
 
     type ModuleRef;
@@ -1405,6 +1406,10 @@ fn Trap() -> ValueRef {
                                str::buf(""));
     }
 
+    fn is_terminated() -> bool {
+        ret *terminated;
+    }
+
     drop {
         llvm::LLVMDisposeBuilder(B);
     }
index 743eb3bd2282e7652b16df5e2a59f49b8b8c9281..5e9cf52a282909cbaaa30b1478171850cfc9d174 100644 (file)
@@ -170,16 +170,24 @@ fn visit_view_item(env e, &@ast::view_item i) {
 fn visit_item(env e, &@ast::item i) {
     alt (i.node) {
         case (ast::item_native_mod(?m)) {
-            alt (m.abi) {
-                case (ast::native_abi_rust) {
-                    e.sess.add_used_library(m.native_name);
-                }
-                case (ast::native_abi_cdecl) {
-                    e.sess.add_used_library(m.native_name);
-                }
-                case (ast::native_abi_llvm) {
-                }
-                case (ast::native_abi_rust_intrinsic) {
+            if (m.abi != ast::native_abi_rust &&
+                m.abi != ast::native_abi_cdecl) {
+                ret;
+            }
+            if (!e.sess.add_used_library(m.native_name)) {
+                ret;
+            }
+            for (ast::attribute a in i.attrs) {
+                auto v = a.node.value.node;
+                alt (v) {
+                    case (ast::meta_name_value(?i, ?s)) {
+                        if (i != "link_args") {
+                            cont;
+                        }
+                        e.sess.add_used_link_args(s);
+                    }
+                    case (_) {
+                    }
                 }
             }
         }
index b82029c21d28c7cfeb7d38ebf351d91f06307671..0eda4bbf5af629fbde3cb5ba3a1d9fd90ea45ce2 100644 (file)
@@ -7,6 +7,7 @@
 import std::io;
 import std::map::hashmap;
 import front::ast;
+import front::attr;
 import middle::ty;
 import tags::*;
 import tydecode::parse_def_id;
@@ -267,8 +268,7 @@ fn get_meta_items(&ebml::doc md) -> vec[@ast::meta_item] {
               ebml::tagged_docs(md, tag_meta_item_word)) {
         auto nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
         auto n = str::unsafe_from_bytes(ebml::doc_data(nd));
-        items += [@rec(node=ast::meta_word(n),
-                       span=rec(lo=0u, hi=0u))];
+        items += [attr::mk_word_item(n)];
     }
     for each (ebml::doc meta_item_doc in
               ebml::tagged_docs(md, tag_meta_item_name_value)) {
@@ -276,16 +276,14 @@ fn get_meta_items(&ebml::doc md) -> vec[@ast::meta_item] {
         auto vd = ebml::get_doc(meta_item_doc, tag_meta_item_value);
         auto n = str::unsafe_from_bytes(ebml::doc_data(nd));
         auto v = str::unsafe_from_bytes(ebml::doc_data(vd));
-        items += [@rec(node=ast::meta_name_value(n, v),
-                       span=rec(lo=0u, hi=0u))];
+        items += [attr::mk_name_value_item(n, v)];
     }
     for each (ebml::doc meta_item_doc in
               ebml::tagged_docs(md, tag_meta_item_list)) {
         auto nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
         auto n = str::unsafe_from_bytes(ebml::doc_data(nd));
         auto subitems = get_meta_items(meta_item_doc);
-        items += [@rec(node=ast::meta_list(n, subitems),
-                       span=rec(lo=0u, hi=0u))];                  
+        items += [attr::mk_list_item(n, subitems)];
     }
     ret items;
 }
index ec7801350d6e159328b4c6412c511692e4d246da..c867f483dd34f5d1f6e869789a095f16c63f5f1a 100644 (file)
@@ -330,7 +330,8 @@ fn encode_info_for_native_item(&@crate_ctxt cx, &ebml::writer ebml_w,
         case (native_item_ty) {
             encode_def_id(ebml_w, local_def(nitem.id));
             encode_kind(ebml_w, 'T' as u8);
-            encode_type(cx, ebml_w, ty::mk_native(cx.tcx));
+            encode_type(cx, ebml_w,
+                        ty::mk_native(cx.tcx, local_def(nitem.id)));
         }
         case (native_item_fn(_, _, ?tps)) {
             encode_def_id(ebml_w, local_def(nitem.id));
@@ -462,7 +463,7 @@ fn encode_attributes(&ebml::writer ebml_w, &vec[attribute] attrs) {
 
 // So there's a special crate attribute called 'link' which defines the
 // metadata that Rust cares about for linking crates. This attribute requires
-// name and value attributes, so if the user didn't provide them we will throw
+// 'name' and 'vers' items, so if the user didn't provide them we will throw
 // them in anyway with default values.
 fn synthesize_crate_attrs(&@crate_ctxt cx,
                           &@crate crate) -> vec[attribute] {
@@ -471,33 +472,23 @@ fn synthesize_link_attr(&@crate_ctxt cx,
                             &vec[@meta_item] items)
         -> attribute {
 
-        auto bogus_span = rec(lo = 0u, hi = 0u);
+        assert cx.link_meta.name != "";
+        assert cx.link_meta.vers != "";
 
-        auto name_item_ = meta_name_value("name", cx.link_meta.name);
-        auto name_item = rec(node=name_item_,
-                             span=bogus_span);
-
-        auto vers_item_ = meta_name_value("vers", cx.link_meta.vers);
-        auto vers_item = rec(node=vers_item_,
-                             span=bogus_span);
+        auto name_item = attr::mk_name_value_item("name",
+                                                  cx.link_meta.name);
+        auto vers_item = attr::mk_name_value_item("vers",
+                                                  cx.link_meta.vers);
 
         auto other_items = {
             auto tmp = attr::remove_meta_items_by_name(items, "name");
             attr::remove_meta_items_by_name(tmp, "vers")
         };
 
-        auto meta_items = [@name_item] + [@vers_item] + other_items;
-
-        auto link_item_ = meta_list("link", meta_items);
-        auto link_item = rec(node=link_item_,
-                             span=bogus_span);
-
-        auto attr_ = rec(style = attr_inner,
-                         value = link_item);
-        auto attr = rec(node=attr_,
-                        span=bogus_span);
+        auto meta_items = [name_item] + [vers_item] + other_items;
+        auto link_item = attr::mk_list_item("link", meta_items);
 
-        ret attr;
+        ret attr::mk_attr(link_item);
     }
 
     let vec[attribute] attrs = [];
index cafabd6c3553ccbd3b216e2758629cfc20c0a1b3..d174dc7e3a10afc61d505c66ab7fefdfb4798dab 100644 (file)
@@ -263,7 +263,10 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
             ret ty::mk_res(st.tcx, def, inner, params);
         }
         case ('X') { ret ty::mk_var(st.tcx, parse_int(st)); }
-        case ('E') { ret ty::mk_native(st.tcx); }
+        case ('E') {
+            auto def = parse_def(st, sd);
+            ret ty::mk_native(st.tcx, def);
+        }
         case ('Y') { ret ty::mk_type(st.tcx); }
         case ('#') {
             auto pos = parse_hex(st);
index df33fadd632b849234e7c23b9d1d7083b3b15231..a9090c3624c19c01cdd731d9059de2ab81412448 100644 (file)
@@ -184,7 +184,11 @@ fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
             w.write_char('X');
             w.write_str(common::istr(id));
         }
-        case (ty::ty_native) { w.write_char('E'); }
+        case (ty::ty_native(?def)) {
+            w.write_char('E');
+            w.write_str(cx.ds(def));
+            w.write_char('|');
+        }
         case (ty::ty_param(?id)) {
             w.write_char('p');
             w.write_str(common::uistr(id));
@@ -228,7 +232,7 @@ fn enc_ty_fn(&io::writer w, &@ctxt cx, &ty::arg[] args, &ty::t out,
 
 }
 fn enc_constr(&io::writer w, &@ctxt cx, &@ty::constr_def c) {
-    w.write_str(ty::path_to_str(c.node.path));
+    w.write_str(path_to_str(c.node.path));
     w.write_char('(');
     w.write_str(cx.ds(c.node.id));
     w.write_char('|');
index 20bed30a7d2a01b954eb1258f2a7a7f55ec7b2b6..3c482cc252e7683905cc8572a8beeffddcfed0ad 100644 (file)
@@ -51,6 +51,7 @@ fn check_crate(@ty::ctxt tcx, &@ast::crate crate) {
              visit_expr=bind visit_expr(cx, _, _, _)
              with *visit::default_visitor[scope]());
     visit::visit_crate(*crate, [], visit::vtor(v));
+    tcx.sess.abort_if_errors();
 }
 
 fn visit_fn(@ctx cx, &ast::_fn f, &vec[ast::ty_param] tp, &span sp,
@@ -93,7 +94,7 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
                 case (some(?ex)) {
                     auto root = expr_root(*cx, ex, false);
                     if (mut_field(root.ds)) {
-                        cx.tcx.sess.span_fatal(ex.span,
+                        cx.tcx.sess.span_err(ex.span,
                                              "result of put must be" +
                                                  " immutably rooted");
                     }
@@ -153,7 +154,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
                             auto m =
                                 "passing a temporary value or \
                                  immutable field by mutable alias";
-                            cx.tcx.sess.span_fatal(arg.span, m);
+                            cx.tcx.sess.span_err(arg.span, m);
                         }
                     }
                 }
@@ -176,7 +177,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
         alt (f.node) {
             case (ast::expr_path(_)) {
                 if (def_is_local(cx.tcx.def_map.get(f.id), true)) {
-                    cx.tcx.sess.span_fatal(f.span,
+                    cx.tcx.sess.span_err(f.span,
                                          #fmt("function may alias with \
                          argument %u, which is not immutably rooted",
                                               unsafe_t_offsets.(0)));
@@ -195,7 +196,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
             if (i != offset &&
                     ty_can_unsafely_include(cx, unsafe, arg_t.ty, mut_alias))
                {
-                cx.tcx.sess.span_fatal(args.(i).span,
+                cx.tcx.sess.span_err(args.(i).span,
                                      #fmt("argument %u may alias with \
                      argument %u, which is not immutably rooted",
                                           i, offset));
@@ -213,7 +214,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
             }
         }
         if (mut_alias_to_root) {
-            cx.tcx.sess.span_fatal(args.(root._0).span,
+            cx.tcx.sess.span_err(args.(root._0).span,
                                  "passing a mutable alias to a \
                  variable that roots another alias");
         }
@@ -239,7 +240,7 @@ fn check_tail_call(&ctx cx, &@ast::expr call) {
                     alt (cx.local_map.find(dnum)) {
                         case (some(arg(ast::alias(?mut)))) {
                             if (mut_a && !mut) {
-                                cx.tcx.sess.span_fatal(args.(i).span,
+                                cx.tcx.sess.span_err(args.(i).span,
                                                       "passing an immutable \
                                      alias by mutable alias");
                             }
@@ -250,7 +251,7 @@ fn check_tail_call(&ctx cx, &@ast::expr call) {
                 case (_) { ok = false; }
             }
             if (!ok) {
-                cx.tcx.sess.span_fatal(args.(i).span,
+                cx.tcx.sess.span_err(args.(i).span,
                                       "can not pass a local value by \
                                      alias to a tail call");
             }
@@ -291,8 +292,8 @@ fn arm_defnums(&ast::arm arm) -> vec[node_id] {
     auto dnums = [];
     fn walk_pat(&mutable vec[node_id] found, &@ast::pat p) {
         alt (p.node) {
-            case (ast::pat_bind(_, ?id)) { vec::push(found, id); }
-            case (ast::pat_tag(_, ?children, _)) {
+            case (ast::pat_bind(_)) { vec::push(found, p.id); }
+            case (ast::pat_tag(_, ?children)) {
                 for (@ast::pat child in children) { walk_pat(found, child); }
             }
             case (_) { }
@@ -386,10 +387,10 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
         case (ast::expr_path(?p)) {
             auto dnum = ast::def_id_of_def(cx.tcx.def_map.get(dest.id))._1;
             if (is_immutable_alias(cx, sc, dnum)) {
-                cx.tcx.sess.span_fatal(dest.span,
+                cx.tcx.sess.span_err(dest.span,
                                      "assigning to immutable alias");
             } else if (is_immutable_objfield(cx, dnum)) {
-                cx.tcx.sess.span_fatal(dest.span,
+                cx.tcx.sess.span_err(dest.span,
                                      "assigning to immutable obj field");
             }
             for (restrict r in sc) {
@@ -402,7 +403,7 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
         case (_) {
             auto root = expr_root(*cx, dest, false);
             if (vec::len(root.ds) == 0u) {
-                cx.tcx.sess.span_fatal(dest.span, "assignment to non-lvalue");
+                cx.tcx.sess.span_err(dest.span, "assignment to non-lvalue");
             } else if (!root.ds.(0).mut) {
                 auto name =
                     alt (root.ds.(0).kind) {
@@ -410,7 +411,7 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
                         case (field) { "field" }
                         case (index) { "vec content" }
                     };
-                cx.tcx.sess.span_fatal(dest.span,
+                cx.tcx.sess.span_err(dest.span,
                                      "assignment to immutable " + name);
             }
             visit_expr(cx, dest, sc, v);
@@ -456,7 +457,7 @@ fn test_scope(&ctx cx, &scope sc, &restrict r, &ast::path p) {
                     tup(sp, "taking the value of " + ast::path_name(vpt))
                 }
             };
-        cx.tcx.sess.span_fatal(msg._0,
+        cx.tcx.sess.span_err(msg._0,
                              msg._1 + " will invalidate alias " +
                                  ast::path_name(p) + ", which is still used");
     }
@@ -549,18 +550,13 @@ fn maybe_push_auto_unbox(&option::t[deref] d, &mutable vec[deref] ds) {
             case (ast::expr_unary(?op, ?base)) {
                 if (op == ast::deref) {
                     auto base_t = ty::expr_ty(*cx.tcx, base);
+                    auto mut = false;
                     alt (ty::struct(*cx.tcx, base_t)) {
-                        case (ty::ty_box(?mt)) {
-                            vec::push(ds, rec(mut=mt.mut != ast::imm,
-                                              kind=unbox,
-                                              outer_t=base_t));
-                        }
-                        case (ty::ty_res(_, ?inner, _)) {
-                            vec::push(ds, rec(mut=false,
-                                              kind=unbox,
-                                              outer_t=base_t));
-                        }
+                        case (ty::ty_box(?mt)) { mut = mt.mut != ast::imm; }
+                        case (ty::ty_res(_, _, _)) {}
+                        case (ty::ty_tag(_, _)) {}
                     }
+                    vec::push(ds, rec(mut=mut, kind=unbox, outer_t=base_t));
                     ex = base;
                 } else { break; }
             }
@@ -663,7 +659,7 @@ fn def_is_local(&ast::def d, bool objfields_count) -> bool {
 }
 
 fn fty_args(&ctx cx, ty::t fty) -> ty::arg[] {
-    ret alt (ty::struct(*cx.tcx, fty)) {
+    ret alt (ty::struct(*cx.tcx, ty::type_autoderef(*cx.tcx, fty))) {
             case (ty::ty_fn(_, ?args, _, _, _)) { args }
             case (ty::ty_native_fn(_, ?args, _)) { args }
         };
index eb7d3d4dd824ab319bf3069a06d1690cfe771ab2..0fdf92192461d0b08567207947bc75812ce27e13 100644 (file)
@@ -301,14 +301,14 @@ fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
     }
     fn walk_pat(&env e, &scopes sc, &@ast::pat pat) {
         alt (pat.node) {
-            case (ast::pat_tag(?p, ?children, ?id)) {
+            case (ast::pat_tag(?p, ?children)) {
                 auto fnd =
                     lookup_path_strict(e, sc, p.span, p.node.idents,
                                        ns_value);
                 if (option::is_some(fnd)) {
                     alt (option::get(fnd)) {
                         case (ast::def_variant(?did, ?vid)) {
-                            e.def_map.insert(id, option::get(fnd));
+                            e.def_map.insert(pat.id, option::get(fnd));
                             for (@ast::pat child in children) {
                                 walk_pat(e, sc, child);
                             }
@@ -423,7 +423,7 @@ fn resolve_constr(@env e, node_id id, &@ast::constr c, &scopes sc,
             case (_) {
                 e.sess.span_err(c.span,
                                 "Non-predicate in constraint: " +
-                                ty::path_to_str(c.node.path));
+                                ast::path_to_str(c.node.path));
             }
         }
     }
@@ -694,14 +694,14 @@ fn lookup_in_ty_params(&ident name, &vec[ast::ty_param] ty_params) ->
 
 fn lookup_in_pat(&ident name, &ast::pat pat) -> option::t[def] {
     alt (pat.node) {
-        case (ast::pat_bind(?p_name, ?id)) {
+        case (ast::pat_bind(?p_name)) {
             if (str::eq(p_name, name)) {
-                ret some(ast::def_binding(local_def(id)));
+                ret some(ast::def_binding(local_def(pat.id)));
             }
         }
-        case (ast::pat_wild(_)) { }
-        case (ast::pat_lit(_, _)) { }
-        case (ast::pat_tag(_, ?pats, _)) {
+        case (ast::pat_wild) { }
+        case (ast::pat_lit(_)) { }
+        case (ast::pat_tag(_, ?pats)) {
             for (@ast::pat p in pats) {
                 auto found = lookup_in_pat(name, *p);
                 if (!option::is_none(found)) { ret found; }
@@ -1248,8 +1248,8 @@ fn check_arm(@env e, &ast::arm a, &() x, &vt[()] v) {
     visit::visit_arm(a, x, v);
     fn walk_pat(checker ch, &@ast::pat p) {
         alt (p.node) {
-            case (ast::pat_bind(?name, _)) { add_name(ch, p.span, name); }
-            case (ast::pat_tag(_, ?children, _)) {
+            case (ast::pat_bind(?name)) { add_name(ch, p.span, name); }
+            case (ast::pat_tag(_, ?children)) {
                 for (@ast::pat child in children) { walk_pat(ch, child); }
             }
             case (_) { }
index 6da9a5785104f64dfd37bafe0b0a31ff9fa8f33a..d05f65d5fd7d4082897e3f55e65cf9264da661bb 100644 (file)
 tag block_parent { parent_none; parent_some(@block_ctxt); }
 
 type result = rec(@block_ctxt bcx, ValueRef val);
+type result_t = rec(@block_ctxt bcx, ValueRef val, ty::t ty);
 
 fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
     ret @rec(path=cx.path + [name] with *cx);
@@ -782,7 +783,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
     if (cx.lltypes.contains_key(t)) { ret cx.lltypes.get(t); }
     let TypeRef llty = 0 as TypeRef;
     alt (ty::struct(cx.tcx, t)) {
-        case (ty::ty_native) { llty = T_ptr(T_i8()); }
+        case (ty::ty_native(_)) { llty = T_ptr(T_i8()); }
         case (ty::ty_nil) { llty = T_nil(); }
         case (ty::ty_bot) {
             llty = T_nil(); /* ...I guess? */
@@ -809,14 +810,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
         case (ty::ty_char) { llty = T_char(); }
         case (ty::ty_str) { llty = T_ptr(T_str()); }
         case (ty::ty_istr) { llty = T_ivec(T_i8()); }
-        case (ty::ty_tag(_, _)) {
-            if (ty::type_has_dynamic_size(cx.tcx, t)) {
-                llty = T_opaque_tag(cx.tn);
-            } else {
-                auto size = static_size_of_tag(cx, sp, t);
-                llty = T_tag(cx.tn, size);
-            }
-        }
+        case (ty::ty_tag(?did, _)) { llty = type_of_tag(cx, sp, did, t); }
         case (ty::ty_box(?mt)) {
             llty = T_ptr(T_box(type_of_inner(cx, sp, mt.ty)));
         }
@@ -894,6 +888,22 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
     ret llty;
 }
 
+fn type_of_tag(&@crate_ctxt cx, &span sp, &ast::def_id did, &ty::t t)
+    -> TypeRef {
+    auto degen = vec::len(ty::tag_variants(cx.tcx, did)) == 1u;
+    if (ty::type_has_dynamic_size(cx.tcx, t)) {
+        if (degen) { ret T_i8(); }
+        else { ret T_opaque_tag(cx.tn); }
+    } else {
+        auto size = static_size_of_tag(cx, sp, t);
+        if (!degen) { ret T_tag(cx.tn, size); }
+        // LLVM does not like 0-size arrays, apparently
+        if (size == 0u) { size = 1u; }
+        ret T_array(T_i8(), size);
+    }
+}
+
+
 fn type_of_arg(@local_ctxt cx, &span sp, &ty::arg arg) -> TypeRef {
     alt (ty::struct(cx.ccx.tcx, arg.ty)) {
         case (ty::ty_param(_)) {
@@ -1339,7 +1349,9 @@ fn align_elements(&@block_ctxt cx, &vec[ty::t] elts) -> result {
                 bcx.build.Store(umax(bcx, this_size, old_max_size), max_size);
             }
             auto max_size_val = bcx.build.Load(max_size);
-            auto total_size = bcx.build.Add(max_size_val, llsize_of(T_int()));
+            auto total_size = if (vec::len(variants) != 1u) {
+                bcx.build.Add(max_size_val, llsize_of(T_int()))
+            } else { max_size_val };
             ret rslt(bcx, total_size);
         }
         case (ty::ty_ivec(?mt)) {
@@ -1933,8 +1945,8 @@ fn make_copy_glue(&@block_ctxt cx, ValueRef v, &ty::t t) {
     if (ty::type_is_boxed(cx.fcx.lcx.ccx.tcx, t)) {
         bcx = incr_refcnt_of_boxed(cx, cx.build.Load(v)).bcx;
     } else if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, t)) {
-        bcx = iter_structural_ty(cx, v, t, bind copy_ty(_, _, _)).bcx;
-        bcx = duplicate_heap_parts_if_necessary(bcx, v, t).bcx;
+        bcx = duplicate_heap_parts_if_necessary(cx, v, t).bcx;
+        bcx = iter_structural_ty(bcx, v, t, bind copy_ty(_, _, _)).bcx;
     } else { bcx = cx; }
     bcx.build.RetVoid();
 }
@@ -2399,7 +2411,7 @@ fn compare_scalar_types(@block_ctxt cx, ValueRef lhs, ValueRef rhs, &ty::t t,
             ret rslt(new_sub_block_ctxt(cx, "after_fail_dummy"),
                      C_bool(false));
         }
-        case (ty::ty_native) {
+        case (ty::ty_native(_)) {
             trans_fail(cx, none[common::span],
                        "attempt to compare values of type native");
             ret rslt(new_sub_block_ctxt(cx, "after_fail_dummy"),
@@ -2535,6 +2547,7 @@ fn iter_boxpp(@block_ctxt cx, ValueRef box_a_cell, ValueRef box_b_cell,
         r.bcx.build.Br(next_cx.llbb);
         ret rslt(next_cx, C_nil());
     }
+
     fn iter_ivec(@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
                  &val_pair_and_ty_fn f) -> result {
         // FIXME: "unimplemented rebinding existing function" workaround
@@ -2603,6 +2616,42 @@ fn adapter(&@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
 
         ret rslt(next_cx, C_nil());
     }
+
+    fn iter_variant(@block_ctxt cx, ValueRef a_tup, ValueRef b_tup,
+                    &ty::variant_info variant, &vec[ty::t] tps,
+                    &ast::def_id tid, &val_pair_and_ty_fn f) -> result {
+        if (vec::len[ty::t](variant.args) == 0u) {
+            ret rslt(cx, C_nil());
+        }
+        auto fn_ty = variant.ctor_ty;
+        auto ccx = cx.fcx.lcx.ccx;
+        alt (ty::struct(ccx.tcx, fn_ty)) {
+            case (ty::ty_fn(_, ?args, _, _, _)) {
+                auto j = 0;
+                for (ty::arg a in args) {
+                    auto rslt = GEP_tag(cx, a_tup, tid,
+                                        variant.id, tps, j);
+                    auto llfldp_a = rslt.val;
+                    cx = rslt.bcx;
+                    rslt = GEP_tag(cx, b_tup, tid,
+                                   variant.id, tps, j);
+                    auto llfldp_b = rslt.val;
+                    cx = rslt.bcx;
+                    auto ty_subst =
+                        ty::substitute_type_params(ccx.tcx, tps, a.ty);
+                    auto llfld_a =
+                        load_if_immediate(cx, llfldp_a, ty_subst);
+                    auto llfld_b =
+                        load_if_immediate(cx, llfldp_b, ty_subst);
+                    rslt = f(cx, llfld_a, llfld_b, ty_subst);
+                    cx = rslt.bcx;
+                    j += 1;
+                }
+            }
+        }
+        ret rslt(cx, C_nil());
+    }
+    
     let result r = rslt(cx, C_nil());
     alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
         case (ty::ty_tup(?args)) {
@@ -2612,8 +2661,7 @@ fn adapter(&@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
                 auto elt_a = r.val;
                 r = GEP_tup_like(r.bcx, t, bv, [0, i]);
                 auto elt_b = r.val;
-                r =
-                    f(r.bcx, load_if_immediate(r.bcx, elt_a, arg.ty),
+                r = f(r.bcx, load_if_immediate(r.bcx, elt_a, arg.ty),
                       load_if_immediate(r.bcx, elt_b, arg.ty), arg.ty);
                 i += 1;
             }
@@ -2625,8 +2673,7 @@ fn adapter(&@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
                 auto llfld_a = r.val;
                 r = GEP_tup_like(r.bcx, t, bv, [0, i]);
                 auto llfld_b = r.val;
-                r =
-                    f(r.bcx, load_if_immediate(r.bcx, llfld_a, fld.mt.ty),
+                r = f(r.bcx, load_if_immediate(r.bcx, llfld_a, fld.mt.ty),
                       load_if_immediate(r.bcx, llfld_b, fld.mt.ty),
                       fld.mt.ty);
                 i += 1;
@@ -2644,8 +2691,12 @@ fn adapter(&@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
         }
         case (ty::ty_tag(?tid, ?tps)) {
             auto variants = ty::tag_variants(cx.fcx.lcx.ccx.tcx, tid);
-            auto n_variants = vec::len[ty::variant_info](variants);
+            auto n_variants = vec::len(variants);
+
             // Cast the tags to types we can GEP into.
+            if (n_variants == 1u) {
+                ret iter_variant(cx, av, bv, variants.(0), tps, tid, f);
+            }
 
             auto lltagty = T_opaque_tag_ptr(cx.fcx.lcx.ccx.tn);
             auto av_tag = cx.build.PointerCast(av, lltagty);
@@ -2656,9 +2707,9 @@ fn adapter(&@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
             auto lldiscrim_b_ptr = cx.build.GEP(bv_tag, [C_int(0), C_int(0)]);
             auto llunion_b_ptr = cx.build.GEP(bv_tag, [C_int(0), C_int(1)]);
             auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr);
+
             // NB: we must hit the discriminant first so that structural
             // comparison know not to proceed when the discriminants differ.
-
             auto bcx = cx;
             bcx =
                 f(bcx, lldiscrim_a, lldiscrim_b,
@@ -2675,47 +2726,10 @@ fn adapter(&@block_ctxt bcx, ValueRef av, ValueRef bv, ty::t unit_ty,
                                        "tag-iter-variant-" +
                                            uint::to_str(i, 10u));
                 llvm::LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb);
-                if (vec::len[ty::t](variant.args) > 0u) {
-                    // N-ary variant.
-
-                    auto fn_ty = variant.ctor_ty;
-                    alt (ty::struct(bcx.fcx.lcx.ccx.tcx, fn_ty)) {
-                        case (ty::ty_fn(_, ?args, _, _, _)) {
-                            auto j = 0;
-                            for (ty::arg a in args) {
-                                auto rslt =
-                                    GEP_tag(variant_cx, llunion_a_ptr, tid,
-                                            variant.id, tps, j);
-                                auto llfldp_a = rslt.val;
-                                variant_cx = rslt.bcx;
-                                rslt =
-                                    GEP_tag(variant_cx, llunion_b_ptr, tid,
-                                            variant.id, tps, j);
-                                auto llfldp_b = rslt.val;
-                                variant_cx = rslt.bcx;
-                                auto tcx = cx.fcx.lcx.ccx.tcx;
-                                auto ty_subst =
-                                    ty::substitute_type_params(tcx, tps,
-                                                               a.ty);
-                                auto llfld_a =
-                                    load_if_immediate(variant_cx, llfldp_a,
-                                                      ty_subst);
-                                auto llfld_b =
-                                    load_if_immediate(variant_cx, llfldp_b,
-                                                      ty_subst);
-                                rslt =
-                                    f(variant_cx, llfld_a, llfld_b, ty_subst);
-                                variant_cx = rslt.bcx;
-                                j += 1;
-                            }
-                        }
-                    }
-                    variant_cx.build.Br(next_cx.llbb);
-                } else {
-                    // Nullary variant; nothing to do.
-
-                    variant_cx.build.Br(next_cx.llbb);
-                }
+                variant_cx = iter_variant
+                    (variant_cx, llunion_a_ptr, llunion_b_ptr, variant,
+                     tps, tid, f).bcx;
+                variant_cx.build.Br(next_cx.llbb);
                 i += 1u;
             }
             ret rslt(next_cx, C_nil());
@@ -3307,18 +3321,16 @@ fn trans_unary(&@block_ctxt cx, ast::unop op, &@ast::expr e,
     auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e);
     alt (op) {
         case (ast::not) {
-            sub =
-                autoderef(sub.bcx, sub.val,
-                          ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
-            ret rslt(sub.bcx, sub.bcx.build.Not(sub.val));
+            auto dr = autoderef(sub.bcx, sub.val,
+                                ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
+            ret rslt(dr.bcx, dr.bcx.build.Not(dr.val));
         }
         case (ast::neg) {
-            sub =
-                autoderef(sub.bcx, sub.val,
-                          ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
+            auto dr = autoderef(sub.bcx, sub.val,
+                                ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
             if (ty::struct(cx.fcx.lcx.ccx.tcx, e_ty) == ty::ty_float) {
-                ret rslt(sub.bcx, sub.bcx.build.FNeg(sub.val));
-            } else { ret rslt(sub.bcx, sub.bcx.build.Neg(sub.val)); }
+                ret rslt(dr.bcx, dr.bcx.build.FNeg(dr.val));
+            } else { ret rslt(dr.bcx, sub.bcx.build.Neg(dr.val)); }
         }
         case (ast::box(_)) {
             auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e);
@@ -3367,7 +3379,6 @@ fn trans_compare(&@block_ctxt cx0, ast::binop op, &ty::t t0, ValueRef lhs0,
     auto rhs_r = autoderef(cx, rhs0, t0);
     auto rhs = rhs_r.val;
     cx = rhs_r.bcx;
-    auto t = autoderefed_ty(cx.fcx.lcx.ccx, t0);
     // Determine the operation we need.
     // FIXME: Use or-patterns when we have them.
 
@@ -3380,7 +3391,7 @@ fn trans_compare(&@block_ctxt cx0, ast::binop op, &ty::t t0, ValueRef lhs0,
         case (ast::ge) { llop = C_u8(abi::cmp_glue_op_lt); }
         case (ast::gt) { llop = C_u8(abi::cmp_glue_op_le); }
     }
-    auto rs = compare(cx, lhs, rhs, t, llop);
+    auto rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
 
     // Invert the result if necessary.
     // FIXME: Use or-patterns when we have them.
@@ -4099,12 +4110,19 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype,
     }
 }
 
-fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
+fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
+    -> result_t {
     let ValueRef v1 = v;
     let ty::t t1 = t;
+    auto ccx = cx.fcx.lcx.ccx;
     while (true) {
-        alt (ty::struct(cx.fcx.lcx.ccx.tcx, t1)) {
+        alt (ty::struct(ccx.tcx, t1)) {
             case (ty::ty_box(?mt)) {
+                // If we are working with an lval, we want to
+                // unconditionally load at the top of the loop
+                // to get rid of the extra indirection
+                if (is_lval) { v1 = cx.build.Load(v1); }
+
                 auto body =
                     cx.build.GEP(v1,
                                  [C_int(0), C_int(abi::box_rc_field_body)]);
@@ -4113,28 +4131,42 @@ fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
                 // to cast this pointer, since statically-sized tag types have
                 // different types depending on whether they're behind a box
                 // or not.
-
-                if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, mt.ty)) {
-                    auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, mt.ty);
+                if (!ty::type_has_dynamic_size(ccx.tcx, mt.ty)) {
+                    auto llty = type_of(ccx, cx.sp, mt.ty);
                     v1 = cx.build.PointerCast(body, T_ptr(llty));
                 } else { v1 = body; }
-                v1 = load_if_immediate(cx, v1, t1);
+            }
+            case (ty::ty_res(?did, ?inner, ?tps)) {
+                if (is_lval) { v1 = cx.build.Load(v1); }
+                t1 = ty::substitute_type_params(ccx.tcx, tps, inner);
+                v1 = cx.build.GEP(v1, [C_int(0), C_int(1)]);
+            }
+            case (ty::ty_tag(?did, ?tps)) {
+                auto variants = ty::tag_variants(ccx.tcx, did);
+                if (vec::len(variants) != 1u ||
+                    vec::len(variants.(0).args) != 1u) {
+                    break;
+                }
+                if (is_lval) { v1 = cx.build.Load(v1); }
+                t1 = ty::substitute_type_params
+                    (ccx.tcx, tps, variants.(0).args.(0));
+                if (!ty::type_has_dynamic_size(ccx.tcx, t1)) {
+                    v1 = cx.build.PointerCast
+                        (v1, T_ptr(type_of(ccx, cx.sp, t1)));
+                }
             }
             case (_) { break; }
         }
+        // But if we aren't working with an lval, we get rid of
+        // a layer of indirection at the bottom of the loop so
+        // that it is gone when we return...
+        if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
     }
-    ret rslt(cx, v1);
+    ret rec(bcx=cx, val=v1, ty=t1);
 }
 
-fn autoderefed_ty(&@crate_ctxt ccx, &ty::t t) -> ty::t {
-    let ty::t t1 = t;
-    while (true) {
-        alt (ty::struct(ccx.tcx, t1)) {
-            case (ty::ty_box(?mt)) { t1 = mt.ty; }
-            case (_) { break; }
-        }
-    }
-    ret t1;
+fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t {
+    ret autoderef_lval(cx, v, t, false);
 }
 
 fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
@@ -4144,15 +4176,14 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
     alt (op) {
         case (ast::and) {
             // Lazy-eval and
-
-            auto lhs_res = trans_expr(cx, a);
-            lhs_res =
-                autoderef(lhs_res.bcx, lhs_res.val,
+            auto lhs_expr = trans_expr(cx, a);
+            auto lhs_res =
+                autoderef(lhs_expr.bcx, lhs_expr.val,
                           ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
             auto rhs_cx = new_scope_block_ctxt(cx, "rhs");
-            auto rhs_res = trans_expr(rhs_cx, b);
-            rhs_res =
-                autoderef(rhs_res.bcx, rhs_res.val,
+            auto rhs_expr = trans_expr(rhs_cx, b);
+            auto rhs_res =
+                autoderef(rhs_expr.bcx, rhs_expr.val,
                           ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
             auto lhs_false_cx = new_scope_block_ctxt(cx, "lhs false");
             auto lhs_false_res = rslt(lhs_false_cx, C_bool(false));
@@ -4165,20 +4196,18 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
             lhs_res.bcx.build.CondBr(lhs_res.val, rhs_cx.llbb,
                                      lhs_false_cx.llbb);
             ret join_results(cx, T_bool(),
-                             [lhs_false_res, rec(bcx=rhs_bcx with rhs_res)]);
+                             [lhs_false_res, rec(bcx=rhs_bcx,
+                                                 val=rhs_res.val)]);
         }
         case (ast::or) {
             // Lazy-eval or
-
-            auto lhs_res = trans_expr(cx, a);
-            lhs_res =
-                autoderef(lhs_res.bcx, lhs_res.val,
-                          ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
+            auto lhs_expr = trans_expr(cx, a);
+            auto lhs_res = autoderef(lhs_expr.bcx, lhs_expr.val,
+                                     ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
             auto rhs_cx = new_scope_block_ctxt(cx, "rhs");
-            auto rhs_res = trans_expr(rhs_cx, b);
-            rhs_res =
-                autoderef(rhs_res.bcx, rhs_res.val,
-                          ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
+            auto rhs_expr = trans_expr(rhs_cx, b);
+            auto rhs_res = autoderef(rhs_expr.bcx, rhs_expr.val,
+                                     ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
             auto lhs_true_cx = new_scope_block_ctxt(cx, "lhs true");
             auto lhs_true_res = rslt(lhs_true_cx, C_bool(true));
             // see the and case for an explanation
@@ -4187,19 +4216,19 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
             lhs_res.bcx.build.CondBr(lhs_res.val, lhs_true_cx.llbb,
                                      rhs_cx.llbb);
             ret join_results(cx, T_bool(),
-                             [lhs_true_res, rec(bcx=rhs_bcx with rhs_res)]);
+                             [lhs_true_res, rec(bcx=rhs_bcx,
+                                                val=rhs_res.val)]);
         }
         case (_) {
             // Remaining cases are eager:
 
-            auto lhs = trans_expr(cx, a);
+            auto lhs_expr = trans_expr(cx, a);
             auto lhty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, a);
-            lhs = autoderef(lhs.bcx, lhs.val, lhty);
-            auto rhs = trans_expr(lhs.bcx, b);
+            auto lhs = autoderef(lhs_expr.bcx, lhs_expr.val, lhty);
+            auto rhs_expr = trans_expr(lhs.bcx, b);
             auto rhty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, b);
-            rhs = autoderef(rhs.bcx, rhs.val, rhty);
-            ret trans_eager_binop(rhs.bcx, op,
-                                  autoderefed_ty(cx.fcx.lcx.ccx, lhty),
+            auto rhs = autoderef(rhs_expr.bcx, rhs_expr.val, rhty);
+            ret trans_eager_binop(rhs.bcx, op, lhs.ty,
                                   lhs.val, rhs.val);
         }
     }
@@ -4600,45 +4629,54 @@ fn trans_do_while(&@block_ctxt cx, &ast::block body, &@ast::expr cond) ->
 fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
                    &@block_ctxt next_cx) -> result {
     alt (pat.node) {
-        case (ast::pat_wild(_)) { ret rslt(cx, llval); }
-        case (ast::pat_bind(_, _)) { ret rslt(cx, llval); }
-        case (ast::pat_lit(?lt, ?id)) {
-            auto lllit = trans_lit(cx.fcx.lcx.ccx, *lt, id);
-            auto lltype = ty::node_id_to_type(cx.fcx.lcx.ccx.tcx, id);
+        case (ast::pat_wild) { ret rslt(cx, llval); }
+        case (ast::pat_bind(_)) { ret rslt(cx, llval); }
+        case (ast::pat_lit(?lt)) {
+            auto lllit = trans_lit(cx.fcx.lcx.ccx, *lt, pat.id);
+            auto lltype = ty::node_id_to_type(cx.fcx.lcx.ccx.tcx, pat.id);
             auto lleq = trans_compare(cx, ast::eq, lltype, llval, lllit);
             auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx");
             lleq.bcx.build.CondBr(lleq.val, matched_cx.llbb, next_cx.llbb);
             ret rslt(matched_cx, llval);
         }
-        case (ast::pat_tag(?ident, ?subpats, ?id)) {
-            auto lltagptr =
-                cx.build.PointerCast(llval,
-                                     T_opaque_tag_ptr(cx.fcx.lcx.ccx.tn));
-            auto lldiscrimptr = cx.build.GEP(lltagptr, [C_int(0), C_int(0)]);
-            auto lldiscrim = cx.build.Load(lldiscrimptr);
+        case (ast::pat_tag(?ident, ?subpats)) {
             auto vdef =
-                ast::variant_def_ids(cx.fcx.lcx.ccx.tcx.def_map.get(id));
-            auto variant_tag = 0;
+                ast::variant_def_ids(cx.fcx.lcx.ccx.tcx.def_map.get(pat.id));
             auto variants = ty::tag_variants(cx.fcx.lcx.ccx.tcx, vdef._0);
-            auto i = 0;
-            for (ty::variant_info v in variants) {
-                auto this_variant_id = v.id;
-                if (vdef._1._0 == this_variant_id._0 &&
+            auto matched_cx = new_sub_block_ctxt(cx, "matched_cx");
+            auto llblobptr = llval;
+
+            if (vec::len(variants) == 1u) {
+                cx.build.Br(matched_cx.llbb);
+            } else {
+                auto lltagptr =
+                    cx.build.PointerCast(llval,
+                                         T_opaque_tag_ptr(cx.fcx.lcx.ccx.tn));
+                auto lldiscrimptr = cx.build.GEP(lltagptr,
+                                                 [C_int(0), C_int(0)]);
+                auto lldiscrim = cx.build.Load(lldiscrimptr);
+                auto variant_tag = 0;
+                auto i = 0;
+                for (ty::variant_info v in variants) {
+                    auto this_variant_id = v.id;
+                    if (vdef._1._0 == this_variant_id._0 &&
                         vdef._1._1 == this_variant_id._1) {
-                    variant_tag = i;
+                        variant_tag = i;
+                    }
+                    i += 1;
+                }
+                auto lleq =
+                    cx.build.ICmp(lib::llvm::LLVMIntEQ, lldiscrim,
+                                  C_int(variant_tag));
+                cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
+                if (vec::len(subpats) > 0u) {
+                    llblobptr =
+                        matched_cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
                 }
-                i += 1;
             }
-            auto matched_cx = new_sub_block_ctxt(cx, "matched_cx");
-            auto lleq =
-                cx.build.ICmp(lib::llvm::LLVMIntEQ, lldiscrim,
-                              C_int(variant_tag));
-            cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
             auto ty_params = ty::node_id_to_type_params
-                (cx.fcx.lcx.ccx.tcx, id);
-            if (vec::len[@ast::pat](subpats) > 0u) {
-                auto llblobptr =
-                    matched_cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
+                (cx.fcx.lcx.ccx.tcx, pat.id);
+            if (vec::len(subpats) > 0u) {
                 auto i = 0;
                 for (@ast::pat subpat in subpats) {
                     auto rslt =
@@ -4664,35 +4702,37 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
 fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
                      bool bind_alias) -> result {
     alt (pat.node) {
-        case (ast::pat_wild(_)) { ret rslt(cx, llval); }
-        case (ast::pat_lit(_, _)) { ret rslt(cx, llval); }
-        case (ast::pat_bind(?name, ?id)) {
+        case (ast::pat_wild) { ret rslt(cx, llval); }
+        case (ast::pat_lit(_)) { ret rslt(cx, llval); }
+        case (ast::pat_bind(?name)) {
             if (bind_alias) {
-                cx.fcx.lllocals.insert(id, llval);
+                cx.fcx.lllocals.insert(pat.id, llval);
                 ret rslt(cx, llval);
             } else {
-                auto t = node_id_type(cx.fcx.lcx.ccx, id);
+                auto t = node_id_type(cx.fcx.lcx.ccx, pat.id);
                 auto rslt = alloc_ty(cx, t);
                 auto dst = rslt.val;
                 auto bcx = rslt.bcx;
                 maybe_name_value(cx.fcx.lcx.ccx, dst, name);
-                bcx.fcx.lllocals.insert(id, dst);
+                bcx.fcx.lllocals.insert(pat.id, dst);
                 bcx.cleanups += [clean(bind drop_slot(_, dst, t))];
                 ret copy_val(bcx, INIT, dst, llval, t);
             }
         }
-        case (ast::pat_tag(_, ?subpats, ?id)) {
+        case (ast::pat_tag(_, ?subpats)) {
             if (vec::len[@ast::pat](subpats) == 0u) { ret rslt(cx, llval); }
             // Get the appropriate variant for this tag.
 
             auto vdef =
-                ast::variant_def_ids(cx.fcx.lcx.ccx.tcx.def_map.get(id));
-            auto lltagptr =
-                cx.build.PointerCast(llval,
-                                     T_opaque_tag_ptr(cx.fcx.lcx.ccx.tn));
-            auto llblobptr = cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
+                ast::variant_def_ids(cx.fcx.lcx.ccx.tcx.def_map.get(pat.id));
+            auto llblobptr = llval;
+            if (vec::len(ty::tag_variants(cx.fcx.lcx.ccx.tcx, vdef._0))!=1u) {
+                auto lltagptr = cx.build.PointerCast
+                    (llval, T_opaque_tag_ptr(cx.fcx.lcx.ccx.tn));
+                llblobptr = cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
+            }
             auto ty_param_substs =
-                ty::node_id_to_type_params(cx.fcx.lcx.ccx.tcx, id);
+                ty::node_id_to_type_params(cx.fcx.lcx.ccx.tcx, pat.id);
             auto this_cx = cx;
             auto i = 0;
             for (@ast::pat subpat in subpats) {
@@ -4825,6 +4865,7 @@ fn lookup_discriminant(&@local_ctxt lcx, &ast::def_id tid, &ast::def_id vid)
 }
 
 fn trans_path(&@block_ctxt cx, &ast::path p, ast::node_id id) -> lval_result {
+    auto ccx = cx.fcx.lcx.ccx;
     alt (cx.fcx.lcx.ccx.tcx.def_map.get(id)) {
         case (ast::def_arg(?did)) {
             alt (cx.fcx.llargs.find(did._1)) {
@@ -4853,12 +4894,12 @@ fn trans_path(&@block_ctxt cx, &ast::path p, ast::node_id id) -> lval_result {
             ret lval_mem(cx, cx.fcx.llobjfields.get(did._1));
         }
         case (ast::def_fn(?did, _)) {
-            auto tyt = ty::lookup_item_type(cx.fcx.lcx.ccx.tcx, did);
+            auto tyt = ty::lookup_item_type(ccx.tcx, did);
             ret lval_generic_fn(cx, tyt, did, id);
         }
         case (ast::def_variant(?tid, ?vid)) {
-            auto v_tyt = ty::lookup_item_type(cx.fcx.lcx.ccx.tcx, vid);
-            alt (ty::struct(cx.fcx.lcx.ccx.tcx, v_tyt._1)) {
+            auto v_tyt = ty::lookup_item_type(ccx.tcx, vid);
+            alt (ty::struct(ccx.tcx, v_tyt._1)) {
                 case (ty::ty_fn(_, _, _, _, _)) {
                     // N-ary variant.
 
@@ -4866,43 +4907,36 @@ fn trans_path(&@block_ctxt cx, &ast::path p, ast::node_id id) -> lval_result {
                 }
                 case (_) {
                     // Nullary variant.
-
-                    auto tag_ty = node_id_type(cx.fcx.lcx.ccx, id);
-                    auto lldiscrim_gv =
-                        lookup_discriminant(cx.fcx.lcx, tid, vid);
-                    auto lldiscrim = cx.build.Load(lldiscrim_gv);
+                    auto tag_ty = node_id_type(ccx, id);
                     auto alloc_result = alloc_ty(cx, tag_ty);
                     auto lltagblob = alloc_result.val;
-                    auto lltagty;
-                    if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, tag_ty))
-                       {
-                        lltagty = T_opaque_tag(cx.fcx.lcx.ccx.tn);
-                    } else {
-                        lltagty = type_of(cx.fcx.lcx.ccx, p.span, tag_ty);
+                    auto lltagty = type_of_tag(ccx, p.span, tid, tag_ty);
+                    auto bcx = alloc_result.bcx;
+                    auto lltagptr = bcx.build.PointerCast
+                        (lltagblob, T_ptr(lltagty));
+                    if (vec::len(ty::tag_variants(ccx.tcx, tid)) != 1u) {
+                        auto lldiscrim_gv =
+                            lookup_discriminant(bcx.fcx.lcx, tid, vid);
+                        auto lldiscrim = bcx.build.Load(lldiscrim_gv);
+                        auto lldiscrimptr = bcx.build.GEP
+                            (lltagptr, [C_int(0), C_int(0)]);
+                        bcx.build.Store(lldiscrim, lldiscrimptr);
                     }
-                    auto lltagptr =
-                        alloc_result.bcx.build.PointerCast(lltagblob,
-                                                           T_ptr(lltagty));
-                    auto lldiscrimptr =
-                        alloc_result.bcx.build.GEP(lltagptr,
-                                                   [C_int(0), C_int(0)]);
-                    alloc_result.bcx.build.Store(lldiscrim, lldiscrimptr);
-                    ret lval_val(alloc_result.bcx, lltagptr);
+                    ret lval_val(bcx, lltagptr);
                 }
             }
         }
         case (ast::def_const(?did)) {
             // TODO: externals
-
-            assert (cx.fcx.lcx.ccx.consts.contains_key(did._1));
-            ret lval_mem(cx, cx.fcx.lcx.ccx.consts.get(did._1));
+            assert (ccx.consts.contains_key(did._1));
+            ret lval_mem(cx, ccx.consts.get(did._1));
         }
         case (ast::def_native_fn(?did)) {
-            auto tyt = ty::lookup_item_type(cx.fcx.lcx.ccx.tcx, did);
+            auto tyt = ty::lookup_item_type(ccx.tcx, did);
             ret lval_generic_fn(cx, tyt, did, id);
         }
         case (_) {
-            cx.fcx.lcx.ccx.sess.span_unimpl(cx.sp, "def variant in trans");
+            ccx.sess.span_unimpl(cx.sp, "def variant in trans");
         }
     }
 }
@@ -4910,7 +4944,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, ast::node_id id) -> lval_result {
 fn trans_field(&@block_ctxt cx, &span sp, ValueRef v, &ty::t t0,
                &ast::ident field, ast::node_id id) -> lval_result {
     auto r = autoderef(cx, v, t0);
-    auto t = autoderefed_ty(cx.fcx.lcx.ccx, t0);
+    auto t = r.ty;
     alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
         case (ty::ty_tup(_)) {
             let uint ix = ty::field_num(cx.fcx.lcx.ccx.sess, sp, field);
@@ -4950,11 +4984,11 @@ fn trans_index(&@block_ctxt cx, &span sp, &@ast::expr base, &@ast::expr idx,
     // Is this an interior vector?
 
     auto base_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, base);
-    auto base_ty_no_boxes = ty::strip_boxes(cx.fcx.lcx.ccx.tcx, base_ty);
+    auto exp = trans_expr(cx, base);
+    auto lv = autoderef(exp.bcx, exp.val, base_ty);
+    auto base_ty_no_boxes = lv.ty;
     auto is_interior =
         ty::sequence_is_interior(cx.fcx.lcx.ccx.tcx, base_ty_no_boxes);
-    auto lv = trans_expr(cx, base);
-    lv = autoderef(lv.bcx, lv.val, base_ty);
     auto ix = trans_expr(lv.bcx, idx);
     auto v = lv.val;
     auto bcx = ix.bcx;
@@ -5035,14 +5069,29 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
             ret trans_index(cx, e.span, base, idx, e.id);
         }
         case (ast::expr_unary(?unop, ?base)) {
+            auto ccx = cx.fcx.lcx.ccx;
             assert (unop == ast::deref);
             auto sub = trans_expr(cx, base);
-            auto t = ty::expr_ty(cx.fcx.lcx.ccx.tcx, base);
-            auto offset = alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
-                case (ty::ty_box(_)) { abi::box_rc_field_body }
-                case (ty::ty_res(_, _, _)) { 1 }
+            auto t = ty::expr_ty(ccx.tcx, base);
+            auto val = alt (ty::struct(ccx.tcx, t)) {
+                case (ty::ty_box(_)) {
+                    sub.bcx.build.GEP
+                    (sub.val, [C_int(0), C_int(abi::box_rc_field_body)])
+                }
+                case (ty::ty_res(_, _, _)) {
+                    sub.bcx.build.GEP(sub.val, [C_int(0), C_int(1)])
+                }
+                case (ty::ty_tag(_, _)) {
+                    auto ety = ty::expr_ty(ccx.tcx, e);
+                    auto ellty;
+                    if (ty::type_has_dynamic_size(ccx.tcx, ety)) {
+                        ellty = T_typaram_ptr(ccx.tn);
+                    } else {
+                        ellty = T_ptr(type_of(ccx, e.span, ety));
+                    };
+                    sub.bcx.build.PointerCast(sub.val, ellty)
+                }
             };
-            auto val = sub.bcx.build.GEP(sub.val, [C_int(0), C_int(offset)]);
             ret lval_mem(sub.bcx, val);
         }
         case (ast::expr_self_method(?ident)) {
@@ -5515,9 +5564,10 @@ fn trans_arg_expr(&@block_ctxt cx, &ty::arg arg, TypeRef lldestty0,
             val = do_spill(lv.res.bcx, lv.res.val);
         }
     } else { auto re = trans_expr(bcx, e); val = re.val; bcx = re.bcx; }
+    auto is_bot = ty::type_is_bot(cx.fcx.lcx.ccx.tcx, e_ty);
 
     // Make a copy here if the type is structural and we're passing by value.
-    if (arg.mode == ty::mo_val) {
+    if (arg.mode == ty::mo_val && !is_bot) {
         if (ty::type_owns_heap_mem(cx.fcx.lcx.ccx.tcx, e_ty)) {
             auto rslt = alloc_ty(bcx, e_ty);
             bcx = rslt.bcx;
@@ -5530,12 +5580,11 @@ fn trans_arg_expr(&@block_ctxt cx, &ty::arg arg, TypeRef lldestty0,
         }
     }
 
-    if (ty::type_is_bot(cx.fcx.lcx.ccx.tcx, e_ty)) {
+    if (is_bot) {
         // For values of type _|_, we generate an
         // "undef" value, as such a value should never
         // be inspected. It's important for the value
         // to have type lldestty0 (the callee's expected type).
-
         val = llvm::LLVMGetUndef(lldestty0);
     } else if (ty::type_contains_params(cx.fcx.lcx.ccx.tcx, arg.ty)) {
         auto lldestty = lldestty0;
@@ -5633,6 +5682,11 @@ fn trans_args(&@block_ctxt cx, ValueRef llenv, &option::t[ValueRef] llobj,
     auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, cx.sp, args);
     auto i = 0u;
     for (@ast::expr e in es) {
+        if (bcx.build.is_terminated()) {
+            // This means an earlier arg was divergent.
+            // So this arg can't be evaluated.
+            break;
+        }
         auto r = trans_arg_expr(bcx, args.(i), arg_tys.(i), e);
         bcx = r.bcx;
         llargs += [r.val];
@@ -5648,17 +5702,33 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
     // with trans_call.
 
     auto f_res = trans_lval(cx, f);
+    let ty::t fn_ty;
+    alt (f_res.method_ty) {
+        case (some(?meth)) {
+            // self-call
+            fn_ty = meth;
+        }
+        case (_) {
+            fn_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, f);
+        }
+    }
+
+    auto bcx = f_res.res.bcx;
+
     auto faddr = f_res.res.val;
     auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.lcx.ccx.tn));
     alt (f_res.llobj) {
         case (some(_)) {
             // It's a vtbl entry.
-            faddr = f_res.res.bcx.build.Load(faddr);
+            faddr = bcx.build.Load(faddr);
         }
         case (none) {
-            // It's a closure.
-            auto bcx = f_res.res.bcx;
-            auto pair = faddr;
+            // It's a closure. We have to autoderef.
+            auto res = autoderef_lval(bcx, f_res.res.val, fn_ty, true);
+            bcx = res.bcx;
+            fn_ty = res.ty;
+
+            auto pair = res.val;
             faddr =
                 bcx.build.GEP(pair, [C_int(0), C_int(abi::fn_field_code)]);
             faddr = bcx.build.Load(faddr);
@@ -5667,19 +5737,12 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
             llenv = bcx.build.Load(llclosure);
         }
     }
-    let ty::t fn_ty;
-    alt (f_res.method_ty) {
-        case (some(?meth)) {
-            // self-call
-            fn_ty = meth;
-        }
-        case (_) { fn_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, f); }
-    }
+
     auto ret_ty = ty::node_id_to_type(cx.fcx.lcx.ccx.tcx, id);
     auto args_res =
-        trans_args(f_res.res.bcx, llenv, f_res.llobj, f_res.generic,
+        trans_args(bcx, llenv, f_res.llobj, f_res.generic,
                    lliterbody, args, fn_ty);
-    auto bcx = args_res._0;
+    bcx = args_res._0;
     auto llargs = args_res._1;
     auto llretslot = args_res._2;
     /*
@@ -5690,25 +5753,30 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
     }
     */
 
-    bcx.build.FastCall(faddr, llargs);
+    /* If the block is terminated,
+       then one or more of the args has
+       type _|_. Since that means it diverges, the code
+       for the call itself is unreachable. */
     auto retval = C_nil();
-    alt (lliterbody) {
-        case (none) {
-            if (!ty::type_is_nil(cx.fcx.lcx.ccx.tcx, ret_ty)) {
-                retval = load_if_immediate(bcx, llretslot, ret_ty);
-                // Retval doesn't correspond to anything really tangible in
-                // the frame, but it's a ref all the same, so we put a note
-                // here to drop it when we're done in this scope.
-
-                find_scope_cx(cx).cleanups +=
-                    [clean(bind drop_ty(_, retval, ret_ty))];
+    if (!bcx.build.is_terminated()) {
+        bcx.build.FastCall(faddr, llargs);
+        alt (lliterbody) {
+            case (none) {
+                if (!ty::type_is_nil(cx.fcx.lcx.ccx.tcx, ret_ty)) {
+                    retval = load_if_immediate(bcx, llretslot, ret_ty);
+                    // Retval doesn't correspond to anything really tangible
+                    // in the frame, but it's a ref all the same, so we put a
+                    // note here to drop it when we're done in this scope.
+                    
+                    find_scope_cx(cx).cleanups +=
+                        [clean(bind drop_ty(_, retval, ret_ty))];
+                }
+            }
+            case (some(_)) {
+                // If there was an lliterbody, it means we were calling an
+                // iter, and we are *not* the party using its 'output' value,
+                // we should ignore llretslot.
             }
-        }
-        case (some(_)) {
-            // If there was an lliterbody, it means we were calling an
-            // iter, and we are *not* the party using its 'output' value,
-            // we should ignore llretslot.
-
         }
     }
     ret rslt(bcx, retval);
@@ -6100,13 +6168,8 @@ fn trans_expr_out(&@block_ctxt cx, &@ast::expr e, out_method output) ->
         case (ast::expr_ext(_, _, _, ?expanded)) {
             ret trans_expr(cx, expanded);
         }
-        case (ast::expr_fail(?str)) {
-            auto failmsg;
-            alt (str) {
-                case (some(?msg)) { failmsg = msg; }
-                case (_) { failmsg = "explicit failure"; }
-            }
-            ret trans_fail(cx, some(e.span), failmsg);
+        case (ast::expr_fail(?expr)) {
+            ret trans_fail_expr(cx, some(e.span), expr);
         }
         case (ast::expr_log(?lvl, ?a)) { ret trans_log(lvl, cx, a); }
         case (ast::expr_assert(?a)) {
@@ -6309,9 +6372,42 @@ fn trans_check_expr(&@block_ctxt cx, &@ast::expr e, &str s) -> result {
     ret rslt(next_cx, C_nil());
 }
 
+fn trans_fail_expr(&@block_ctxt cx, &option::t[common::span] sp_opt,
+                   &option::t[@ast::expr] fail_expr)
+        -> result {
+    auto bcx = cx;
+    alt (fail_expr) {
+        case (some(?expr)) {
+            auto tcx = bcx.fcx.lcx.ccx.tcx;
+            auto expr_res = trans_expr(bcx, expr);
+            auto e_ty = ty::expr_ty(tcx, expr);
+            bcx = expr_res.bcx;
+
+            if (ty::type_is_str(tcx, e_ty)) {
+                auto elt = bcx.build.GEP(expr_res.val,
+                                        [C_int(0), C_int(abi::vec_elt_data)]);
+                ret trans_fail_value(bcx, sp_opt, elt);
+            } else {
+                cx.fcx.lcx.ccx.sess.span_bug(expr.span,
+                                             "fail called with unsupported \
+                                              type " + ty_to_str(tcx, e_ty));
+            }
+        }
+        case (_) {
+            ret trans_fail(bcx, sp_opt, "explicit failure");
+        }
+    }
+}
 fn trans_fail(&@block_ctxt cx, &option::t[common::span] sp_opt, &str fail_str)
    -> result {
     auto V_fail_str = C_cstr(cx.fcx.lcx.ccx, fail_str);
+    ret trans_fail_value(cx, sp_opt, V_fail_str);
+}
+
+fn trans_fail_value(&@block_ctxt cx, &option::t[common::span] sp_opt,
+                    &ValueRef V_fail_str)
+        -> result {
     auto V_filename;
     auto V_line;
     alt (sp_opt) {
@@ -6325,9 +6421,9 @@ fn trans_fail(&@block_ctxt cx, &option::t[common::span] sp_opt, &str fail_str)
             V_line = 0;
         }
     }
-    V_fail_str = cx.build.PointerCast(V_fail_str, T_ptr(T_i8()));
+    auto V_str = cx.build.PointerCast(V_fail_str, T_ptr(T_i8()));
     V_filename = cx.build.PointerCast(V_filename, T_ptr(T_i8()));
-    auto args = [cx.fcx.lltaskptr, V_fail_str, V_filename, C_int(V_line)];
+    auto args = [cx.fcx.lltaskptr, V_str, V_filename, C_int(V_line)];
     cx.build.Call(cx.fcx.lcx.ccx.upcalls._fail, args);
     cx.build.Unreachable();
     ret rslt(cx, C_nil());
@@ -7908,7 +8004,7 @@ fn trans_res_ctor(@local_ctxt cx, &span sp, &ast::_fn dtor,
 
 
 fn trans_tag_variant(@local_ctxt cx, ast::node_id tag_id,
-                     &ast::variant variant, int index,
+                     &ast::variant variant, int index, bool is_degen,
                      &vec[ast::ty_param] ty_params) {
     if (vec::len[ast::variant_arg](variant.node.args) == 0u) {
         ret; // nullary constructors are just constants
@@ -7941,13 +8037,17 @@ fn trans_tag_variant(@local_ctxt cx, ast::node_id tag_id,
     copy_args_to_allocas(fcx, fn_args, arg_tys);
     auto bcx = new_top_block_ctxt(fcx);
     auto lltop = bcx.llbb;
-    // Cast the tag to a type we can GEP into.
 
-    auto lltagptr =
-        bcx.build.PointerCast(fcx.llretptr, T_opaque_tag_ptr(fcx.lcx.ccx.tn));
-    auto lldiscrimptr = bcx.build.GEP(lltagptr, [C_int(0), C_int(0)]);
-    bcx.build.Store(C_int(index), lldiscrimptr);
-    auto llblobptr = bcx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
+    auto llblobptr = if (is_degen) {
+        fcx.llretptr
+    } else {
+        // Cast the tag to a type we can GEP into.
+        auto lltagptr = bcx.build.PointerCast
+            (fcx.llretptr, T_opaque_tag_ptr(fcx.lcx.ccx.tn));
+        auto lldiscrimptr = bcx.build.GEP(lltagptr, [C_int(0), C_int(0)]);
+        bcx.build.Store(C_int(index), lldiscrimptr);
+        bcx.build.GEP(lltagptr, [C_int(0), C_int(1)])
+    };
     i = 0u;
     for (ast::variant_arg va in variant.node.args) {
         auto rslt =
@@ -8028,9 +8128,10 @@ fn trans_item(@local_ctxt cx, &ast::item item) {
         }
         case (ast::item_tag(?variants, ?tps)) {
             auto sub_cx = extend_path(cx, item.ident);
+            auto degen = vec::len(variants) == 1u;
             auto i = 0;
             for (ast::variant variant in variants) {
-                trans_tag_variant(sub_cx, item.id, variant, i, tps);
+                trans_tag_variant(sub_cx, item.id, variant, i, degen, tps);
                 i += 1;
             }
         }
@@ -8415,13 +8516,14 @@ fn trans_constant(@crate_ctxt ccx, &@ast::item it, &vec[str] pt,
             auto n_variants = vec::len[ast::variant](variants);
             while (i < n_variants) {
                 auto variant = variants.(i);
-                auto discrim_val = C_int(i as int);
                 auto p = new_pt + [it.ident, variant.node.name, "discrim"];
                 auto s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
                 auto discrim_gvar =
                     llvm::LLVMAddGlobal(ccx.llmod, T_int(), str::buf(s));
-                llvm::LLVMSetInitializer(discrim_gvar, discrim_val);
-                llvm::LLVMSetGlobalConstant(discrim_gvar, True);
+                if (n_variants != 1u) {
+                    llvm::LLVMSetInitializer(discrim_gvar, C_int(i as int));
+                    llvm::LLVMSetGlobalConstant(discrim_gvar, True);
+                }
                 ccx.discrims.insert(variant.node.id, discrim_gvar);
                 ccx.discrim_symbols.insert(variant.node.id, s);
                 i += 1u;
index ee056f8ddb63f47913209c3e6d09d91cebd4e132..25d6fb98a92b40527fc72dd4ccf3f5abdba1e794 100644 (file)
@@ -529,11 +529,19 @@ fn combine_pp(pre_and_post antec, fn_ctxt fcx, &pre_and_post pp,
             find_pre_post_expr(fcx, operator);
             copy_pre_post(fcx.ccx, e.id, operator);
         }
-        case (expr_fail(_)) {
+        case (expr_fail(?maybe_val)) {
+            auto prestate;
+            alt (maybe_val) {
+                case (none) { prestate = empty_prestate(num_local_vars); }
+                case (some(?fail_val)) {
+                    find_pre_post_expr(fcx, fail_val);
+                    prestate = expr_precond(fcx.ccx, fail_val);
+                }
+            }
             set_pre_and_post(fcx.ccx, e.id,
                              /* if execution continues after fail,
                                 then everything is true! */
-                             empty_prestate(num_local_vars),
+                             prestate,
                              false_postcond(num_local_vars));
         }
         case (expr_assert(?p)) {
index dc64f64e6dfdc65b479578a3f120c5bfa44bbecb..4e4c3a961d7d54b4d36c9694095be1e63e1cd8b0 100644 (file)
@@ -543,12 +543,18 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool {
         case (expr_cast(?operand, _)) {
             ret find_pre_post_state_sub(fcx, pres, operand, e.id, none);
         }
-        case (expr_fail(_)) {
+        case (expr_fail(?maybe_fail_val)) {
             ret set_prestate_ann(fcx.ccx, e.id, pres) |
             /* if execution continues after fail, then everything is true!
                woo! */
                 set_poststate_ann(fcx.ccx, e.id,
-                                  false_postcond(num_constrs));
+                                  false_postcond(num_constrs)) |
+                alt(maybe_fail_val) {
+                    case (none) { false }
+                    case (some(?fail_val)) {
+                        find_pre_post_state_expr(fcx, pres, fail_val)
+                    }
+                }
         }
         case (expr_assert(?p)) {
             ret find_pre_post_state_sub(fcx, pres, p, e.id, none);
index 5022a1cb2e27614ac4c07f5c9a70c648aae414fb..254fd130681bef9412824ee15c024363d3bac864 100644 (file)
@@ -18,6 +18,7 @@
 import front::ast::constr_arg_general;
 import front::ast::mutability;
 import front::ast::controlflow;
+import front::ast::path_to_str;
 import metadata::creader;
 import metadata::decoder;
 import util::common::*;
 export mo_alias;
 export mt;
 export node_type_table;
-export pat_node_id;
 export pat_ty;
 export cname;
-export path_to_str;
 export rename;
 export ret_ty_of_fn;
 export ret_ty_of_fn_ty;
 export struct;
 export sort_methods;
 export stmt_node_id;
-export strip_boxes;
 export sty;
 export substitute_type_params;
 export t;
 export type_is_tup_like;
 export type_is_str;
 export type_owns_heap_mem;
+export type_autoderef;
 export type_param;
 export def_to_str;
 export unify;
@@ -273,7 +272,7 @@ fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
     ty_var(int); // type variable
     ty_param(uint); // fn/tag type param
     ty_type;
-    ty_native;
+    ty_native(def_id);
     // TODO: ty_fn_arg(t), for a possibly-aliased function argument
 }
 
@@ -342,13 +341,11 @@ fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
 
 const uint idx_task = 18u;
 
-const uint idx_native = 19u;
+const uint idx_type = 19u;
 
-const uint idx_type = 20u;
+const uint idx_bot = 20u;
 
-const uint idx_bot = 21u;
-
-const uint idx_first_others = 22u;
+const uint idx_first_others = 21u;
 
 type type_store = interner::interner[raw_t];
 
@@ -377,7 +374,6 @@ fn populate_type_store(&ctxt cx) {
     intern(cx, ty_str, none[str]);
     intern(cx, ty_istr, none[str]);
     intern(cx, ty_task, none[str]);
-    intern(cx, ty_native, none[str]);
     intern(cx, ty_type, none[str]);
     intern(cx, ty_bot, none[str]);
     assert (vec::len(cx.ts.vect) == idx_first_others);
@@ -462,7 +458,7 @@ fn derive_flags_sig(&ctxt cx, &mutable bool has_params,
         case (ty_istr) {/* no-op */ }
         case (ty_task) {/* no-op */ }
         case (ty_type) {/* no-op */ }
-        case (ty_native) {/* no-op */ }
+        case (ty_native(_)) {/* no-op */ }
         case (ty_param(_)) { has_params = true; }
         case (ty_var(_)) { has_vars = true; }
         case (ty_tag(_, ?tys)) {
@@ -620,7 +616,7 @@ fn mk_res(&ctxt cx, &ast::def_id did, &t inner, &vec[t] tps) -> t {
 
 fn mk_type(&ctxt cx) -> t { ret idx_type; }
 
-fn mk_native(&ctxt cx) -> t { ret idx_native; }
+fn mk_native(&ctxt cx, &def_id did) -> t { ret gen_ty(cx, ty_native(did)); }
 
 
 // Returns the one-level-deep type structure of the given type.
@@ -635,19 +631,6 @@ fn cname(&ctxt cx, &t typ) -> option::t[str] {
 }
 
 
-// Stringification
-fn path_to_str(&ast::path pth) -> str {
-    auto result = str::connect(pth.node.idents, "::");
-    if (vec::len[@ast::ty](pth.node.types) > 0u) {
-        fn f(&@ast::ty t) -> str { ret pretty::pprust::ty_to_str(*t); }
-        result += "[";
-        result += str::connect(vec::map(f, pth.node.types), ",");
-        result += "]";
-    }
-    ret result;
-}
-
-
 // Type folds
 type ty_walk = fn(t) ;
 
@@ -664,7 +647,7 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
         case (ty_str) {/* no-op */ }
         case (ty_istr) {/* no-op */ }
         case (ty_type) {/* no-op */ }
-        case (ty_native) {/* no-op */ }
+        case (ty_native(_)) {/* no-op */ }
         case (ty_box(?tm)) { walk_ty(cx, walker, tm.ty); }
         case (ty_vec(?tm)) { walk_ty(cx, walker, tm.ty); }
         case (ty_ivec(?tm)) { walk_ty(cx, walker, tm.ty); }
@@ -731,7 +714,7 @@ fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
         case (ty_str) {/* no-op */ }
         case (ty_istr) {/* no-op */ }
         case (ty_type) {/* no-op */ }
-        case (ty_native) {/* no-op */ }
+        case (ty_native(_)) {/* no-op */ }
         case (ty_task) {/* no-op */ }
         case (ty_box(?tm)) {
             ty =
@@ -1017,7 +1000,7 @@ fn type_is_scalar(&ctxt cx, &t ty) -> bool {
         case (ty_machine(_)) { ret true; }
         case (ty_char) { ret true; }
         case (ty_type) { ret true; }
-        case (ty_native) { ret true; }
+        case (ty_native(_)) { ret true; }
         case (ty_ptr(_)) { ret true; }
         case (_) { ret false; }
     }
@@ -1041,7 +1024,7 @@ fn type_has_pointers(&ctxt cx, &t ty) -> bool {
         case (ty_machine(_)) { /* no-op */ }
         case (ty_char) { /* no-op */ }
         case (ty_type) { /* no-op */ }
-        case (ty_native) { /* no-op */ }
+        case (ty_native(_)) { /* no-op */ }
         case (ty_tup(?elts)) {
             for (mt m in elts) {
                 if (type_has_pointers(cx, m.ty)) { result = true; }
@@ -1082,7 +1065,7 @@ fn type_has_pointers(&ctxt cx, &t ty) -> bool {
 // type_is_scalar?
 fn type_is_native(&ctxt cx, &t ty) -> bool {
     alt (struct(cx, ty)) {
-        case (ty_native) { ret true; }
+        case (ty_native(_)) { ret true; }
         case (_) { ret false; }
     }
 }
@@ -1142,7 +1125,7 @@ fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
         case (ty_var(_)) { fail "ty_var in type_has_dynamic_size()"; }
         case (ty_param(_)) { ret true; }
         case (ty_type) { ret false; }
-        case (ty_native) { ret false; }
+        case (ty_native(_)) { ret false; }
     }
 }
 
@@ -1219,7 +1202,7 @@ fn type_owns_heap_mem(&ctxt cx, &t ty) -> bool {
         case (ty_machine(_)) { result = false; }
         case (ty_char) { result = false; }
         case (ty_type) { result = false; }
-        case (ty_native) { result = false; }
+        case (ty_native(_)) { result = false; }
 
         // boxed types
         case (ty_str) { result = false; }
@@ -1281,6 +1264,28 @@ fn type_param(&ctxt cx, &t ty) -> option::t[uint] {
     ret none[uint];
 }
 
+fn type_autoderef(&ctxt cx, &ty::t t) -> ty::t {
+    let ty::t t1 = t;
+    while (true) {
+        alt (struct(cx, t1)) {
+            case (ty::ty_box(?mt)) { t1 = mt.ty; }
+            case (ty::ty_res(_, ?inner, ?tps)) {
+                t1 = substitute_type_params(cx, tps, inner);
+            }
+            case (ty::ty_tag(?did, ?tps)) {
+                auto variants = tag_variants(cx, did);
+                if (vec::len(variants) != 1u ||
+                    vec::len(variants.(0).args) != 1u) {
+                    break;
+                }
+                t1 = substitute_type_params(cx, tps, variants.(0).args.(0));
+            }
+            case (_) { break; }
+        }
+    }
+    ret t1;
+}
+
 fn def_to_str(&ast::def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); }
 
 
@@ -1366,7 +1371,7 @@ fn hash_fn(uint id, &arg[] args, &t rty) -> uint {
         case (ty_var(?v)) { ret hash_uint(30u, v as uint); }
         case (ty_param(?pid)) { ret hash_uint(31u, pid); }
         case (ty_type) { ret 32u; }
-        case (ty_native) { ret 33u; }
+        case (ty_native(?did)) { ret hash_def(33u, did); }
         case (ty_bot) { ret 34u; }
         case (ty_ptr(?mt)) { ret hash_subty(35u, mt.ty); }
         case (ty_res(?did, ?sub, ?tps)) {
@@ -1665,8 +1670,12 @@ fn equal_def(&ast::def_id did_a, &ast::def_id did_b) -> bool {
         case (ty_type) {
             alt (b) { case (ty_type) { ret true; } case (_) { ret false; } }
         }
-        case (ty_native) {
-            alt (b) { case (ty_native) { ret true; } case (_) { ret false; } }
+        case (ty_native(?a_id)) {
+            alt (b) {
+                case (ty_native(?b_id)) {
+                    ret a_id._0 == b_id._0 && a_id._1 == b_id._1;
+                }
+                case (_) { ret false; } }
         }
     }
 }
@@ -1840,7 +1849,7 @@ fn block_ty(&ctxt cx, &ast::block b) -> t {
 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
 // doesn't provide type parameter substitutions.
 fn pat_ty(&ctxt cx, &@ast::pat pat) -> t {
-    ret node_id_to_monotype(cx, pat_node_id(pat));
+    ret node_id_to_monotype(cx, pat.id);
 }
 
 
@@ -1878,16 +1887,6 @@ fn stmt_node_id(&@ast::stmt s) -> ast::node_id {
     }
 }
 
-fn pat_node_id(&@ast::pat p) -> ast::node_id {
-    alt (p.node) {
-        case (ast::pat_wild(?id)) { ret id; }
-        case (ast::pat_bind(_, ?id)) { ret id; }
-        case (ast::pat_lit(_, ?id)) { ret id; }
-        case (ast::pat_tag(_, _, ?id)) { ret id; }
-    }
-}
-
-
 // Expression utilities
 fn field_num(&session::session sess, &span sp, &ast::ident id) -> uint {
     let uint accum = 0u;
@@ -2291,9 +2290,8 @@ fn unify_step(&@ctxt cx, &t expected, &t actual) -> result {
         }
         alt (struct(cx.tcx, expected)) {
             case (ty::ty_nil) { ret struct_cmp(cx, expected, actual); }
-            case (
-                 // _|_ unifies with anything
-                 ty::ty_bot) {
+            // _|_ unifies with anything
+            case (ty::ty_bot) {
                 ret ures_ok(actual);
             }
             case (ty::ty_bool) { ret struct_cmp(cx, expected, actual); }
@@ -2305,7 +2303,18 @@ fn unify_step(&@ctxt cx, &t expected, &t actual) -> result {
             case (ty::ty_str) { ret struct_cmp(cx, expected, actual); }
             case (ty::ty_istr) { ret struct_cmp(cx, expected, actual); }
             case (ty::ty_type) { ret struct_cmp(cx, expected, actual); }
-            case (ty::ty_native) { ret struct_cmp(cx, expected, actual); }
+            case (ty::ty_native(?ex_id)) {
+                alt (struct(cx.tcx, actual)) {
+                    case (ty_native(?act_id)) {
+                        if (ex_id._0 == act_id._0 && ex_id._1 == act_id._1) {
+                            ret ures_ok(actual);
+                        } else {
+                            ret ures_err(terr_mismatch);
+                        }
+                    }
+                    case (_) { ret ures_err(terr_mismatch); }
+                }
+            }       
             case (ty::ty_param(_)) { ret struct_cmp(cx, expected, actual); }
             case (ty::ty_tag(?expected_id, ?expected_tps)) {
                 alt (struct(cx.tcx, actual)) {
@@ -2879,7 +2888,7 @@ fn ret_ty_of_fn(ctxt cx, ast::node_id id) -> t {
 
 
 // NB: This function requires that the given type has no variables. So, inside
-// typeck, you should use typeck::strip_boxes() instead.
+// typeck, you should use typeck::do_autoderef() instead.
 fn strip_boxes(&ctxt cx, &ty::t t) -> ty::t {
     auto t1 = t;
     while (true) {
index b9d5860d0e9aef5eab3bc91811409b0c10a36cc6..785393e13c907ba2347d6b41a257f799e41e980c 100644 (file)
@@ -2,6 +2,7 @@
 import front::ast;
 import front::ast::mutability;
 import front::ast::local_def;
+import front::ast::path_to_str;
 import metadata::decoder;
 import driver::session;
 import util::common;
@@ -22,7 +23,6 @@
 import middle::ty::mo_alias;
 import middle::ty::node_type_table;
 import middle::ty::pat_ty;
-import middle::ty::path_to_str;
 import middle::ty::ty_param_substs_opt_and_ty;
 import pretty::ppaux::ty_to_str;
 import middle::ty::ty_param_count_and_ty;
 // Used for ast_ty_to_ty() below.
 type ty_getter = fn(&ast::def_id) -> ty::ty_param_count_and_ty ;
 
+fn lookup_local(&@fn_ctxt fcx, &span sp, ast::node_id id) -> int {
+    alt (fcx.locals.find(id)) {
+        case (some(?x)) { x }
+        case (_) {
+            fcx.ccx.tcx.sess.span_fatal(sp, "internal error looking up a \
+              local var")
+        }
+    }
+}
+
+fn lookup_def(&@fn_ctxt fcx, &span sp, ast::node_id id) -> ast::def {
+    alt (fcx.ccx.tcx.def_map.find(id)) {
+        case (some(?x)) { x }
+        case (_) {
+            fcx.ccx.tcx.sess.span_fatal(sp, "internal error looking up \
+              a definition")
+        }
+    }
+}
 
 // Returns the type parameter count and the type for the given definition.
 fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn) ->
@@ -76,17 +95,18 @@ fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn) ->
     alt (defn) {
         case (ast::def_arg(?id)) {
             assert (fcx.locals.contains_key(id._1));
-            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id._1));
+            auto typ = ty::mk_var(fcx.ccx.tcx, 
+                                  lookup_local(fcx, sp, id._1));
             ret tup(0u, typ);
         }
         case (ast::def_local(?id)) {
             assert (fcx.locals.contains_key(id._1));
-            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id._1));
+            auto typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id._1));
             ret tup(0u, typ);
         }
         case (ast::def_obj_field(?id)) {
             assert (fcx.locals.contains_key(id._1));
-            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id._1));
+            auto typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id._1));
             ret tup(0u, typ);
         }
         case (ast::def_fn(?id, _)) {
@@ -103,7 +123,7 @@ fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn) ->
         }
         case (ast::def_binding(?id)) {
             assert (fcx.locals.contains_key(id._1));
-            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id._1));
+            auto typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id._1));
             ret tup(0u, typ);
         }
         case (ast::def_mod(_)) {
@@ -320,18 +340,24 @@ fn instantiate(&ty::ctxt tcx, &span sp, &ty_getter getter,
             typ = ty::mk_fn(tcx, proto, i, out_ty, cf, out_constrs);
         }
         case (ast::ty_path(?path, ?id)) {
-            alt (tcx.def_map.get(id)) {
-                case (ast::def_ty(?id)) {
+            alt (tcx.def_map.find(id)) {
+                case (some(ast::def_ty(?id))) {
                     typ =
                         instantiate(tcx, ast_ty.span, getter, id,
                                     path.node.types);
                 }
-                case (ast::def_native_ty(?id)) { typ = getter(id)._1; }
-                case (ast::def_ty_arg(?id)) { typ = ty::mk_param(tcx, id); }
-                case (_) {
+                case (some(ast::def_native_ty(?id))) { typ = getter(id)._1; }
+                case (some(ast::def_ty_arg(?id))) {
+                    typ = ty::mk_param(tcx, id);
+                }
+                case (some(_)) {
                     tcx.sess.span_fatal(ast_ty.span,
                                       "found type name used as a variable");
                 }
+                case (_) {
+                    tcx.sess.span_fatal(ast_ty.span,
+                                       "internal error in instantiate");
+                }
             }
             cname = some(path_to_str(path));
         }
@@ -499,14 +525,20 @@ fn getter(@ctxt cx, &ast::def_id id) -> ty::ty_param_count_and_ty {
 
             ret decoder::get_type(cx.tcx, id);
         }
-        auto it = cx.tcx.items.get(id._1);
+        auto it = cx.tcx.items.find(id._1);
         auto tpt;
         alt (it) {
-            case (ast_map::node_item(?item)) { tpt = ty_of_item(cx, item); }
-            case (ast_map::node_native_item(?native_item)) {
+            case (some(ast_map::node_item(?item))) {
+                tpt = ty_of_item(cx, item);
+            }
+            case (some(ast_map::node_native_item(?native_item))) {
                 tpt = ty_of_native_item(cx, native_item,
                                         ast::native_abi_cdecl);
             }
+            case (_) {
+                cx.tcx.sess.fatal("internal error " +
+                                  util::common::istr(id._1));
+            }
         }
         ret tpt;
     }
@@ -640,7 +672,7 @@ fn ty_of_native_item(&@ctxt cx, &@ast::native_item it,
                     case (some(?tpt)) { ret tpt; }
                     case (none) { }
                 }
-                auto t = ty::mk_native(cx.tcx);
+                auto t = ty::mk_native(cx.tcx, ast::local_def(it.id));
                 auto tpt = tup(0u, t);
                 cx.tcx.tcache.insert(local_def(it.id), tpt);
                 ret tpt;
@@ -819,11 +851,25 @@ fn simple(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) ->
 
 tag autoderef_kind { AUTODEREF_OK; NO_AUTODEREF; }
 
-fn strip_boxes(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
+// FIXME This is almost a duplicate of ty::type_autoderef, with structure_of
+// instead of ty::struct.
+fn do_autoderef(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
     auto t1 = t;
     while (true) {
         alt (structure_of(fcx, sp, t1)) {
             case (ty::ty_box(?inner)) { t1 = inner.ty; }
+            case (ty::ty_res(_, ?inner, ?tps)) {
+                t1 = ty::substitute_type_params(fcx.ccx.tcx, tps, inner);
+            }
+            case (ty::ty_tag(?did, ?tps)) {
+                auto variants = ty::tag_variants(fcx.ccx.tcx, did);
+                if (vec::len(variants) != 1u ||
+                    vec::len(variants.(0).args) != 1u) {
+                    ret t1;
+                }
+                t1 = ty::substitute_type_params(fcx.ccx.tcx, tps,
+                                                variants.(0).args.(0));
+            }
             case (_) { ret t1; }
         }
     }
@@ -881,8 +927,8 @@ fn full(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
         auto actual_1 = actual;
         auto implicit_boxes = 0u;
         if (adk == AUTODEREF_OK) {
-            expected_1 = strip_boxes(fcx, sp, expected_1);
-            actual_1 = strip_boxes(fcx, sp, actual_1);
+            expected_1 = do_autoderef(fcx, sp, expected_1);
+            actual_1 = do_autoderef(fcx, sp, actual_1);
             implicit_boxes = count_boxes(fcx, sp, actual);
         }
         let vec[mutable ty::t] ty_param_substs = [mutable ];
@@ -1010,10 +1056,10 @@ fn visit_block_pre(@fn_ctxt fcx, &ast::block b) {
         resolve_type_vars_for_node(fcx, b.span, b.node.id);
     }
     fn visit_pat_pre(@fn_ctxt fcx, &@ast::pat p) {
-        resolve_type_vars_for_node(fcx, p.span, ty::pat_node_id(p));
+        resolve_type_vars_for_node(fcx, p.span, p.id);
     }
     fn visit_local_pre(@fn_ctxt fcx, &@ast::local l) {
-        auto var_id = fcx.locals.get(l.node.id);
+        auto var_id = lookup_local(fcx, l.span, l.node.id);
         auto fix_rslt =
             ty::unify::resolve_type_var(fcx.ccx.tcx, fcx.var_bindings,
                                         var_id);
@@ -1150,9 +1196,9 @@ fn visit_pat_pre(@crate_ctxt ccx, @ty::unify::var_bindings vb,
                      hashmap[ast::node_id, ast::ident] local_names,
                      @mutable int nvi, &@ast::pat p) {
         alt (p.node) {
-            case (ast::pat_bind(?ident, ?id)) {
+            case (ast::pat_bind(?ident)) {
                 assign(ccx.tcx, vb, locals, local_names, nvi,
-                       id, ident, none[ty::t]);
+                       p.id, ident, none[ty::t]);
             }
             case (_) {/* no-op */ }
         }
@@ -1203,24 +1249,23 @@ fn check_lit(@crate_ctxt ccx, &@ast::lit lit) -> ty::t {
 // their types immediately.
 fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
     alt (pat.node) {
-        case (ast::pat_wild(?id)) {
-            write::ty_only_fixup(fcx, id, expected);
+        case (ast::pat_wild) {
+            write::ty_only_fixup(fcx, pat.id, expected);
         }
-        case (ast::pat_lit(?lt, ?id)) {
+        case (ast::pat_lit(?lt)) {
             auto typ = check_lit(fcx.ccx, lt);
             typ = demand::simple(fcx, pat.span, expected, typ);
-            write::ty_only_fixup(fcx, id, typ);
+            write::ty_only_fixup(fcx, pat.id, typ);
         }
-        case (ast::pat_bind(?name, ?id)) {
-            auto vid = fcx.locals.get(id);
+        case (ast::pat_bind(?name)) {
+            auto vid = lookup_local(fcx, pat.span, pat.id);
             auto typ = ty::mk_var(fcx.ccx.tcx, vid);
             typ = demand::simple(fcx, pat.span, expected, typ);
-            write::ty_only_fixup(fcx, id, typ);
+            write::ty_only_fixup(fcx, pat.id, typ);
         }
-        case (ast::pat_tag(?path, ?subpats, ?id)) {
+        case (ast::pat_tag(?path, ?subpats)) {
             // Typecheck the path.
-
-            auto v_def = fcx.ccx.tcx.def_map.get(id);
+            auto v_def = lookup_def(fcx, path.span, pat.id);
             auto v_def_ids = ast::variant_def_ids(v_def);
             auto tag_tpt = ty::lookup_item_type(fcx.ccx.tcx, v_def_ids._0);
             auto path_tpot = instantiate_path(fcx, path, tag_tpt, pat.span);
@@ -1295,7 +1340,7 @@ fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
                                                    ""
                                                } else { "s" }));
             }
-            write::ty_fixup(fcx, id, path_tpot);
+            write::ty_fixup(fcx, pat.id, path_tpot);
         }
     }
 }
@@ -1315,8 +1360,8 @@ fn require_pure_call(@crate_ctxt ccx, &ast::purity caller_purity,
     alt (caller_purity) {
         case (ast::impure_fn) { ret; }
         case (ast::pure_fn) {
-            alt (ccx.tcx.def_map.get(callee.id)) {
-                case (ast::def_fn(_, ast::pure_fn)) {
+            alt (ccx.tcx.def_map.find(callee.id)) {
+                case (some(ast::def_fn(_, ast::pure_fn))) {
                     ret;
                 }
                 case (_) {
@@ -1336,17 +1381,21 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
     // expressions.
 
     fn check_call_or_bind(&@fn_ctxt fcx, &span sp, &@ast::expr f,
-                          &vec[option::t[@ast::expr]] args) {
+                          &vec[option::t[@ast::expr]] args, bool is_call) {
         // Check the function.
 
         check_expr(fcx, f);
         // Get the function type.
 
         auto fty = expr_ty(fcx.ccx.tcx, f);
-        // Grab the argument types and the return type.
 
+        // We want to autoderef calls but not binds
+        auto fty_stripped =
+            if (is_call) { do_autoderef(fcx, sp, fty) } else { fty };
+
+        // Grab the argument types and the return type.
         auto arg_tys;
-        alt (structure_of(fcx, sp, fty)) {
+        alt (structure_of(fcx, sp, fty_stripped)) {
             case (ty::ty_fn(_, ?arg_tys_0, _, _, _)) { arg_tys = arg_tys_0; }
             case (ty::ty_native_fn(_, ?arg_tys_0, _)) { arg_tys = arg_tys_0; }
             case (_) {
@@ -1410,7 +1459,7 @@ fn check_call(&@fn_ctxt fcx, &span sp, &@ast::expr f,
         }
         // Call the generic checker.
 
-        check_call_or_bind(fcx, sp, f, args_opt_0);
+        check_call_or_bind(fcx, sp, f, args_opt_0, true);
     }
     // A generic function for checking for or for-each loops
 
@@ -1440,8 +1489,9 @@ fn check_pred_expr(&@fn_ctxt fcx, &@ast::expr e) {
                 case (ast::expr_call(?operator, ?operands)) {
                     alt (operator.node) {
                         case (ast::expr_path(?oper_name)) {
-                            alt (fcx.ccx.tcx.def_map.get(operator.id)) {
-                                case (ast::def_fn(?_d_id, ast::pure_fn)) { 
+                            alt (fcx.ccx.tcx.def_map.find(operator.id)) {
+                                case (some(ast::def_fn(?_d_id,
+                                                       ast::pure_fn))) { 
                                     // do nothing
                                 }
                                 case (_) {
@@ -1530,7 +1580,7 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
                 case (ast::ne) { ty::mk_bool(fcx.ccx.tcx) }
                 case (ast::ge) { ty::mk_bool(fcx.ccx.tcx) }
                 case (ast::gt) { ty::mk_bool(fcx.ccx.tcx) }
-                case (_) { strip_boxes(fcx, expr.span, lhs_t) }
+                case (_) { do_autoderef(fcx, expr.span, lhs_t) }
             };
             write::ty_only_fixup(fcx, id, t);
         }
@@ -1545,10 +1595,23 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
                     alt (structure_of(fcx, expr.span, oper_t)) {
                         case (ty::ty_box(?inner)) { oper_t = inner.ty; }
                         case (ty::ty_res(_, ?inner, _)) { oper_t = inner; }
+                        case (ty::ty_tag(?id, ?tps)) {
+                            auto variants = ty::tag_variants(fcx.ccx.tcx, id);
+                            if (vec::len(variants) != 1u ||
+                                vec::len(variants.(0).args) != 1u) {
+                                fcx.ccx.tcx.sess.span_fatal
+                                    (expr.span, "can only dereference tags " +
+                                     "with a single variant which has a " +
+                                     "single argument");
+                            }
+                            oper_t = ty::substitute_type_params
+                                (fcx.ccx.tcx, tps, variants.(0).args.(0));
+                        }
                         case (_) {
-                            auto s = "dereferencing non-box type: " +
-                                ty_to_str(fcx.ccx.tcx, oper_t);
-                            fcx.ccx.tcx.sess.span_fatal(expr.span, s);
+                            fcx.ccx.tcx.sess.span_fatal
+                                (expr.span, "dereferencing non-" + 
+                                 "dereferenceable type: " +
+                                 ty_to_str(fcx.ccx.tcx, oper_t));
                         }
                     }
                 }
@@ -1564,12 +1627,12 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
                                                                  oper_t)));
                     }
                 }
-                case (_) { oper_t = strip_boxes(fcx, expr.span, oper_t); }
+                case (_) { oper_t = do_autoderef(fcx, expr.span, oper_t); }
             }
             write::ty_only_fixup(fcx, id, oper_t);
         }
         case (ast::expr_path(?pth)) {
-            auto defn = fcx.ccx.tcx.def_map.get(id);
+            auto defn = lookup_def(fcx, pth.span, id);
             auto tpt = ty_param_count_and_ty_for_def(fcx, expr.span, defn);
             if (ty::def_has_ty_params(defn)) {
                 auto path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
@@ -1591,7 +1654,18 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
             auto t = expr_ty(fcx.ccx.tcx, expanded);
             write::ty_only_fixup(fcx, id, t);
         }
-        case (ast::expr_fail(_)) { write::bot_ty(fcx.ccx.tcx, id); }
+        case (ast::expr_fail(?expr_opt)) {
+            alt (expr_opt) {
+                case (none) { /* do nothing */ }
+                case (some(?e)) {
+                    check_expr(fcx, e);
+                    auto tcx = fcx.ccx.tcx;
+                    auto ety = expr_ty(tcx, e);
+                    demand::simple(fcx, e.span, ty::mk_str(tcx), ety);
+                }
+            }
+            write::bot_ty(fcx.ccx.tcx, id);
+        }
         case (ast::expr_break) { write::bot_ty(fcx.ccx.tcx, id); }
         case (ast::expr_cont) { write::bot_ty(fcx.ccx.tcx, id); }
         case (ast::expr_ret(?expr_opt)) {
@@ -1806,7 +1880,7 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
         case (ast::expr_bind(?f, ?args)) {
             // Call the generic checker.
 
-            check_call_or_bind(fcx, expr.span, f, args);
+            check_call_or_bind(fcx, expr.span, f, args, false);
             // Pull the argument and return types out.
 
             auto proto_1;
@@ -1855,7 +1929,8 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
             // Pull the return type out of the type of the function.
 
             auto rt_1;
-            auto fty = ty::expr_ty(fcx.ccx.tcx, f);
+            auto fty = do_autoderef(fcx, expr.span,
+                                   ty::expr_ty(fcx.ccx.tcx, f));
             alt (structure_of(fcx, expr.span, fty)) {
                 case (ty::ty_fn(_, _, ?rt, _, _)) { rt_1 = rt; }
                 case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
@@ -2012,7 +2087,7 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
         case (ast::expr_field(?base, ?field)) {
             check_expr(fcx, base);
             auto base_t = expr_ty(fcx.ccx.tcx, base);
-            base_t = strip_boxes(fcx, expr.span, base_t);
+            base_t = do_autoderef(fcx, expr.span, base_t);
             alt (structure_of(fcx, expr.span, base_t)) {
                 case (ty::ty_tup(?args)) {
                     let uint ix =
@@ -2058,7 +2133,7 @@ fn check_binop_type_compat(&@fn_ctxt fcx, common::span span,
         case (ast::expr_index(?base, ?idx)) {
             check_expr(fcx, base);
             auto base_t = expr_ty(fcx.ccx.tcx, base);
-            base_t = strip_boxes(fcx, expr.span, base_t);
+            base_t = do_autoderef(fcx, expr.span, base_t);
             check_expr(fcx, idx);
             auto idx_t = expr_ty(fcx.ccx.tcx, idx);
             if (!type_is_integral(fcx, idx.span, idx_t)) {
@@ -2249,7 +2324,8 @@ fn ast_constr_to_constr(ty::ctxt tcx, &@ast::constr c)
 fn check_decl_initializer(&@fn_ctxt fcx, ast::node_id nid,
                           &ast::initializer init) {
     check_expr(fcx, init.expr);
-    auto lty = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(nid));
+    auto lty = ty::mk_var(fcx.ccx.tcx,
+                          lookup_local(fcx, init.expr.span, nid));
     alt (init.op) {
         case (ast::init_assign) {
             demand::simple(fcx, init.expr.span, lty,
index 2b84747046e0e5849cf9e13f76caf69c7438d469..c87373c4ff8699ac66690e81a00b5a696d579760 100644 (file)
@@ -60,12 +60,6 @@ fn visit_crate[E](&crate c, &E e, &vt[E] v) {
 
 fn visit_crate_directive[E](&@crate_directive cd, &E e, &vt[E] v) {
     alt (cd.node) {
-        case (cdir_let(_, ?ex, ?cdirs)) {
-            vt(v).visit_expr(ex, e, v);
-            for (@crate_directive cdir in cdirs) {
-                visit_crate_directive(cdir, e, v);
-            }
-        }
         case (cdir_src_mod(_, _, _)) { }
         case (cdir_dir_mod(_, _, ?cdirs, _)) {
             for (@crate_directive cdir in cdirs) {
@@ -196,7 +190,7 @@ fn visit_constr[E](&@constr c, &E e, &vt[E] v) {
 
 fn visit_pat[E](&@pat p, &E e, &vt[E] v) {
     alt (p.node) {
-        case (pat_tag(?path, ?children, _)) {
+        case (pat_tag(?path, ?children)) {
             for (@ty tp in path.node.types) { vt(v).visit_ty(tp, e, v); }
             for (@pat child in children) { vt(v).visit_pat(child, e, v); }
         }
@@ -365,7 +359,9 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
         case (expr_ext(_, _, _, ?expansion)) {
             vt(v).visit_expr(expansion, e, v);
         }
-        case (expr_fail(_)) { }
+        case (expr_fail(?eo)) {
+            visit_expr_opt(eo, e, v);
+        }
         case (expr_break) { }
         case (expr_cont) { }
         case (expr_ret(?eo)) { visit_expr_opt(eo, e, v); }
index 8821db4914ac968010c69c83618bf095ea4d55bd..598c6d68f787dee544e0ac5812485051f52352b5 100644 (file)
@@ -56,12 +56,6 @@ fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
     if (!v.want_crate_directives()) { ret; }
     v.visit_crate_directive_pre(cd);
     alt (cd.node) {
-        case (ast::cdir_let(_, ?e, ?cdirs)) {
-            walk_expr(v, e);
-            for (@ast::crate_directive cdir in cdirs) {
-                walk_crate_directive(v, cdir);
-            }
-        }
         case (ast::cdir_src_mod(_, _, _)) { }
         case (ast::cdir_dir_mod(_, _, ?cdirs, _)) {
             for (@ast::crate_directive cdir in cdirs) {
@@ -191,7 +185,7 @@ fn walk_ty(&ast_visitor v, @ast::ty t) {
 fn walk_pat(&ast_visitor v, &@ast::pat p) {
     v.visit_pat_pre(p);
     alt (p.node) {
-        case (ast::pat_tag(?path, ?children, _)) {
+        case (ast::pat_tag(?path, ?children)) {
             for (@ast::ty tp in path.node.types) { walk_ty(v, tp); }
             for (@ast::pat child in children) { walk_pat(v, child); }
         }
@@ -375,7 +369,7 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
 
             walk_expr(v, expansion);
         }
-        case (ast::expr_fail(_)) { }
+        case (ast::expr_fail(?eo)) { walk_expr_opt(v, eo); }
         case (ast::expr_break) { }
         case (ast::expr_cont) { }
         case (ast::expr_ret(?eo)) { walk_expr_opt(v, eo); }
index 05cd539e00c5d7dc40d497be5240daeda08c3aa3..396d37a80905b9b107c8344a4e2f783afff27222 100644 (file)
@@ -89,7 +89,7 @@ fn mt_to_str(&ctxt cx, &mt m) -> str {
     alt (cname(cx, typ)) { case (some(?cs)) { ret cs; } case (_) { } }
     auto s = "";
     alt (struct(cx, typ)) {
-        case (ty_native) { s += "native"; }
+        case (ty_native(_)) { s += "native"; }
         case (ty_nil) { s += "()"; }
         case (ty_bot) { s += "_|_"; }
         case (ty_bool) { s += "bool"; }
@@ -139,6 +139,9 @@ fn mt_to_str(&ctxt cx, &mt m) -> str {
             auto m = vec::map[method, str](f, meths);
             s += "obj {\n\t" + str::connect(m, "\n\t") + "\n}";
         }
+        case (ty_res(?id, _, _)) {
+            s += "<resource#" + istr(id._0) + ":" + istr(id._1) + ">";
+        }
         case (ty_var(?v)) { s += "<T" + istr(v) + ">"; }
         case (ty_param(?id)) {
             s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
@@ -376,12 +379,12 @@ fn rust_printer(io::writer writer) -> ps {
 fn uint_to_str(&uint i) -> str { ret uistr(i); }
 
 fn constr_to_str(&@constr_def c) -> str {
-    ret path_to_str(c.node.path) +
+    ret ast::path_to_str(c.node.path) +
             constr_args_to_str(uint_to_str, c.node.args);
 }
 
 fn ast_constr_to_str(&@front::ast::constr c) -> str {
-    ret path_to_str(c.node.path) +
+    ret ast::path_to_str(c.node.path) +
             constr_args_to_str(uint_to_str, c.node.args);
 }
 
index fa28a01a6daed95067eb23a50b6be88c932a4b53..04f7522a7d8c8e19163883272b848c3192de8e53 100644 (file)
@@ -383,27 +383,43 @@ fn print_item(&ps s, &@ast::item item) {
             break_offset(s.s, 0u, 0);
         }
         case (ast::item_tag(?variants, ?params)) {
-            head(s, "tag");
+            auto newtype = vec::len(variants) == 1u &&
+                str::eq(item.ident, variants.(0).node.name) &&
+                vec::len(variants.(0).node.args) == 1u;
+            if (newtype) {
+                ibox(s, indent_unit);
+                word_space(s, "tag");
+            } else {
+                head(s, "tag");
+            }
             word(s.s, item.ident);
             print_type_params(s, params);
             space(s.s);
-            bopen(s);
-            for (ast::variant v in variants) {
-                space(s.s);
-                maybe_print_comment(s, v.span.lo);
-                word(s.s, v.node.name);
-                if (vec::len(v.node.args) > 0u) {
-                    popen(s);
-                    fn print_variant_arg(&ps s, &ast::variant_arg arg) {
-                        print_type(s, *arg.ty);
+            if (newtype) {
+                word_space(s, "=");
+                print_type(s, *variants.(0).node.args.(0).ty);
+                word(s.s, ";");
+                end(s);
+            } else {
+                bopen(s);
+                for (ast::variant v in variants) {
+                    space(s.s);
+                    maybe_print_comment(s, v.span.lo);
+                    word(s.s, v.node.name);
+                    if (vec::len(v.node.args) > 0u) {
+                        popen(s);
+                        fn print_variant_arg(&ps s, &ast::variant_arg arg) {
+                            print_type(s, *arg.ty);
+                        }
+                        commasep(s, consistent, v.node.args,
+                                 print_variant_arg);
+                        pclose(s);
                     }
-                    commasep(s, consistent, v.node.args, print_variant_arg);
-                    pclose(s);
+                    word(s.s, ";");
+                    maybe_print_trailing_comment(s, v.span, none[uint]);
                 }
-                word(s.s, ";");
-                maybe_print_trailing_comment(s, v.span, none[uint]);
+                bclose(s, item.span);
             }
-            bclose(s, item.span);
         }
         case (ast::item_obj(?_obj, ?params, _)) {
             head(s, "obj");
@@ -442,7 +458,7 @@ fn print_field(&ps s, &ast::obj_field field) {
             bclose(s, item.span);
         }
         case (ast::item_res(?dt, ?dt_id, ?tps, ?ct_id)) {
-            head(s, "res");
+            head(s, "resource");
             word(s.s, item.ident);
             print_type_params(s, tps);
             popen(s);
@@ -822,10 +838,10 @@ fn print_opt(&ps s, &option::t[@ast::expr] expr) {
             pclose(s);
         }
         case (ast::expr_path(?path)) { print_path(s, path); }
-        case (ast::expr_fail(?str)) {
+        case (ast::expr_fail(?maybe_fail_val)) {
             word(s.s, "fail");
-            alt (str) {
-                case (some(?msg)) { word(s.s, #fmt(" \"%s\"", msg)); }
+            alt (maybe_fail_val) {
+                case (some(?expr)) { word(s.s, " "); print_expr(s, expr); }
                 case (_) { }
             }
         }
@@ -1000,10 +1016,10 @@ fn print_path(&ps s, &ast::path path) {
 fn print_pat(&ps s, &@ast::pat pat) {
     maybe_print_comment(s, pat.span.lo);
     alt (pat.node) {
-        case (ast::pat_wild(_)) { word(s.s, "_"); }
-        case (ast::pat_bind(?id, _)) { word(s.s, "?" + id); }
-        case (ast::pat_lit(?lit, _)) { print_literal(s, lit); }
-        case (ast::pat_tag(?path, ?args, _)) {
+        case (ast::pat_wild) { word(s.s, "_"); }
+        case (ast::pat_bind(?id)) { word(s.s, "?" + id); }
+        case (ast::pat_lit(?lit)) { print_literal(s, lit); }
+        case (ast::pat_tag(?path, ?args)) {
             print_path(s, path);
             if (vec::len(args) > 0u) {
                 popen(s);
@@ -1017,7 +1033,7 @@ fn print_pat(&ps s, &@ast::pat pat) {
     alt (s.mode) {
         case (mo_identified) {
             space(s.s);
-            synth_comment(s, int::to_str(ty::pat_node_id(pat), 10u));
+            synth_comment(s, int::to_str(pat.id, 10u));
         }
         case (_) {/* no-op */ }
     }
index 473a7b20615adcd7efb5338f609597a585941611..12e6562e702758145aacb841ff72f329f70a2c57 100644 (file)
@@ -1,7 +1,6 @@
 // -*- rust -*-
 
 use std;
-use rustc;
 
 mod fuzzer;
 
index 09872431831eec342ad8a299bc0f179ad7687ccf..2de291eac5b4c17b6698c7d8bdf1ac1e64022170 100644 (file)
@@ -6,8 +6,6 @@
 import std::io;
 import std::vec;
 
-import rustc::front::ast;
-
 type src_gen = iter() -> str;
 
 iter dir_src_gen(str dir) -> str {
index a947a1c93e8e2fc2048819da146515d10b33a455..78301e3d879ddc64e07f5e16cf7433c4862d494a 100644 (file)
@@ -7,6 +7,7 @@
 rust_chan::rust_chan(rust_task *task,
                      maybe_proxy<rust_port> *port,
                      size_t unit_sz) :
+                     ref_count(1),
                      task(task),
                      port(port),
                      buffer(task, unit_sz) {
@@ -97,6 +98,60 @@ void rust_chan::send(void *sptr) {
 
     return;
 }
+
+rust_chan *rust_chan::clone(maybe_proxy<rust_task> *target) {
+    size_t unit_sz = buffer.unit_sz;
+    maybe_proxy<rust_port> *port = this->port;
+    rust_task *target_task = NULL;
+    if (target->is_proxy() == false) {
+        port = this->port;
+        target_task = target->referent();
+    } else {
+        rust_handle<rust_port> *handle =
+            task->sched->kernel->get_port_handle(port->as_referent());
+        maybe_proxy<rust_port> *proxy = new rust_proxy<rust_port> (handle);
+        LOG(task, mem, "new proxy: " PTR, proxy);
+        port = proxy;
+        target_task = target->as_proxy()->handle()->referent();
+    }
+    return new (target_task) rust_chan(target_task, port, unit_sz);
+}
+
+/**
+ * Cannot Yield: If the task were to unwind, the dropped ref would still
+ * appear to be live, causing modify-after-free errors.
+ */
+void rust_chan::destroy() {
+    A(task->sched, ref_count == 0,
+      "Channel's ref count should be zero.");
+
+    if (is_associated()) {
+        if (port->is_proxy()) {
+            // Here is a good place to delete the port proxy we allocated
+            // in upcall_clone_chan.
+            rust_proxy<rust_port> *proxy = port->as_proxy();
+            disassociate();
+            delete proxy;
+        } else {
+            // We're trying to delete a channel that another task may be
+            // reading from. We have two options:
+            //
+            // 1. We can flush the channel by blocking in upcall_flush_chan()
+            //    and resuming only when the channel is flushed. The problem
+            //    here is that we can get ourselves in a deadlock if the
+            //    parent task tries to join us.
+            //
+            // 2. We can leave the channel in a "dormnat" state by not freeing
+            //    it and letting the receiver task delete it for us instead.
+            if (buffer.is_empty() == false) {
+                return;
+            }
+            disassociate();
+        }
+    }
+    delete this;
+}
+
 //
 // Local Variables:
 // mode: C++
index a6e4d3d6b43c91b42fc6bd831e762020b9d37ce7..4172ca5f09d868c8d01fc92683f3f654b4d3a0b9 100644 (file)
@@ -1,10 +1,10 @@
 #ifndef RUST_CHAN_H
 #define RUST_CHAN_H
 
-class rust_chan : public rc_base<rust_chan>,
-                  public task_owned<rust_chan>,
+class rust_chan : public task_owned<rust_chan>,
                   public rust_cond {
 public:
+    RUST_REFCOUNTED_WITH_DTOR(rust_chan, destroy())
     rust_chan(rust_task *task, maybe_proxy<rust_port> *port, size_t unit_sz);
 
     ~rust_chan();
@@ -19,6 +19,11 @@ public:
     bool is_associated();
 
     void send(void *sptr);
+
+    rust_chan *clone(maybe_proxy<rust_task> *target);
+
+    // Called whenever the channel's ref count drops to zero.
+    void destroy();
 };
 
 //
index d5c4f459f1c7eed3faea6f309342a2d1ec33f1ec..9d7d714064fd700ea832d0394cbdc100b4c012db 100644 (file)
@@ -97,19 +97,18 @@ static intptr_t const CONST_REFCOUNT = 0x7badface;
 static size_t const BUF_BYTES = 2048;
 
 // Every reference counted object should derive from this base class.
+// Or use this macro. The macro is preferred as the base class will be
+// disappearing.
 
-template <typename T> struct rc_base {
-    intptr_t ref_count;
-
-    void ref() {
-        ++ref_count;
-    }
+#define RUST_REFCOUNTED(T) \
+  RUST_REFCOUNTED_WITH_DTOR(T, delete (T*)this)
+#define RUST_REFCOUNTED_WITH_DTOR(T, dtor) \
+  intptr_t ref_count;      \
+  void ref() { ++ref_count; } \
+  void deref() { if (--ref_count == 0) { dtor; } }
 
-    void deref() {
-        if (--ref_count == 0) {
-            delete (T*)this;
-        }
-    }
+template <typename T> struct rc_base {
+    RUST_REFCOUNTED(T)
 
     rc_base();
     ~rc_base();
index 4f7dccc46524753099eeafdcecf17d31f52e7b5b..05220f026065c3ff0d29d4a7204e6f43f7847b55 100644 (file)
@@ -126,35 +126,7 @@ void upcall_del_chan(rust_task *task, rust_chan *chan) {
     scoped_lock with(task->kernel->scheduler_lock);
 
     LOG(task, comm, "upcall del_chan(0x%" PRIxPTR ")", (uintptr_t) chan);
-
-    A(task->sched, chan->ref_count == 0,
-      "Channel's ref count should be zero.");
-
-    if (chan->is_associated()) {
-        if (chan->port->is_proxy()) {
-            // Here is a good place to delete the port proxy we allocated
-            // in upcall_clone_chan.
-            rust_proxy<rust_port> *proxy = chan->port->as_proxy();
-            chan->disassociate();
-            delete proxy;
-        } else {
-            // We're trying to delete a channel that another task may be
-            // reading from. We have two options:
-            //
-            // 1. We can flush the channel by blocking in upcall_flush_chan()
-            //    and resuming only when the channel is flushed. The problem
-            //    here is that we can get ourselves in a deadlock if the
-            //    parent task tries to join us.
-            //
-            // 2. We can leave the channel in a "dormant" state by not freeing
-            //    it and letting the receiver task delete it for us instead.
-            if (chan->buffer.is_empty() == false) {
-                return;
-            }
-            chan->disassociate();
-        }
-    }
-    delete chan;
+    chan->destroy();
 }
 
 /**
@@ -166,21 +138,7 @@ upcall_clone_chan(rust_task *task, maybe_proxy<rust_task> *target,
                   rust_chan *chan) {
     LOG_UPCALL_ENTRY(task);
     scoped_lock with(task->kernel->scheduler_lock);
-    size_t unit_sz = chan->buffer.unit_sz;
-    maybe_proxy<rust_port> *port = chan->port;
-    rust_task *target_task = NULL;
-    if (target->is_proxy() == false) {
-        port = chan->port;
-        target_task = target->referent();
-    } else {
-        rust_handle<rust_port> *handle =
-            task->sched->kernel->get_port_handle(port->as_referent());
-        maybe_proxy<rust_port> *proxy = new rust_proxy<rust_port> (handle);
-        LOG(task, mem, "new proxy: " PTR, proxy);
-        port = proxy;
-        target_task = target->as_proxy()->handle()->referent();
-    }
-    return new (target_task) rust_chan(target_task, port, unit_sz);
+    return chan->clone(target);
 }
 
 extern "C" CDECL void
diff --git a/src/test/compile-fail/auto-deref-bind.rs b/src/test/compile-fail/auto-deref-bind.rs
new file mode 100644 (file)
index 0000000..51f76be
--- /dev/null
@@ -0,0 +1,7 @@
+// error-pattern: mismatched types
+
+fn add1(int i) -> int { ret i+1; }
+fn main() {
+    auto f = @add1;
+    auto g = bind f(5);
+}
diff --git a/src/test/compile-fail/ext-noname.rs b/src/test/compile-fail/ext-noname.rs
new file mode 100644 (file)
index 0000000..82395c7
--- /dev/null
@@ -0,0 +1,5 @@
+// error-pattern:expected a syntax expander name
+
+fn main() {
+  #();
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/fail-expr.rs b/src/test/compile-fail/fail-expr.rs
new file mode 100644 (file)
index 0000000..dbc5afa
--- /dev/null
@@ -0,0 +1,5 @@
+// error-pattern:mismatched types
+
+fn main() {
+  fail 5;
+}
\ No newline at end of file
index a8c4934aa0c2334bd0437dded05b67fb5bdea3d3..768cc1e1bf4c66effe9ea91b81a5d67e8ed2daa7 100644 (file)
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-// error-pattern: after expression but found
+// error-pattern:unexpected token
 fn main() {
   fail @ ;
 }
diff --git a/src/test/compile-fail/use-meta-mismatch.rs b/src/test/compile-fail/use-meta-mismatch.rs
new file mode 100644 (file)
index 0000000..fc01f5e
--- /dev/null
@@ -0,0 +1,5 @@
+// error-pattern:can't find crate for 'std'
+
+use std (complex(meta(item)));
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/run-fail/args-fail.rs b/src/test/run-fail/args-fail.rs
new file mode 100644 (file)
index 0000000..07f47e0
--- /dev/null
@@ -0,0 +1,9 @@
+// xfail-stage0
+// error-pattern:meep
+fn f(int a, int b, @int c) {
+  fail "moop";
+}
+
+fn main() {
+  f(1, fail "meep", @42);
+}
\ No newline at end of file
index 123b1087d9b6ea6ab059f93f6e3db89c287cd81d..793260210b088b706a93cd32b4ebc165f3b594b5 100644 (file)
@@ -1,5 +1,10 @@
 
 
-
-// error-pattern:woooo
-fn main() { fail"woooo"; }
\ No newline at end of file
+// error-pattern:wooooo
+fn main() {
+  auto a = 1;
+  if (1 == 1) {
+    a = 2;
+  }
+  fail "woooo" + "o";
+}
\ No newline at end of file
diff --git a/src/test/run-fail/fail-arg.rs b/src/test/run-fail/fail-arg.rs
new file mode 100644 (file)
index 0000000..1d69d2c
--- /dev/null
@@ -0,0 +1,9 @@
+// xfail-stage0
+// error-pattern:woe
+fn f(int a) {
+  log a;
+}
+
+fn main() { 
+  f(fail "woe");
+} 
diff --git a/src/test/run-fail/fmt-fail.rs b/src/test/run-fail/fmt-fail.rs
new file mode 100644 (file)
index 0000000..2b8a39f
--- /dev/null
@@ -0,0 +1,9 @@
+// xfail-stage0
+// error-pattern:meh
+use std;
+import std::str;
+
+fn main() {
+  let str str_var = "meh";
+  fail #fmt("%s", str_var);
+}
\ No newline at end of file
diff --git a/src/test/run-pass/auto-deref-fn.rs b/src/test/run-pass/auto-deref-fn.rs
new file mode 100644 (file)
index 0000000..6959e8e
--- /dev/null
@@ -0,0 +1,11 @@
+// xfail-stage0
+
+fn add1(int i) -> int { ret i+1; }
+fn main() {
+    auto f = @add1;
+    auto g = @f;
+    auto h = @@@add1;
+    assert(f(5) == 6);
+    assert(g(8) == 9);
+    assert(h(0x1badd00d) == 0x1badd00e);
+}
diff --git a/src/test/run-pass/newtype-polymorphic.rs b/src/test/run-pass/newtype-polymorphic.rs
new file mode 100644 (file)
index 0000000..efbcb51
--- /dev/null
@@ -0,0 +1,16 @@
+tag myvec[X] = vec[X];
+
+fn myvec_deref[X](&myvec[X] mv) -> vec[X] {
+    ret *mv;
+}
+
+fn myvec_elt[X](&myvec[X] mv) -> X {
+    ret mv.(0);
+}
+
+fn main() {
+    auto mv = myvec([1, 2, 3]);
+    assert(myvec_deref(mv).(1) == 2);
+    assert(myvec_elt(mv) == 1);
+    assert(mv.(2) == 3);
+}
diff --git a/src/test/run-pass/newtype.rs b/src/test/run-pass/newtype.rs
new file mode 100644 (file)
index 0000000..7f8cb3b
--- /dev/null
@@ -0,0 +1,10 @@
+tag mytype = rec(fn (&mytype i) -> int compute, int val);
+
+fn compute(&mytype i) -> int {
+    ret i.val + 20;
+}
+
+fn main() {
+    auto myval = mytype(rec(compute=compute, val=30));
+    assert(myval.compute(myval) == 50);
+}