diff --git a/Makefile.in b/Makefile.in
index ecff84dc4c0..362b97ea036 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -144,9 +144,9 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/comp/, \
######################################################################
LREQ := rt/$(CFG_RUNTIME) rustllvm/$(CFG_RUSTLLVM)
-SREQ0 := stage0/rustc$(X) $(LREQ) stage1/glue.o stage1/$(CFG_STDLIB)
-SREQ1 := stage1/rustc$(X) $(LREQ) stage2/glue.o stage2/$(CFG_STDLIB)
-SREQ2 := stage2/rustc$(X) $(LREQ) stage3/glue.o stage3/$(CFG_STDLIB)
+SREQ0 := stage0/rustc$(X) $(LREQ) rt/main.a stage1/glue.o stage1/$(CFG_STDLIB)
+SREQ1 := stage1/rustc$(X) $(LREQ) rt/main.a stage2/glue.o stage2/$(CFG_STDLIB)
+SREQ2 := stage2/rustc$(X) $(LREQ) rt/main.a stage3/glue.o stage3/$(CFG_STDLIB)
######################################################################
diff --git a/mk/clean.mk b/mk/clean.mk
index 3f19953929e..305b06b5e0a 100644
--- a/mk/clean.mk
+++ b/mk/clean.mk
@@ -28,6 +28,8 @@ clean:
$(Q)rm -f stage3/rustc$(X) stage3/$(CFG_STDLIB) stage3/glue*
$(Q)rm -f rustllvm/$(CFG_RUSTLLVM) rustllvm/rustllvmbits.a
$(Q)rm -f rt/$(CFG_RUNTIME)
+ $(Q)rm -f rt/main.o
+ $(Q)rm -f rt/main.a
$(Q)rm -Rf $(PKG_NAME)-*.tar.gz dist
$(Q)rm -f $(foreach ext,o a d bc s exe,$(wildcard stage*/*.$(ext)))
$(Q)rm -Rf $(foreach ext,out out.tmp \
diff --git a/mk/rt.mk b/mk/rt.mk
index 8139f9e4e79..1cc6dfb57f4 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -76,6 +76,18 @@ rt/%.o: rt/%.s $(MKFILES)
@$(call E, compile: $@)
$(Q)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
+ifdef CFG_WINDOWSY
+rt/main.ll: rt/main.ll.in
+ sed 's/MAIN/WinMain@16/' < $^ > $@
+else
+rt/main.ll: rt/main.ll.in
+ sed 's/MAIN/main/' < $^ > $@
+endif
+
+rt/main.a: rt/main.o
+ rm -f $@
+ ar crs $@ $^
+
rt/%.o: rt/%.ll $(MKFILES)
@$(call E, llc: $@)
$(Q)$(LLC) -filetype=obj -relocation-model=pic -march=x86 -o $@ $<
diff --git a/mk/stage1.mk b/mk/stage1.mk
index f2ca6321d94..c98882e41a8 100644
--- a/mk/stage1.mk
+++ b/mk/stage1.mk
@@ -44,7 +44,7 @@ stage1/%.o: stage1/%.s
stage1/%$(X): stage1/%.o $(SREQ0)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
- -Lstage1 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
+ -Lstage1 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
diff --git a/mk/stage2.mk b/mk/stage2.mk
index e084a19a8d3..0d87400c1e2 100644
--- a/mk/stage2.mk
+++ b/mk/stage2.mk
@@ -44,7 +44,7 @@ stage2/%.o: stage2/%.s
stage2/%$(X): stage2/%.o $(SREQ1)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
- -Lstage2 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
+ -Lstage2 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
diff --git a/mk/stage3.mk b/mk/stage3.mk
index dc2792446e2..77d09440883 100644
--- a/mk/stage3.mk
+++ b/mk/stage3.mk
@@ -23,7 +23,7 @@ stage3/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ2)
$(STAGE2) -c -o $@ $<
stage3/glue.o: stage2/rustc$(X) stage2/$(CFG_STDLIB) stage2/intrinsics.bc \
- rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
+ rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
@$(call E, generate: $@)
$(STAGE2) -c -o $@ --glue
@@ -44,7 +44,7 @@ stage3/%.o: stage3/%.s
stage3/%$(X): stage3/%.o $(SREQ2)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
- -Lstage3 -Lrustllvm -Lrt -lrustrt -lrustllvm -lstd -lm
+ -Lstage3 -Lrustllvm -Lrt rt/main.a -lrustrt -lrustllvm -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
diff --git a/mk/tests.mk b/mk/tests.mk
index 5e30b352dfa..db7a3dd4d33 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -185,7 +185,7 @@ compile-check: tidy \
%.stage0$(X): %.stage0.o $(SREQ0)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage1/glue.o -o $@ $< \
- -Lstage1 -Lrt -lrustrt -lstd -lm
+ -Lstage1 -Lrt rt/main.a -lrustrt -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
@@ -194,7 +194,7 @@ compile-check: tidy \
%.stage1$(X): %.stage1.o $(SREQ1)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage2/glue.o -o $@ $< \
- -Lstage2 -Lrt -lrustrt -lstd -lm
+ -Lstage2 -Lrt rt/main.a -lrustrt -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
@@ -203,7 +203,7 @@ compile-check: tidy \
%.stage2$(X): %.stage2.o $(SREQ2)
@$(call E, link [gcc]: $@)
$(Q)gcc $(CFG_GCCISH_CFLAGS) stage3/glue.o -o $@ $< \
- -Lstage3 -Lrt -lrustrt -lstd -lm
+ -Lstage3 -Lrt rt/main.a -lrustrt -lstd -lm
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index 2ae7b6a6fab..6469bbd3ced 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -1,8 +1,18 @@
import driver::session;
import lib::llvm::llvm;
import middle::trans;
+import middle::metadata;
+import middle::ty;
import std::str;
import std::fs;
+import std::vec;
+import std::option;
+import option::some;
+import option::none;
+import std::sha1::sha1;
+import std::sort;
+import trans::crate_ctxt;
+import front::ast;
import lib::llvm::llvm::ModuleRef;
import lib::llvm::llvm::ValueRef;
@@ -49,7 +59,7 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
auto linkres = llvm::LLVMLinkModules(llmod, llintrinsicsmod);
llvm::LLVMDisposeModule(llintrinsicsmod);
-
+
if (linkres == False) {
llvm_err(sess, "couldn't link the module with the intrinsics");
fail;
@@ -58,7 +68,7 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
mod write {
fn is_object_or_assembly_or_exe(output_type ot) -> bool {
- if ( (ot == output_type_assembly) ||
+ if ( (ot == output_type_assembly) ||
(ot == output_type_object) ||
(ot == output_type_exe) ) {
ret true;
@@ -218,3 +228,235 @@ mod write {
}
}
+/*
+ * Name mangling and its relationship to metadata. This is complex. Read
+ * carefully.
+ *
+ * The semantic model of Rust linkage is, broadly, that "there's no global
+ * namespace" between crates. Our aim is to preserve the illusion of this
+ * model despite the fact that it's not *quite* possible to implement on
+ * modern linkers. We initially didn't use system linkers at all, but have
+ * been convinced of their utility.
+ *
+ * There are a few issues to handle:
+ *
+ * - Linkers operate on a flat namespace, so we have to flatten names.
+ * We do this using the C++ namespace-mangling technique. Foo::bar
+ * symbols and such.
+ *
+ * - Symbols with the same name but different types need to get different
+ * linkage-names. We do this by hashing a string-encoding of the type into
+ * a fixed-size (currently 16-byte hex) cryptographic hash function (CHF:
+ * we use SHA1) to "prevent collisions". This is not airtight but 16 hex
+ * digits on uniform probability means you're going to need 2**32 same-name
+ * symbols in the same process before you're even hitting birthday-paradox
+ * collision probability.
+ *
+ * - Symbols in dirrerent crates but with same names "within" the crate need
+ * to get different linkage-names.
+ *
+ * So here is what we do:
+ *
+ * - Separate the meta tags into two sets: exported and local. Only work with
+ * the exported ones when considering linkage.
+ *
+ * - Consider two exported tags as special (and madatory): name and vers.
+ * Every crate gets them; if it doesn't name them explicitly we infer them
+ * as basename(crate) and "0.1", respectively. Call these CNAME, CVERS.
+ *
+ * - Define CMETA as all the non-name, non-vers exported meta tags in the
+ * crate (in sorted order).
+ *
+ * - Define CMH as hash(CMETA).
+ *
+ * - Compile our crate to lib CNAME-CMH-CVERS.so
+ *
+ * - Define STH(sym) as hash(CNAME, CMH, type_str(sym))
+ *
+ * - Suffix a mangled sym with ::STH@CVERS, so that it is unique in the
+ * name, non-name metadata, and type sense, and versioned in the way
+ * system linkers understand.
+ *
+ */
+
+
+iter crate_export_metas(ast::crate c) -> @ast::meta_item {
+ for (@ast::crate_directive cdir in c.node.directives) {
+ alt (cdir.node) {
+ case (ast::cdir_meta(?v, ?mis)) {
+ if (v == ast::export_meta) {
+ for (@ast::meta_item mi in mis) {
+ put mi;
+ }
+ }
+ }
+ case (_) {}
+ }
+ }
+}
+fn get_crate_meta(&session::session sess,
+ &ast::crate c, str k, str default,
+ bool warn_default) -> str {
+ let vec[@ast::meta_item] v = [];
+ for each (@ast::meta_item mi in crate_export_metas(c)) {
+ if (mi.node.name == k) {
+ v += [mi];
+ }
+ }
+ alt (vec::len(v)) {
+ case (0u) {
+ if (warn_default) {
+ sess.warn(#fmt("missing meta '%s', using '%s' as default",
+ k, default));
+ }
+ ret default;
+ }
+ case (1u) {
+ ret v.(0).node.value;
+ }
+ case (_) {
+ sess.span_err(v.(1).span, #fmt("duplicate meta '%s'", k));
+ }
+ }
+}
+
+// This calculates CMH as defined above
+fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
+ fn lteq(&@ast::meta_item ma,
+ &@ast::meta_item mb) -> bool {
+ ret ma.node.name <= mb.node.name;
+ }
+
+ fn len_and_str(&str s) -> str {
+ ret #fmt("%u_%s", str::byte_len(s), s);
+ }
+
+ let vec[mutable @ast::meta_item] v = [mutable];
+ for each (@ast::meta_item mi in crate_export_metas(crate)) {
+ if (mi.node.name != "name" &&
+ mi.node.name != "vers") {
+ v += [mutable mi];
+ }
+ }
+ sort::quick_sort(lteq, v);
+ sha.reset();
+ for (@ast::meta_item m in v) {
+ sha.input_str(len_and_str(m.node.name));
+ sha.input_str(len_and_str(m.node.value));
+ }
+ ret truncated_sha1_result(sha);
+}
+
+fn crate_meta_name(&session::session sess, &ast::crate crate,
+ &str output) -> str {
+ auto os = str::split(fs::basename(output), '.' as u8);
+ assert vec::len(os) >= 2u;
+ vec::pop(os);
+ ret get_crate_meta(sess, crate, "name", str::connect(os, "."),
+ sess.get_opts().shared);
+}
+
+fn crate_meta_vers(&session::session sess, &ast::crate crate) -> str {
+ ret get_crate_meta(sess, crate, "vers", "0.0",
+ sess.get_opts().shared);
+}
+
+fn truncated_sha1_result(sha1 sha) -> str {
+ ret str::substr(sha.result_str(), 0u, 16u);
+}
+
+
+
+// This calculates STH for a symbol, as defined above
+fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t,
+ str crate_meta_name,
+ str crate_meta_extras_hash) -> str {
+ // NB: do *not* use abbrevs here as we want the symbol names
+ // to be independent of one another in the crate.
+ auto cx = @rec(ds=metadata::def_to_str, tcx=tcx,
+ abbrevs=metadata::ac_no_abbrevs);
+ sha.reset();
+ sha.input_str(crate_meta_name);
+ sha.input_str("-");
+ sha.input_str(crate_meta_name);
+ sha.input_str("-");
+ sha.input_str(metadata::Encode::ty_str(cx, t));
+ auto hash = truncated_sha1_result(sha);
+ // Prefix with _ so that it never blends into adjacent digits
+ ret "_" + hash;
+}
+
+fn get_symbol_hash(&@crate_ctxt ccx, &ty::t t) -> str {
+ auto hash = "";
+ alt (ccx.type_sha1s.find(t)) {
+ case (some(?h)) { hash = h; }
+ case (none) {
+ hash = symbol_hash(ccx.tcx, ccx.sha, t,
+ ccx.crate_meta_name,
+ ccx.crate_meta_extras_hash);
+ ccx.type_sha1s.insert(t, hash);
+ }
+ }
+ ret hash;
+}
+
+
+fn mangle(&vec[str] ss) -> str {
+
+ // Follow C++ namespace-mangling style
+
+ auto n = "_ZN"; // Begin name-sequence.
+
+ for (str s in ss) {
+ n += #fmt("%u%s", str::byte_len(s), s);
+ }
+
+ n += "E"; // End name-sequence.
+ ret n;
+}
+
+
+fn exported_name(&vec[str] path, &str hash, &str vers) -> str {
+ // FIXME: versioning isn't working yet
+ ret mangle(path + [hash]); // + "@" + vers;
+}
+
+fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path,
+ &ty::t t) -> str {
+ auto hash = get_symbol_hash(ccx, t);
+ ret exported_name(path, hash, ccx.crate_meta_vers);
+}
+
+fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t,
+ &str name) -> str {
+ auto f = metadata::def_to_str;
+ auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
+ auto s = ty::ty_to_short_str(ccx.tcx, t);
+
+ auto hash = get_symbol_hash(ccx, t);
+ ret mangle([name, s, hash]);
+}
+
+fn mangle_internal_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
+ &str flav) -> str {
+ ret mangle(path + [ccx.names.next(flav)]);
+}
+
+fn mangle_internal_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str {
+ ret mangle(path);
+}
+
+fn mangle_internal_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
+ ret ccx.names.next(flav);
+}
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index e33a2e1c35d..a33416c8638 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -125,7 +125,7 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
pp_mode ppm) {
auto def = tup(ast::local_crate, 0);
auto p = front::parser::new_parser(sess, env, def, input, 0u, 0u);
- auto crate = front::parser::parse_crate_from_source_file(p);
+ auto crate = parse_input(sess, p, input);
auto mode;
alt (ppm) {
diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs
index 9f025849402..e0080ca2651 100644
--- a/src/comp/driver/session.rs
+++ b/src/comp/driver/session.rs
@@ -6,6 +6,9 @@ import std::uint;
import std::term;
import std::io;
import std::map;
+import std::option;
+import std::option::some;
+import std::option::none;
tag os {
os_win32;
@@ -48,9 +51,16 @@ fn span_to_str(span sp, codemap::codemap cm) -> str {
lo.col, hi.line, hi.col));
}
-fn emit_diagnostic(span sp, str msg, str kind, u8 color,
+fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
codemap::codemap cm) {
- io::stdout().write_str(span_to_str(sp, cm) + ": ");
+ auto ss = ":0:0:0:0";
+ alt (sp) {
+ case (some(?ssp)) {
+ ss = span_to_str(ssp, cm);
+ }
+ case (none) {}
+ }
+ io::stdout().write_str(ss + ": ");
if (term::color_supported()) {
term::fg(io::stdout().get_buf_writer(), color);
@@ -85,12 +95,12 @@ state obj session(ast::crate_num cnum,
fn span_err(span sp, str msg) -> ! {
// FIXME: Use constants, but rustboot doesn't know how to export them.
- emit_diagnostic(sp, msg, "error", 9u8, cm);
+ emit_diagnostic(some(sp), msg, "error", 9u8, cm);
fail;
}
fn err(str msg) -> ! {
- log_err #fmt("error: %s", msg);
+ emit_diagnostic(none[span], msg, "error", 9u8, cm);
fail;
}
@@ -103,29 +113,32 @@ state obj session(ast::crate_num cnum,
fn span_warn(span sp, str msg) {
// FIXME: Use constants, but rustboot doesn't know how to export them.
- emit_diagnostic(sp, msg, "warning", 11u8, cm);
+ emit_diagnostic(some(sp), msg, "warning", 11u8, cm);
+ }
+
+ fn warn(str msg) {
+ emit_diagnostic(none[span], msg, "warning", 11u8, cm);
}
fn span_note(span sp, str msg) {
// FIXME: Use constants, but rustboot doesn't know how to export them.
- emit_diagnostic(sp, msg, "note", 10u8, cm);
+ emit_diagnostic(some(sp), msg, "note", 10u8, cm);
+ }
+
+ fn span_bug(span sp, str msg) -> ! {
+ self.span_err(sp, #fmt("internal compiler error %s", msg));
}
fn bug(str msg) -> ! {
- log_err #fmt("error: internal compiler error %s", msg);
- fail;
+ self.err(#fmt("internal compiler error %s", msg));
}
fn span_unimpl(span sp, str msg) -> ! {
- // FIXME: Use constants, but rustboot doesn't know how to export them.
- emit_diagnostic(sp, "internal compiler error: unimplemented " + msg,
- "error", 9u8, cm);
- fail;
+ self.span_bug(sp, "unimplemented " + msg);
}
-
+
fn unimpl(str msg) -> ! {
- log_err #fmt("error: unimplemented %s", msg);
- fail;
+ self.bug("unimplemented " + msg);
}
fn get_external_crate(int num) -> crate_metadata {
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index 92f12c3dc1b..f670c2760a7 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -71,6 +71,11 @@ type crate = spanned[crate_];
type crate_ = rec(vec[@crate_directive] directives,
_mod module);
+tag meta_visibility {
+ export_meta;
+ local_meta;
+}
+
tag crate_directive_ {
cdir_expr(@expr);
// FIXME: cdir_let should be eliminated
@@ -80,7 +85,7 @@ tag crate_directive_ {
cdir_src_mod(ident, option::t[filename]);
cdir_dir_mod(ident, option::t[filename], vec[@crate_directive]);
cdir_view_item(@view_item);
- cdir_meta(vec[@meta_item]);
+ cdir_meta(meta_visibility, vec[@meta_item]);
cdir_syntax(path);
cdir_auth(path, _auth);
}
diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs
index d5a76372846..a8e881ee036 100644
--- a/src/comp/front/eval.rs
+++ b/src/comp/front/eval.rs
@@ -418,8 +418,13 @@ fn eval_crate_directive(ctx cx,
vec::push[@ast::view_item](view_items, vi);
}
- case (ast::cdir_meta(?mi)) {
- cx.sess.add_metadata(mi);
+ case (ast::cdir_meta(?vi, ?mi)) {
+ // FIXME: we should actually record, for documentation-sake,
+ // the metadata that's not exported. It would be nice to have
+ // compiled-in to the target crate, not just in theh AST.
+ if (vi == ast::export_meta) {
+ cx.sess.add_metadata(mi);
+ }
}
case (ast::cdir_syntax(?pth)) {}
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index 62ba7325f99..b84a740a917 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -2362,10 +2362,14 @@ fn parse_crate_directive(&parser p) -> ast::crate_directive
expect(p, token::SEMI);
ret spanned(lo, hi, ast::cdir_auth(n, a));
} else if (eat_word(p, "meta")) {
+ auto mv = ast::local_meta;
+ if (eat_word(p, "export")) {
+ mv = ast::export_meta;
+ }
auto mis = parse_meta(p);
auto hi = p.get_hi_pos();
expect(p, token::SEMI);
- ret spanned(lo, hi, ast::cdir_meta(mis));
+ ret spanned(lo, hi, ast::cdir_meta(mv, mis));
} else if (eat_word(p, "mod")) {
auto id = parse_ident(p);
auto file_opt = none[filename];
diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs
index e2e60b80075..59f3cf56387 100644
--- a/src/comp/middle/metadata.rs
+++ b/src/comp/middle/metadata.rs
@@ -230,17 +230,6 @@ mod Encode {
}
case (ty::ty_type) {w.write_char('Y');}
case (ty::ty_task) {w.write_char('a');}
-
- // These two don't appear in crate metadata, but are here because
- // `hash_ty()` uses this function.
- case (ty::ty_bound_param(?id)) {
- w.write_char('o');
- w.write_str(common::uistr(id));
- }
- case (ty::ty_local(?def)) {
- w.write_char('L');
- w.write_str(cx.ds(def));
- }
}
}
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 4230032f7ee..01192deb8da 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -6,7 +6,7 @@
// particular definition to the LLVM IR output we're producing.
//
// Hopefully useful general knowledge about trans:
-//
+//
// * There's no way to find out the ty::t type of a ValueRef. Doing so
// would be "trying to get the eggs out of an omelette" (credit:
// pcwalton). You can, instead, find out its TypeRef by calling val_ty,
@@ -24,6 +24,7 @@ import std::map::hashmap;
import std::option;
import std::option::some;
import std::option::none;
+import std::fs;
import front::ast;
import front::creader;
@@ -62,6 +63,15 @@ import lib::llvm::False;
import lib::llvm::True;
import lib::llvm::Bool;
+import link::mangle_internal_name_by_type_only;
+import link::mangle_internal_name_by_seq;
+import link::mangle_internal_name_by_path;
+import link::mangle_internal_name_by_path_and_seq;
+import link::mangle_exported_name;
+import link::crate_meta_name;
+import link::crate_meta_vers;
+import link::crate_meta_extras_hash;
+
state obj namegen(mutable int i) {
fn next(str prefix) -> str {
i += 1;
@@ -119,6 +129,9 @@ state type crate_ctxt = rec(session::session sess,
@ast::native_item] native_items,
hashmap[ast::def_id, str] item_symbols,
mutable option::t[ValueRef] main_fn,
+ str crate_meta_name,
+ str crate_meta_vers,
+ str crate_meta_extras_hash,
// TODO: hashmap[tup(tag_id,subtys), @tag_info]
hashmap[ty::t, uint] tag_sizes,
hashmap[ast::def_id, ValueRef] discrims,
@@ -166,14 +179,14 @@ type fn_ctxt = rec(
ValueRef lltaskptr,
ValueRef llenv,
ValueRef llretptr,
-
+
// The next three elements: "hoisted basic blocks" containing
// administrative activities that have to happen in only one place in the
// function, due to LLVM's quirks.
// A block for all the function's allocas, so that LLVM will coalesce them
// into a single alloca call.
- mutable BasicBlockRef llallocas,
+ mutable BasicBlockRef llallocas,
// A block containing code that copies incoming arguments to space already
// allocated by code in the llallocas block. (LLVM requires that
@@ -313,70 +326,6 @@ fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
ret @rec(path = cx.path + [name] with *cx);
}
-fn get_type_sha1(&@crate_ctxt ccx, &ty::t t) -> str {
- auto hash = "";
- alt (ccx.type_sha1s.find(t)) {
- case (some(?h)) { hash = h; }
- case (none) {
- ccx.sha.reset();
- auto f = metadata::def_to_str;
- // NB: do *not* use abbrevs here as we want the symbol names
- // to be independent of one another in the crate.
- auto cx = @rec(ds=f,
- tcx=ccx.tcx,
- abbrevs=metadata::ac_no_abbrevs);
-
- ccx.sha.input_str(metadata::Encode::ty_str(cx, t));
- hash = str::substr(ccx.sha.result_str(), 0u, 16u);
- // Prefix with _ so that it never blends into adjacent digits
- hash = "_" + hash;
- ccx.type_sha1s.insert(t, hash);
- }
- }
- ret hash;
-}
-
-fn mangle(&vec[str] ss) -> str {
-
- // Follow C++ namespace-mangling style
-
- auto n = "_ZN"; // Begin name-sequence.
-
- for (str s in ss) {
- n += #fmt("%u%s", str::byte_len(s), s);
- }
-
- n += "E"; // End name-sequence.
- ret n;
-}
-
-fn mangle_name_by_type(&@crate_ctxt ccx, &vec[str] path, &ty::t t) -> str {
- auto hash = get_type_sha1(ccx, t);
- ret mangle(path + [hash]);
-}
-
-fn mangle_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) -> str {
- auto f = metadata::def_to_str;
- auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
- auto s = ty::ty_to_short_str(ccx.tcx, t);
-
- auto hash = get_type_sha1(ccx, t);
- ret mangle([name, s, hash]);
-}
-
-fn mangle_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
- &str flav) -> str {
- ret mangle(path + [ccx.names.next(flav)]);
-}
-
-fn mangle_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str {
- ret mangle(path);
-}
-
-fn mangle_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
- ret ccx.names.next(flav);
-}
-
fn res(@block_ctxt bcx, ValueRef val) -> result {
ret rec(bcx = bcx,
val = val);
@@ -955,10 +904,6 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
case (ty::ty_param(_)) {
llty = T_i8();
}
- case (ty::ty_bound_param(_)) {
- cx.tcx.sess.span_err(sp,
- "trans::type_of called on ty_bound_param");
- }
case (ty::ty_type) { llty = T_ptr(T_tydesc(cx.tn)); }
}
@@ -1350,7 +1295,6 @@ fn static_size_of_tag(&@crate_ctxt cx, &span sp, &ty::t t) -> uint {
auto tup_ty = simplify_type(cx, ty::mk_imm_tup(cx.tcx, variant.args));
// Perform any type parameter substitutions.
- tup_ty = ty::bind_params_in_type(cx.tcx, tup_ty);
tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
// Here we possibly do a recursive call.
@@ -1424,10 +1368,8 @@ fn dynamic_size_of(&@block_ctxt cx, ty::t t) -> result {
let vec[ty::t] raw_tys = variant.args;
let vec[ty::t] tys = [];
for (ty::t raw_ty in raw_tys) {
- auto t = ty::bind_params_in_type(cx.fcx.lcx.ccx.tcx,
- raw_ty);
- t = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx, tps,
- t);
+ auto t = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
+ tps, raw_ty);
tys += [t];
}
@@ -1604,9 +1546,8 @@ fn GEP_tag(@block_ctxt cx,
auto i = 0;
let vec[ty::t] true_arg_tys = [];
for (ty::t aty in arg_tys) {
- auto arg_ty = ty::bind_params_in_type(cx.fcx.lcx.ccx.tcx, aty);
- arg_ty = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx, ty_substs,
- arg_ty);
+ auto arg_ty = ty::substitute_type_params(cx.fcx.lcx.ccx.tcx,
+ ty_substs, aty);
true_arg_tys += [arg_ty];
if (i == ix) {
elem_ty = arg_ty;
@@ -1914,10 +1855,10 @@ fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
auto name;
if (cx.ccx.sess.get_opts().debuginfo) {
- name = mangle_name_by_type_only(cx.ccx, t, "tydesc");
+ name = mangle_internal_name_by_type_only(cx.ccx, t, "tydesc");
name = sanitize(name);
} else {
- name = mangle_name_by_seq(cx.ccx, "tydesc");
+ name = mangle_internal_name_by_seq(cx.ccx, "tydesc");
}
auto gvar = llvm::LLVMAddGlobal(ccx.llmod, T_tydesc(ccx.tn),
@@ -1948,10 +1889,12 @@ fn declare_generic_glue(&@local_ctxt cx,
&str name) -> ValueRef {
auto fn_nm;
if (cx.ccx.sess.get_opts().debuginfo) {
- fn_nm = mangle_name_by_type_only(cx.ccx, t, "glue_" + name);
+ fn_nm = mangle_internal_name_by_type_only(cx.ccx, t,
+ "glue_" + name);
fn_nm = sanitize(fn_nm);
} else {
- fn_nm = mangle_name_by_seq(cx.ccx, "glue_" + name);
+ fn_nm = mangle_internal_name_by_seq(cx.ccx,
+ "glue_" + name);
}
auto llfn = decl_fastcall_fn(cx.ccx.llmod, fn_nm, llfnty);
set_glue_inlining(cx, llfn, t);
@@ -2794,10 +2737,8 @@ fn iter_structural_ty_full(&@block_ctxt cx,
auto llfldp_b = rslt.val;
variant_cx = rslt.bcx;
- auto ty_subst = ty::bind_params_in_type(
- cx.fcx.lcx.ccx.tcx, a.ty);
- ty_subst = ty::substitute_type_params(
- cx.fcx.lcx.ccx.tcx, tps, ty_subst);
+ auto ty_subst = ty::substitute_type_params(
+ cx.fcx.lcx.ccx.tcx, tps, a.ty);
auto llfld_a =
load_if_immediate(variant_cx,
@@ -3684,13 +3625,11 @@ fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
v1 = load_if_immediate(cx, v1, t1);
}
- case (_) {
- ret res(cx, v1);
- }
+ case (_) { break; }
}
}
- fail; // fools the return-checker
+ ret res(cx, v1);
}
fn autoderefed_ty(&@crate_ctxt ccx, &ty::t t) -> ty::t {
@@ -3701,13 +3640,11 @@ fn autoderefed_ty(&@crate_ctxt ccx, &ty::t t) -> ty::t {
case (ty::ty_box(?mt)) {
t1 = mt.ty;
}
- case (_) {
- ret t1;
- }
+ case (_) { break; }
}
}
- fail; // fools the return-checker
+ ret t1;
}
fn trans_binary(&@block_ctxt cx, ast::binop op,
@@ -3873,7 +3810,7 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
}
// FIXME: This isn't quite right, particularly re: dynamic types
- auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types,
+ auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx,
ann);
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
@@ -4107,7 +4044,8 @@ fn trans_for_each(&@block_ctxt cx,
// Step 2: Declare foreach body function.
- let str s = mangle_name_by_path_and_seq(lcx.ccx, lcx.path, "foreach");
+ let str s = mangle_internal_name_by_path_and_seq(lcx.ccx, lcx.path,
+ "foreach");
// The 'env' arg entering the body function is a fake env member (as in
// the env-part of the normal rust calling convention) that actually
@@ -4257,7 +4195,7 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
case (ast::pat_lit(?lt, ?ann)) {
auto lllit = trans_lit(cx.fcx.lcx.ccx, *lt, ann);
- auto lltype = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
+ auto lltype = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
auto lleq = trans_compare(cx, ast::eq, lltype, llval, lllit);
auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx");
@@ -4295,7 +4233,7 @@ fn trans_pat_match(&@block_ctxt cx, &@ast::pat pat, ValueRef llval,
cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
auto ty_params =
- ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx.node_types, ann);
+ ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx, ann);
if (vec::len[@ast::pat](subpats) > 0u) {
auto llblobptr = matched_cx.build.GEP(lltagptr,
@@ -4356,7 +4294,7 @@ fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat,
auto llblobptr = cx.build.GEP(lltagptr, [C_int(0), C_int(1)]);
auto ty_param_substs =
- ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx.node_types, ann);
+ ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx, ann);
auto this_cx = cx;
auto i = 0;
@@ -4405,7 +4343,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
"non-exhaustive match failure");
// FIXME: This isn't quite right, particularly re: dynamic types
- auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
+ auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
auto expr_llty;
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
@@ -4470,8 +4408,8 @@ fn lval_generic_fn(&@block_ctxt cx,
lv = trans_external_path(cx, fn_id, tpt);
}
- auto tys = ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx.node_types, ann);
- auto monoty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
+ auto tys = ty::ann_to_type_params(cx.fcx.lcx.ccx.tcx, ann);
+ auto monoty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
if (vec::len[ty::t](tys) != 0u) {
auto bcx = lv.res.bcx;
@@ -4806,7 +4744,8 @@ fn trans_bind_thunk(&@local_ctxt cx,
// Construct a thunk-call with signature incoming_fty, and that copies
// args forward into a call to outgoing_fty:
- let str s = mangle_name_by_path_and_seq(cx.ccx, cx.path, "thunk");
+ let str s = mangle_internal_name_by_path_and_seq(cx.ccx, cx.path,
+ "thunk");
let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx.ccx, sp,
incoming_fty));
let ValueRef llthunk = decl_internal_fastcall_fn(cx.ccx.llmod,
@@ -5358,7 +5297,8 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f,
}
- auto ret_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types, ann);
+ auto ret_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx, ann);
+
auto args_res = trans_args(f_res.res.bcx,
llenv, f_res.llobj,
f_res.generic,
@@ -5824,13 +5764,17 @@ fn load_if_immediate(&@block_ctxt cx, ValueRef v, &ty::t t) -> ValueRef {
fn trans_log(int lvl, &@block_ctxt cx, &@ast::expr e) -> result {
auto lcx = cx.fcx.lcx;
- auto modname = str::connect(lcx.module_path, "::");
+ auto modname = link::mangle_internal_name_by_path(lcx.ccx,
+ lcx.module_path);
auto global;
if (lcx.ccx.module_data.contains_key(modname)) {
global = lcx.ccx.module_data.get(modname);
} else {
- global = llvm::LLVMAddGlobal(lcx.ccx.llmod, T_int(),
- str::buf("_rust_mod_log_" + modname));
+ auto s =
+ link::mangle_internal_name_by_path_and_seq(lcx.ccx,
+ lcx.module_path,
+ "loglevel");
+ global = llvm::LLVMAddGlobal(lcx.ccx.llmod, T_int(), str::buf(s));
llvm::LLVMSetGlobalConstant(global, False);
llvm::LLVMSetInitializer(global, C_null(T_int()));
llvm::LLVMSetLinkage(global, lib::llvm::LLVMInternalLinkage
@@ -6226,8 +6170,8 @@ fn trans_spawn(&@block_ctxt cx,
ret res(bcx, new_task);
}
-fn mk_spawn_wrapper(&@block_ctxt cx,
- &@ast::expr func,
+fn mk_spawn_wrapper(&@block_ctxt cx,
+ &@ast::expr func,
&ty::t args_ty) -> result {
auto llmod = cx.fcx.lcx.ccx.llmod;
let TypeRef args_ty_tref = type_of(cx.fcx.lcx.ccx, cx.sp, args_ty);
@@ -6240,9 +6184,9 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
// TODO: construct a name based on tname
let str wrap_name =
- mangle_name_by_path_and_seq(cx.fcx.lcx.ccx,
- cx.fcx.lcx.path,
- "spawn_wrapper");
+ mangle_internal_name_by_path_and_seq(cx.fcx.lcx.ccx,
+ cx.fcx.lcx.path,
+ "spawn_wrapper");
auto llfndecl = decl_fastcall_fn(llmod, wrap_name,
wrapper_fn_type);
@@ -6253,7 +6197,7 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
// 3u to skip the three implicit args
let ValueRef arg = llvm::LLVMGetParam(fcx.llfn, 3u);
- let vec[ValueRef] child_args =
+ let vec[ValueRef] child_args =
[llvm::LLVMGetParam(fcx.llfn, 0u),
llvm::LLVMGetParam(fcx.llfn, 1u),
llvm::LLVMGetParam(fcx.llfn, 2u)];
@@ -6272,19 +6216,19 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
}
}
}
-
+
// Find the function
auto fnptr = trans_lval(fbcx, func).res;
fbcx = fnptr.bcx;
-
+
auto llfnptr = fbcx.build.GEP(fnptr.val,
[C_int(0), C_int(0)]);
auto llfn = fbcx.build.Load(llfnptr);
-
+
fbcx.build.FastCall(llfn,
child_args);
fbcx.build.RetVoid();
-
+
finish_fn(fcx, fbcx.llbb);
// TODO: make sure we clean up everything we need to.
@@ -6720,7 +6664,7 @@ fn new_local_ctxt(&@crate_ctxt ccx) -> @local_ctxt {
let vec[ast::ty_param] obj_typarams = [];
let vec[ast::obj_field] obj_fields = [];
ret @rec(path=pth,
- module_path=[crate_name(ccx, "main")],
+ module_path=[ccx.crate_meta_name],
obj_typarams = obj_typarams,
obj_fields = obj_fields,
ccx = ccx);
@@ -6907,7 +6851,7 @@ fn is_terminated(&@block_ctxt cx) -> bool {
}
fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
- alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx.node_types, ann))) {
+ alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx, ann))) {
case (ty::ty_fn(_, ?arg_tys, _, _)) {
ret arg_tys;
}
@@ -6924,7 +6868,7 @@ fn ret_ty_of_fn_ty(&@crate_ctxt ccx, ty::t t) -> ty::t {
fn ret_ty_of_fn(&@crate_ctxt ccx, ast::ann ann) -> ty::t {
- ret ret_ty_of_fn_ty(ccx, ty::ann_to_type(ccx.tcx.node_types, ann));
+ ret ret_ty_of_fn_ty(ccx, ty::ann_to_type(ccx.tcx, ann));
}
fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, val_self_pair llself) {
@@ -7095,7 +7039,7 @@ fn create_vtbl(@local_ctxt cx,
let @local_ctxt mcx = @rec(path = cx.path + ["method",
m.node.ident] with *cx);
- let str s = mangle_name_by_path(mcx.ccx, mcx.path);
+ let str s = mangle_internal_name_by_path(mcx.ccx, mcx.path);
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s,
llfnty);
cx.ccx.item_ids.insert(m.node.id, llfn);
@@ -7107,7 +7051,8 @@ fn create_vtbl(@local_ctxt cx,
methods += [llfn];
}
auto vtbl = C_struct(methods);
- auto vtbl_name = mangle_name_by_path(cx.ccx, cx.path + ["vtbl"]);
+ auto vtbl_name = mangle_internal_name_by_path(cx.ccx,
+ cx.path + ["vtbl"]);
auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl),
str::buf(vtbl_name));
llvm::LLVMSetInitializer(gvar, vtbl);
@@ -7124,7 +7069,7 @@ fn trans_dtor(@local_ctxt cx,
&@ast::method dtor) -> ValueRef {
auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty);
- let str s = mangle_name_by_path(cx.ccx, cx.path + ["drop"]);
+ let str s = mangle_internal_name_by_path(cx.ccx, cx.path + ["drop"]);
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty);
cx.ccx.item_ids.insert(dtor.node.id, llfn);
cx.ccx.item_symbols.insert(dtor.node.id, s);
@@ -7517,23 +7462,29 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp,
}
}
+ let bool is_main = (str::eq(vec::top(path), "main") &&
+ !ccx.sess.get_opts().shared);
+
// Declare the function itself.
- let str s = mangle_name_by_path(ccx, path);
+ let str s =
+ if (is_main) { "_rust_main" }
+ else { mangle_internal_name_by_path(ccx, path) };
+
let ValueRef llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfty);
// Declare the global constant pair that points to it.
- let str ps = mangle_name_by_type(ccx, path, node_ann_type(ccx, ann));
-
+ let str ps = mangle_exported_name(ccx, path, node_ann_type(ccx, ann));
register_fn_pair(ccx, ps, llpairty, llfn, id);
- if (str::eq(vec::top(path), "main") &&
- !ccx.sess.get_opts().shared) {
+ if (is_main) {
if (ccx.main_fn != none[ValueRef]) {
ccx.sess.span_err(sp, "multiple 'main' functions");
}
- log #fmt("registering %s as main function for crate", ps);
+ llvm::LLVMSetLinkage(llfn, lib::llvm::LLVMExternalLinkage
+ as llvm::Linkage);
ccx.main_fn = some(llfn);
}
+
}
fn register_fn_pair(&@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn,
@@ -7564,7 +7515,7 @@ fn native_fn_ty_param_count(&@crate_ctxt cx, &ast::def_id id) -> uint {
alt (native_item.node) {
case (ast::native_item_ty(_,_)) {
cx.sess.bug("decl_native_fn_and_pair(): native fn isn't " +
- "actually a fn?!");
+ "actually a fn");
}
case (ast::native_item_fn(_, _, _, ?tps, _, _)) {
count = vec::len[ast::ty_param](tps);
@@ -7592,14 +7543,15 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx,
// Declare the wrapper.
auto t = node_ann_type(ccx, ann);
+
auto wrapper_type = native_fn_wrapper_type(ccx, sp, num_ty_param, t);
- let str s = mangle_name_by_path(ccx, path);
+ let str s = mangle_internal_name_by_path(ccx, path);
let ValueRef wrapper_fn = decl_internal_fastcall_fn(ccx.llmod, s,
wrapper_type);
// Declare the global constant pair that points to it.
auto wrapper_pair_type = T_fn_pair(ccx.tn, wrapper_type);
- let str ps = mangle_name_by_type(ccx, path, node_ann_type(ccx, ann));
+ let str ps = mangle_exported_name(ccx, path, node_ann_type(ccx, ann));
register_fn_pair(ccx, ps, wrapper_pair_type, wrapper_fn, id);
@@ -7937,7 +7889,7 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
auto discrim_val = C_int(i as int);
auto p = wcx.path + [ident, variant.node.name, "discrim"];
- auto s = mangle_name_by_type(ccx, p, ty::mk_int(ccx.tcx));
+ auto s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
auto discrim_gvar = llvm::LLVMAddGlobal(ccx.llmod, T_int(),
str::buf(s));
@@ -7956,8 +7908,8 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
// with consts.
auto v = C_int(1);
ccx.item_ids.insert(cid, v);
- auto s = mangle_name_by_type(ccx, wcx.path + [name],
- node_ann_type(ccx, ann));
+ auto s = mangle_exported_name(ccx, wcx.path + [name],
+ node_ann_type(ccx, ann));
ccx.item_symbols.insert(cid, s);
}
@@ -7996,51 +7948,6 @@ fn create_typedefs(&@crate_ctxt cx) {
llvm::LLVMAddTypeName(cx.llmod, str::buf("tydesc"), T_tydesc(cx.tn));
}
-fn trans_main_fn(@local_ctxt cx, ValueRef crate_map) {
- auto T_main_args = [T_int(), T_int()];
- auto T_rust_start_args = [T_int(), T_int(), T_int(), T_int()];
-
- auto main_name;
- if (str::eq(std::os::target_os(), "win32")) {
- main_name = "WinMain@16";
- } else {
- main_name = "main";
- }
-
- auto llmain =
- decl_cdecl_fn(cx.ccx.llmod, main_name, T_fn(T_main_args, T_int()));
-
- auto llrust_start = decl_cdecl_fn(cx.ccx.llmod, "rust_start",
- T_fn(T_rust_start_args, T_int()));
-
- auto llargc = llvm::LLVMGetParam(llmain, 0u);
- auto llargv = llvm::LLVMGetParam(llmain, 1u);
- auto llrust_main = alt (cx.ccx.main_fn) {
- case (none) {
- cx.ccx.sess.err("missing 'main' function");
- // FIXME: shouldn't sess.err's ! result unify with f?
- C_nil()
- }
- case (some(?f)) { f }
- };
-
- //
- // Emit the moral equivalent of:
- //
- // main(int argc, char **argv) {
- // rust_start(&_rust.main, argc, argv);
- // }
- //
-
- let BasicBlockRef llbb =
- llvm::LLVMAppendBasicBlock(llmain, str::buf(""));
- auto b = new_builder(llbb);
-
- auto start_args = [p2i(llrust_main), llargc, llargv, p2i(crate_map)];
-
- b.Ret(b.Call(llrust_start, start_args));
-}
-
fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] {
let vec[TypeRef] T_memmove32_args = [T_ptr(T_i8()), T_ptr(T_i8()),
@@ -8211,8 +8118,6 @@ fn create_module_map(&@crate_ctxt ccx) -> ValueRef {
auto maptype = T_array(elttype, ccx.module_data.size() + 1u);
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype,
str::buf("_rust_mod_map"));
- llvm::LLVMSetLinkage(map, lib::llvm::LLVMInternalLinkage
- as llvm::Linkage);
let vec[ValueRef] elts = [];
for each (@tup(str, ValueRef) item in ccx.module_data.items()) {
auto elt = C_struct([p2i(C_cstr(ccx, item._0)), p2i(item._1)]);
@@ -8224,15 +8129,6 @@ fn create_module_map(&@crate_ctxt ccx) -> ValueRef {
ret map;
}
-fn crate_name(&@crate_ctxt ccx, &str deflt) -> str {
- for (@ast::meta_item item in ccx.sess.get_metadata()) {
- if (str::eq(item.node.name, "name")) {
- ret item.node.value;
- }
- }
- ret deflt;
-}
-
// FIXME use hashed metadata instead of crate names once we have that
fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
let vec[ValueRef] subcrates = [];
@@ -8245,7 +8141,13 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
i += 1;
}
vec::push[ValueRef](subcrates, C_int(0));
- auto sym_name = "_rust_crate_map_" + crate_name(ccx, "__none__");
+ auto mapname;
+ if (ccx.sess.get_opts().shared) {
+ mapname = ccx.crate_meta_name;
+ } else {
+ mapname = "toplevel";
+ }
+ auto sym_name = "_rust_crate_map_" + mapname;
auto arrtype = T_array(T_int(), vec::len[ValueRef](subcrates));
auto maptype = T_struct([T_int(), arrtype]);
auto map = llvm::LLVMAddGlobal(ccx.llmod, maptype, str::buf(sym_name));
@@ -8279,7 +8181,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
auto sha1s = map::mk_hashmap[ty::t,str](hasher, eqer);
auto abbrevs = map::mk_hashmap[ty::t,metadata::ty_abbrev](hasher, eqer);
auto short_names = map::mk_hashmap[ty::t,str](hasher, eqer);
-
+ auto sha = std::sha1::mk_sha1();
auto ccx = @rec(sess = sess,
llmod = llmod,
td = td,
@@ -8291,6 +8193,10 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
native_items = new_def_hash[@ast::native_item](),
item_symbols = new_def_hash[str](),
mutable main_fn = none[ValueRef],
+ crate_meta_name = crate_meta_name(sess, *crate, output),
+ crate_meta_vers = crate_meta_vers(sess, *crate),
+ crate_meta_extras_hash =
+ crate_meta_extras_hash(sha, *crate),
tag_sizes = tag_sizes,
discrims = new_def_hash[ValueRef](),
discrim_symbols = new_def_hash[str](),
@@ -8302,7 +8208,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
lltypes = lltypes,
glues = glues,
names = namegen(0),
- sha = std::sha1::mk_sha1(),
+ sha = sha,
type_sha1s = sha1s,
type_abbrevs = abbrevs,
type_short_names = short_names,
@@ -8322,9 +8228,17 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
trans_constants(ccx, crate);
trans_mod(cx, crate.node.module);
auto crate_map = create_crate_map(ccx);
+
if (!sess.get_opts().shared) {
- trans_main_fn(cx, crate_map);
- }
+ auto gvar = llvm::LLVMAddGlobal(cx.ccx.llmod, T_ptr(T_int()),
+ str::buf("_rust_fetch_this_object_hack"));
+
+ auto gvar2 = llvm::LLVMAddGlobal(cx.ccx.llmod, T_ptr(T_ptr(T_int())),
+ str::buf("_rust_fetch_this_object_hack2"));
+ llvm::LLVMSetInitializer(gvar2, gvar);
+ llvm::LLVMSetGlobalConstant(gvar, True);
+ llvm::LLVMSetGlobalConstant(gvar2, True);
+ }
emit_tydescs(ccx);
diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs
index 4aa178d6c5c..b801954b933 100644
--- a/src/comp/middle/tstate/auxiliary.rs
+++ b/src/comp/middle/tstate/auxiliary.rs
@@ -482,7 +482,7 @@ fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow {
If it has a function type with a ! annotation,
the answer is noreturn. */
fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
- alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx.node_types,
+ alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx,
expr_ann(e)))) {
case (ty::ty_fn(_,_,_,?cf)) {
ret cf;
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 9095f9e9c52..3d0c612a085 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -9,6 +9,7 @@ import std::map::hashmap;
import std::option;
import std::option::none;
import std::option::some;
+import std::smallintmap;
import driver::session;
import front::ast;
@@ -88,9 +89,7 @@ type raw_t = rec(sty struct,
option::t[str] cname,
uint hash,
bool has_params,
- bool has_bound_params,
- bool has_vars,
- bool has_locals);
+ bool has_vars);
type t = uint;
@@ -118,10 +117,8 @@ tag sty {
ty_fn(ast::proto, vec[arg], t, controlflow);
ty_native_fn(ast::native_abi, vec[arg], t);
ty_obj(vec[method]);
- ty_var(int); // ephemeral type var
- ty_local(ast::def_id); // type of a local var
+ ty_var(int); // type variable
ty_param(uint); // fn/tag type param
- ty_bound_param(uint); // bound param, only paths
ty_type;
ty_native;
// TODO: ty_fn_arg(t), for a possibly-aliased function argument
@@ -129,12 +126,6 @@ tag sty {
// Data structures used in type unification
-type unify_handler = obj {
- fn resolve_local(ast::def_id id) -> option::t[t];
- fn record_local(ast::def_id id, t ty); // TODO: -> unify::result
- fn record_param(uint index, t binding) -> unify::result;
-};
-
tag type_err {
terr_mismatch;
terr_controlflow_mismatch;
@@ -259,132 +250,101 @@ fn mk_raw_ty(&ctxt cx, &sty st, &option::t[str] cname) -> raw_t {
auto h = hash_type_info(st, cname);
let bool has_params = false;
- let bool has_bound_params = false;
let bool has_vars = false;
- let bool has_locals = false;
fn derive_flags_t(&ctxt cx,
&mutable bool has_params,
- &mutable bool has_bound_params,
&mutable bool has_vars,
- &mutable bool has_locals,
&t tt) {
auto rt = interner::get[raw_t](*cx.ts, tt);
has_params = has_params || rt.has_params;
- has_bound_params = has_bound_params || rt.has_bound_params;
has_vars = has_vars || rt.has_vars;
- has_locals = has_locals || rt.has_locals;
}
fn derive_flags_mt(&ctxt cx,
&mutable bool has_params,
- &mutable bool has_bound_params,
&mutable bool has_vars,
- &mutable bool has_locals,
&mt m) {
- derive_flags_t(cx, has_params, has_bound_params,
- has_vars, has_locals, m.ty);
+ derive_flags_t(cx, has_params, has_vars, m.ty);
}
fn derive_flags_arg(&ctxt cx,
&mutable bool has_params,
- &mutable bool has_bound_params,
&mutable bool has_vars,
- &mutable bool has_locals,
&arg a) {
- derive_flags_t(cx, has_params, has_bound_params,
- has_vars, has_locals, a.ty);
+ derive_flags_t(cx, has_params, has_vars, a.ty);
}
fn derive_flags_sig(&ctxt cx,
&mutable bool has_params,
- &mutable bool has_bound_params,
&mutable bool has_vars,
- &mutable bool has_locals,
&vec[arg] args,
&t tt) {
for (arg a in args) {
- derive_flags_arg(cx, has_params, has_bound_params,
- has_vars, has_locals, a);
+ derive_flags_arg(cx, has_params, has_vars, a);
}
- derive_flags_t(cx, has_params, has_bound_params,
- has_vars, has_locals, tt);
+ derive_flags_t(cx, has_params, has_vars, tt);
}
alt (st) {
case (ty_param(_)) {
has_params = true;
}
- case (ty_bound_param(_)) {
- has_bound_params = true;
- }
case (ty_var(_)) { has_vars = true; }
- case (ty_local(_)) { has_locals = true; }
case (ty_tag(_, ?tys)) {
for (t tt in tys) {
- derive_flags_t(cx, has_params, has_bound_params,
- has_vars, has_locals, tt);
+ derive_flags_t(cx, has_params, has_vars, tt);
}
}
case (ty_box(?m)) {
- derive_flags_mt(cx, has_params, has_bound_params,
- has_vars, has_locals, m);
+ derive_flags_mt(cx, has_params, has_vars, m);
}
case (ty_vec(?m)) {
- derive_flags_mt(cx, has_params, has_bound_params,
- has_vars, has_locals, m);
+ derive_flags_mt(cx, has_params, has_vars, m);
}
case (ty_port(?tt)) {
- derive_flags_t(cx, has_params, has_bound_params,
- has_vars, has_locals, tt);
+ derive_flags_t(cx, has_params, has_vars, tt);
}
case (ty_chan(?tt)) {
- derive_flags_t(cx, has_params, has_bound_params,
- has_vars, has_locals, tt);
+ derive_flags_t(cx, has_params, has_vars, tt);
}
case (ty_tup(?mts)) {
for (mt m in mts) {
- derive_flags_mt(cx, has_params, has_bound_params,
- has_vars, has_locals, m);
+ derive_flags_mt(cx, has_params, has_vars, m);
}
}
case (ty_rec(?flds)) {
for (field f in flds) {
- derive_flags_mt(cx, has_params, has_bound_params,
- has_vars, has_locals, f.mt);
+ derive_flags_mt(cx, has_params, has_vars, f.mt);
}
}
case (ty_fn(_, ?args, ?tt, _)) {
- derive_flags_sig(cx, has_params, has_bound_params,
- has_vars, has_locals, args, tt);
+ derive_flags_sig(cx, has_params, has_vars, args, tt);
}
case (ty_native_fn(_, ?args, ?tt)) {
- derive_flags_sig(cx, has_params, has_bound_params,
- has_vars, has_locals, args, tt);
+ derive_flags_sig(cx, has_params, has_vars, args, tt);
}
case (ty_obj(?meths)) {
for (method m in meths) {
- derive_flags_sig(cx, has_params, has_bound_params,
- has_vars, has_locals, m.inputs, m.output);
+ derive_flags_sig(cx, has_params, has_vars, m.inputs,
+ m.output);
}
}
case (_) { }
}
ret rec(struct=st, cname=cname, hash=h,
- has_params = has_params,
- has_bound_params = has_bound_params,
- has_vars = has_vars,
- has_locals = has_locals);
+ has_params=has_params,
+ has_vars=has_vars);
}
fn intern(&ctxt cx, &sty st, &option::t[str] cname) {
@@ -485,18 +445,10 @@ fn mk_var(&ctxt cx, int v) -> t {
ret gen_ty(cx, ty_var(v));
}
-fn mk_local(&ctxt cx, ast::def_id did) -> t {
- ret gen_ty(cx, ty_local(did));
-}
-
fn mk_param(&ctxt cx, uint n) -> t {
ret gen_ty(cx, ty_param(n));
}
-fn mk_bound_param(&ctxt cx, uint n) -> t {
- ret gen_ty(cx, ty_bound_param(n));
-}
-
fn mk_type(&ctxt cx) -> t { ret idx_type; }
fn mk_native(&ctxt cx) -> t { ret idx_native; }
@@ -594,12 +546,12 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
ret mstr + ty_to_str(cx, m.ty);
}
- alt (cname(cx, typ)) {
+ /*alt (cname(cx, typ)) {
case (some(?cs)) {
ret cs;
}
case (_) { }
- }
+ }*/
auto s = "";
@@ -664,20 +616,10 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
s += "";
}
- case (ty_local(?id)) {
- s += "";
- }
-
case (ty_param(?id)) {
s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
}
- case (ty_bound_param(?id)) {
- s += "''" + str::unsafe_from_bytes([('a' as u8) +
- (id as u8)]);
- }
-
case (_) {
s += ty_to_short_str(cx, typ);
}
@@ -753,9 +695,7 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
}
}
case (ty_var(_)) { /* no-op */ }
- case (ty_local(_)) { /* no-op */ }
case (ty_param(_)) { /* no-op */ }
- case (ty_bound_param(_)) { /* no-op */ }
}
walker(ty);
@@ -853,9 +793,7 @@ fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
}
case (ty_var(_)) { /* no-op */ }
- case (ty_local(_)) { /* no-op */ }
case (ty_param(_)) { /* no-op */ }
- case (ty_bound_param(_)) { /* no-op */ }
}
ret fld(ty);
@@ -921,9 +859,7 @@ fn sequence_element_type(&ctxt cx, &t ty) -> t {
// NB: This is not exhaustive.
}
- // FIXME: add sess.err or sess.span_err explaining failure (issue
- // #444)
- fail;
+ cx.sess.bug("sequence_element_type called on non-sequence value");
}
fn type_is_tup_like(&ctxt cx, &t ty) -> bool {
@@ -949,8 +885,8 @@ fn get_element_type(&ctxt cx, &t ty, uint i) -> t {
// tag.
}
- // FIXME: add sess.err or sess.span_err explaining failure (issue #444)
- fail;
+ cx.sess.bug("get_element_type called on a value other than a "
+ + "tuple or record");
}
fn type_is_box(&ctxt cx, &t ty) -> bool {
@@ -1020,7 +956,6 @@ fn type_has_pointers(&ctxt cx, &t ty) -> bool {
for (variant_info variant in variants) {
auto tup_ty = mk_imm_tup(cx, variant.args);
// Perform any type parameter substitutions.
- tup_ty = bind_params_in_type(cx, tup_ty);
tup_ty = substitute_type_params(cx, tps, tup_ty);
if (type_has_pointers(cx, tup_ty)) { ret true; }
}
@@ -1230,13 +1165,11 @@ fn hash_type_structure(&sty st) -> uint {
ret h;
}
case (ty_var(?v)) { ret hash_uint(28u, v as uint); }
- case (ty_local(?did)) { ret hash_def(29u, did); }
- case (ty_param(?pid)) { ret hash_uint(30u, pid); }
- case (ty_bound_param(?pid)) { ret hash_uint(31u, pid); }
- case (ty_type) { ret 32u; }
- case (ty_native) { ret 33u; }
- case (ty_bot) { ret 34u; }
- case (ty_ptr(?mt)) { ret hash_subty(35u, mt.ty); }
+ case (ty_param(?pid)) { ret hash_uint(29u, pid); }
+ case (ty_type) { ret 30u; }
+ case (ty_native) { ret 31u; }
+ case (ty_bot) { ret 32u; }
+ case (ty_ptr(?mt)) { ret hash_subty(33u, mt.ty); }
}
}
@@ -1472,24 +1405,12 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
case (_) { ret false; }
}
}
- case (ty_local(?did_a)) {
- alt (b) {
- case (ty_local(?did_b)) { ret equal_def(did_a, did_b); }
- case (_) { ret false; }
- }
- }
case (ty_param(?pid_a)) {
alt (b) {
case (ty_param(?pid_b)) { ret pid_a == pid_b; }
case (_) { ret false; }
}
}
- case (ty_bound_param(?pid_a)) {
- alt (b) {
- case (ty_bound_param(?pid_b)) { ret pid_a == pid_b; }
- case (_) { ret false; }
- }
- }
case (ty_type) {
alt (b) {
case (ty_type) { ret true; }
@@ -1544,24 +1465,25 @@ fn eq_ty(&t a, &t b) -> bool { ret a == b; }
// Type lookups
-fn ann_to_ty_param_substs_opt_and_ty(&node_type_table ntt, &ast::ann ann)
- -> ty_param_substs_opt_and_ty {
- alt ({ntt.(ann.id)}) {
+fn ann_to_ty_param_substs_opt_and_ty(&ctxt cx, &ast::ann ann)
+ -> ty_param_substs_opt_and_ty {
+
+ // Pull out the node type table.
+ alt ({cx.node_types.(ann.id)}) {
case (none) {
- log_err "ann_to_ty_param_substs_opt_and_ty() called on an " +
- "untyped node";
- fail;
+ cx.sess.bug("ann_to_ty_param_substs_opt_and_ty() called on an " +
+ "untyped node");
}
case (some(?tpot)) { ret tpot; }
}
}
-fn ann_to_type(&node_type_table ntt, &ast::ann ann) -> t {
- ret ann_to_ty_param_substs_opt_and_ty(ntt, ann)._1;
+fn ann_to_type(&ctxt cx, &ast::ann ann) -> t {
+ ret ann_to_ty_param_substs_opt_and_ty(cx, ann)._1;
}
-fn ann_to_type_params(&node_type_table ntt, &ast::ann ann) -> vec[t] {
- alt (ann_to_ty_param_substs_opt_and_ty(ntt, ann)._0) {
+fn ann_to_type_params(&ctxt cx, &ast::ann ann) -> vec[t] {
+ alt (ann_to_ty_param_substs_opt_and_ty(cx, ann)._0) {
case (none) {
let vec[t] result = [];
ret result;
@@ -1570,22 +1492,27 @@ fn ann_to_type_params(&node_type_table ntt, &ast::ann ann) -> vec[t] {
}
}
-fn ann_has_type_params(&node_type_table ntt, &ast::ann ann) -> bool {
- auto tpt = ann_to_ty_param_substs_opt_and_ty(ntt, ann);
+fn ann_has_type_params(&ctxt cx, &ast::ann ann) -> bool {
+ auto tpt = ann_to_ty_param_substs_opt_and_ty(cx, ann);
ret !option::is_none[vec[t]](tpt._0);
}
+// Returns a type with type parameter substitutions performed if applicable.
+fn ty_param_substs_opt_and_ty_to_monotype(&ctxt cx,
+ &ty_param_substs_opt_and_ty tpot)
+ -> t {
+ alt (tpot._0) {
+ case (none) { ret tpot._1; }
+ case (some(?tps)) { ret substitute_type_params(cx, tps, tpot._1); }
+ }
+}
+
// Returns the type of an annotation, with type parameter substitutions
// performed if applicable.
fn ann_to_monotype(&ctxt cx, ast::ann a) -> t {
- auto tpot = ann_to_ty_param_substs_opt_and_ty(cx.node_types, a);
- alt (tpot._0) {
- case (none) { ret tpot._1; }
- case (some(?tps)) {
- ret substitute_type_params(cx, tps, tpot._1);
- }
- }
+ auto tpot = ann_to_ty_param_substs_opt_and_ty(cx, a);
+ ret ty_param_substs_opt_and_ty_to_monotype(cx, tpot);
}
@@ -1619,18 +1546,10 @@ fn type_contains_vars(&ctxt cx, &t typ) -> bool {
ret interner::get[raw_t](*cx.ts, typ).has_vars;
}
-fn type_contains_locals(&ctxt cx, &t typ) -> bool {
- ret interner::get[raw_t](*cx.ts, typ).has_locals;
-}
-
fn type_contains_params(&ctxt cx, &t typ) -> bool {
ret interner::get[raw_t](*cx.ts, typ).has_params;
}
-fn type_contains_bound_params(&ctxt cx, &t typ) -> bool {
- ret interner::get[raw_t](*cx.ts, typ).has_bound_params;
-}
-
// Type accessors for substructures of types
fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
@@ -1638,21 +1557,21 @@ fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
case (ty::ty_fn(_, ?a, _, _)) { ret a; }
case (ty::ty_native_fn(_, ?a, _)) { ret a; }
}
- fail;
+ cx.sess.bug("ty_fn_args() called on non-fn type");
}
fn ty_fn_proto(&ctxt cx, &t fty) -> ast::proto {
alt (struct(cx, fty)) {
case (ty::ty_fn(?p, _, _, _)) { ret p; }
}
- fail;
+ cx.sess.bug("ty_fn_proto() called on non-fn type");
}
fn ty_fn_abi(&ctxt cx, &t fty) -> ast::native_abi {
alt (struct(cx, fty)) {
case (ty::ty_native_fn(?a, _, _)) { ret a; }
}
- fail;
+ cx.sess.bug("ty_fn_abi() called on non-native-fn type");
}
fn ty_fn_ret(&ctxt cx, &t fty) -> t {
@@ -1660,7 +1579,7 @@ fn ty_fn_ret(&ctxt cx, &t fty) -> t {
case (ty::ty_fn(_, _, ?r, _)) { ret r; }
case (ty::ty_native_fn(_, _, ?r)) { ret r; }
}
- fail;
+ cx.sess.bug("ty_fn_ret() called on non-fn type");
}
fn is_fn_ty(&ctxt cx, &t fty) -> bool {
@@ -1671,69 +1590,18 @@ fn is_fn_ty(&ctxt cx, &t fty) -> bool {
}
}
+fn ty_var_id(&ctxt cx, t typ) -> int {
+ alt (struct(cx, typ)) {
+ case (ty::ty_var(?vid)) { ret vid; }
+ case (_) { log_err "ty_var_id called on non-var ty"; fail; }
+ }
+}
+
// Type accessors for AST nodes
-// Given an item, returns the associated type as well as the number of type
-// parameters it has.
-fn native_item_ty(&node_type_table ntt, &@ast::native_item it)
- -> ty_param_count_and_ty {
- auto ty_param_count;
- auto result_ty;
- alt (it.node) {
- case (ast::native_item_fn(_, _, _, ?tps, _, ?ann)) {
- ty_param_count = vec::len[ast::ty_param](tps);
- result_ty = ann_to_type(ntt, ann);
- }
- }
- ret tup(ty_param_count, result_ty);
-}
-
-fn item_ty(&node_type_table ntt, &@ast::item it) -> ty_param_count_and_ty {
- auto ty_param_count;
- auto result_ty;
- alt (it.node) {
- case (ast::item_const(_, _, _, _, ?ann)) {
- ty_param_count = 0u;
- result_ty = ann_to_type(ntt, ann);
- }
- case (ast::item_fn(_, _, ?tps, _, ?ann)) {
- ty_param_count = vec::len[ast::ty_param](tps);
- result_ty = ann_to_type(ntt, ann);
- }
- case (ast::item_mod(_, _, _)) {
- fail; // modules are typeless
- }
- case (ast::item_ty(_, _, ?tps, _, ?ann)) {
- ty_param_count = vec::len[ast::ty_param](tps);
- result_ty = ann_to_type(ntt, ann);
- }
- case (ast::item_tag(_, _, ?tps, ?did, ?ann)) {
- ty_param_count = vec::len[ast::ty_param](tps);
- result_ty = ann_to_type(ntt, ann);
- }
- case (ast::item_obj(_, _, ?tps, _, ?ann)) {
- ty_param_count = vec::len[ast::ty_param](tps);
- result_ty = ann_to_type(ntt, ann);
- }
- }
-
- ret tup(ty_param_count, result_ty);
-}
-
-fn stmt_ty(&ctxt cx, &@ast::stmt s) -> t {
- alt (s.node) {
- case (ast::stmt_expr(?e,_)) {
- ret expr_ty(cx, e);
- }
- case (_) {
- ret mk_nil(cx);
- }
- }
-}
-
fn block_ty(&ctxt cx, &ast::block b) -> t {
- ret ann_to_type(cx.node_types, b.node.a);
+ ret ann_to_type(cx, b.node.a);
}
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
@@ -1820,18 +1688,18 @@ fn expr_ty_params_and_ty(&ctxt cx, &@ast::expr expr)
-> tup(vec[t], t) {
auto a = expr_ann(expr);
- ret tup(ann_to_type_params(cx.node_types, a),
- ann_to_type(cx.node_types, a));
+ ret tup(ann_to_type_params(cx, a),
+ ann_to_type(cx, a));
}
-fn expr_has_ty_params(&node_type_table ntt, &@ast::expr expr) -> bool {
- ret ann_has_type_params(ntt, expr_ann(expr));
+fn expr_has_ty_params(&ctxt cx, &@ast::expr expr) -> bool {
+ ret ann_has_type_params(cx, expr_ann(expr));
}
fn decl_local_ty(&ctxt cx, &@ast::decl d) -> t {
alt (d.node) {
case (ast::decl_local(?l)) {
- ret ann_to_type(cx.node_types, l.ann);
+ ret ann_to_type(cx, l.ann);
}
case (_) {
cx.sess.bug("decl_local_ty called on an item decl");
@@ -1941,54 +1809,87 @@ fn is_lval(&@ast::expr expr) -> bool {
mod unify {
tag result {
ures_ok(t);
- ures_err(type_err, t, t);
+ ures_err(type_err);
}
- tag set_result {
- usr_ok(vec[t]);
- usr_err(type_err, t, t);
+ tag union_result {
+ unres_ok;
+ unres_err(type_err);
}
- type bindings[T] = rec(ufind::ufind sets,
- hashmap[T,uint] ids,
- mutable vec[mutable option::t[t]] types);
-
- fn mk_bindings[T](map::hashfn[T] hasher, map::eqfn[T] eqer)
- -> @bindings[T] {
- let vec[mutable option::t[t]] types = [mutable];
- ret @rec(sets=ufind::make(),
- ids=map::mk_hashmap[T,uint](hasher, eqer),
- mutable types=types);
+ tag fixup_result {
+ fix_ok(t); // fixup succeeded
+ fix_err(int); // fixup failed because a type variable was unresolved
}
- fn record_binding[T](&@ctxt cx, &@bindings[T] bindings, &T key, t typ)
- -> result {
- auto n = get_or_create_set[T](bindings, key);
+ type var_bindings = rec(ufind::ufind sets,
+ smallintmap::smallintmap[t] types);
- auto result_type = typ;
- if (n < vec::len[option::t[t]](bindings.types)) {
- alt (bindings.types.(n)) {
- case (some(?old_type)) {
- alt (unify_step(cx, old_type, typ)) {
- case (ures_ok(?unified_type)) {
- result_type = unified_type;
- }
- case (?res) { ret res; }
+ type ctxt = rec(@var_bindings vb, ty_ctxt tcx);
+
+ fn mk_var_bindings() -> @var_bindings {
+ ret @rec(sets=ufind::make(), types=smallintmap::mk[t]());
+ }
+
+ // Unifies two sets.
+ fn union(&@ctxt cx, uint set_a, uint set_b) -> union_result {
+ ufind::grow(cx.vb.sets, uint::max(set_a, set_b) + 1u);
+
+ auto root_a = ufind::find(cx.vb.sets, set_a);
+ auto root_b = ufind::find(cx.vb.sets, set_b);
+ ufind::union(cx.vb.sets, set_a, set_b);
+ auto root_c = ufind::find(cx.vb.sets, set_a);
+
+ alt (smallintmap::find[t](cx.vb.types, root_a)) {
+ case (none[t]) {
+ alt (smallintmap::find[t](cx.vb.types, root_b)) {
+ case (none[t]) { ret unres_ok; }
+ case (some[t](?t_b)) {
+ smallintmap::insert[t](cx.vb.types, root_c, t_b);
+ ret unres_ok;
+ }
+ }
+ }
+ case (some[t](?t_a)) {
+ alt (smallintmap::find[t](cx.vb.types, root_b)) {
+ case (none[t]) {
+ smallintmap::insert[t](cx.vb.types, root_c, t_a);
+ ret unres_ok;
+ }
+ case (some[t](?t_b)) {
+ alt (unify_step(cx, t_a, t_b)) {
+ case (ures_ok(?t_c)) {
+ smallintmap::insert[t](cx.vb.types, root_c,
+ t_c);
+ ret unres_ok;
+ }
+ case (ures_err(?terr)) { ret unres_err(terr); }
+ }
}
}
- case (none) { /* fall through */ }
}
}
-
- vec::grow_set[option::t[t]](bindings.types, n, none[t],
- some[t](result_type));
-
- ret ures_ok(typ);
}
- type ctxt = rec(@bindings[int] bindings,
- unify_handler handler,
- ty_ctxt tcx);
+ fn record_var_binding(&@ctxt cx, int key, t typ) -> result {
+ ufind::grow(cx.vb.sets, (key as uint) + 1u);
+
+ auto result_type = typ;
+ alt (smallintmap::find[t](cx.vb.types, key as uint)) {
+ case (some(?old_type)) {
+ alt (unify_step(cx, old_type, typ)) {
+ case (ures_ok(?unified_type)) {
+ result_type = unified_type;
+ }
+ case (?res) { ret res; }
+ }
+ }
+ case (none) { /* fall through */ }
+ }
+
+ smallintmap::insert[t](cx.vb.types, key as uint, result_type);
+ ret ures_ok(typ);
+ }
// Wraps the given type in an appropriate cname.
//
@@ -2003,7 +1904,7 @@ mod unify {
ret ures_ok(expected);
}
- ret ures_err(terr_mismatch, expected, actual);
+ ret ures_err(terr_mismatch);
}
// Unifies two mutability flags.
@@ -2035,8 +1936,7 @@ mod unify {
auto expected_len = vec::len[arg](expected_inputs);
auto actual_len = vec::len[arg](actual_inputs);
if (expected_len != actual_len) {
- ret fn_common_res_err(ures_err(terr_arg_count,
- expected, actual));
+ ret fn_common_res_err(ures_err(terr_arg_count));
}
// TODO: as above, we should have an iter2 iterator.
@@ -2054,8 +1954,7 @@ mod unify {
result_mode = expected_input.mode;
} else if (expected_input.mode != actual_input.mode) {
// FIXME this is the wrong error
- ret fn_common_res_err(ures_err(terr_arg_count,
- expected, actual));
+ ret fn_common_res_err(ures_err(terr_arg_count));
} else {
result_mode = expected_input.mode;
}
@@ -2099,7 +1998,7 @@ mod unify {
-> result {
if (e_proto != a_proto) {
- ret ures_err(terr_mismatch, expected, actual);
+ ret ures_err(terr_mismatch);
}
alt (expected_cf) {
case (ast::return) { } // ok
@@ -2114,8 +2013,7 @@ mod unify {
this check is necessary to ensure that the
annotation in an object method matches the
declared object type */
- ret ures_err(terr_controlflow_mismatch,
- expected, actual);
+ ret ures_err(terr_controlflow_mismatch);
}
}
}
@@ -2143,9 +2041,7 @@ mod unify {
&vec[arg] expected_inputs, &t expected_output,
&vec[arg] actual_inputs, &t actual_output)
-> result {
- if (e_abi != a_abi) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ if (e_abi != a_abi) { ret ures_err(terr_mismatch); }
auto t = unify_fn_common(cx, expected, actual,
expected_inputs, expected_output,
@@ -2172,16 +2068,13 @@ mod unify {
let uint expected_len = vec::len[method](expected_meths);
let uint actual_len = vec::len[method](actual_meths);
- if (expected_len != actual_len) {
- ret ures_err(terr_meth_count, expected, actual);
- }
+ if (expected_len != actual_len) { ret ures_err(terr_meth_count); }
while (i < expected_len) {
auto e_meth = expected_meths.(i);
auto a_meth = actual_meths.(i);
if (! str::eq(e_meth.ident, a_meth.ident)) {
- ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident),
- expected, actual);
+ ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident));
}
auto r = unify_fn(cx,
e_meth.proto, a_meth.proto,
@@ -2210,16 +2103,42 @@ mod unify {
ret ures_ok(t);
}
- fn get_or_create_set[T](&@bindings[T] bindings, &T key) -> uint {
- auto set_num;
- alt (bindings.ids.find(key)) {
- case (none) {
- set_num = ufind::make_set(bindings.sets);
- bindings.ids.insert(key, set_num);
+ // FIXME: This function should not be necessary, but it is for now until
+ // we eliminate pushdown. The typechecker should never rely on early
+ // resolution of type variables.
+ fn resolve_all_vars(&ty_ctxt tcx, &@var_bindings vb, t typ) -> t {
+ fn folder(ty_ctxt tcx, @var_bindings vb, @bool success, t typ) -> t {
+ alt (struct(tcx, typ)) {
+ case (ty_var(?vid)) {
+ // It's possible that we haven't even created the var set.
+ // Handle this case gracefully.
+ if ((vid as uint) >= ufind::set_count(vb.sets)) {
+ *success = false; ret typ;
+ }
+
+ auto root_id = ufind::find(vb.sets, vid as uint);
+ alt (smallintmap::find[t](vb.types, root_id)) {
+ case (some[t](?typ2)) {
+ ret fold_ty(tcx, bind folder(tcx, vb, success, _),
+ typ2);
+ }
+ case (none[t]) { *success = false; ret typ; }
+ }
+ log ""; // fixes ambiguity
+ *success = false; ret typ;
+ }
+
+ case (_) { ret typ; }
}
- case (some(?n)) { set_num = n; }
}
- ret set_num;
+
+ auto success = @true;
+ auto rty = fold_ty(tcx, bind folder(tcx, vb, success, _), typ);
+ /*if (*success) { ret rty; }
+ log_err "*** failed! type " + ty::ty_to_str(tcx, typ) + " => " +
+ ty::ty_to_str(tcx, rty);
+ ret typ;*/
+ ret rty;
}
fn unify_step(&@ctxt cx, &t expected, &t actual) -> result {
@@ -2232,71 +2151,57 @@ mod unify {
// Fast path.
if (eq_ty(expected, actual)) { ret ures_ok(expected); }
- alt (struct(cx.tcx, actual)) {
+ // Stage 1: Handle the cases in which one side or another is a type
+ // variable.
- // a _|_ type can be used anywhere
- case (ty::ty_bot) {
- ret ures_ok(expected);
- }
-
+ alt (struct(cx.tcx, actual)) {
// If the RHS is a variable type, then just do the appropriate
// binding.
case (ty::ty_var(?actual_id)) {
- auto actual_n = get_or_create_set[int](cx.bindings,
- actual_id);
+ auto actual_n = actual_id as uint;
alt (struct(cx.tcx, expected)) {
case (ty::ty_var(?expected_id)) {
- auto expected_n = get_or_create_set[int](cx.bindings,
- expected_id);
- ufind::union(cx.bindings.sets, expected_n, actual_n);
+ auto expected_n = expected_id as uint;
+ union(cx, expected_n, actual_n);
}
-
case (_) {
// Just bind the type variable to the expected type.
- alt (record_binding[int](cx, cx.bindings, actual_id,
- expected)) {
+ alt (record_var_binding(cx, actual_id, expected)) {
case (ures_ok(_)) { /* fall through */ }
case (?res) { ret res; }
}
}
}
- ret ures_ok(actual);
+ ret ures_ok(mk_var(cx.tcx, actual_id));
}
- case (ty::ty_local(?actual_id)) {
- auto result_ty;
- alt (cx.handler.resolve_local(actual_id)) {
- case (none) { result_ty = expected; }
- case (some(?actual_ty)) {
- auto result = unify_step(cx, expected, actual_ty);
- alt (result) {
- case (ures_ok(?rty)) { result_ty = rty; }
- case (_) { ret result; }
- }
- }
- }
- cx.handler.record_local(actual_id, result_ty);
- ret ures_ok(result_ty);
- }
- case (ty::ty_bound_param(?actual_id)) {
- alt (struct(cx.tcx, expected)) {
- case (ty::ty_local(_)) {
- log_err "TODO: bound param unifying with local";
- fail;
- }
-
- case (_) {
- ret cx.handler.record_param(actual_id, expected);
- }
- }
- }
case (_) { /* empty */ }
}
+ alt (struct(cx.tcx, expected)) {
+ case (ty::ty_var(?expected_id)) {
+ // Add a binding. (`actual` can't actually be a var here.)
+ alt (record_var_binding(cx, expected_id, actual)) {
+ case (ures_ok(_)) { /* fall through */ }
+ case (?res) { ret res; }
+ }
+ ret ures_ok(mk_var(cx.tcx, expected_id));
+ }
+
+ case (_) { /* fall through */ }
+ }
+
+ // Stage 2: Handle all other cases.
+
+ alt (struct(cx.tcx, actual)) {
+ case (ty::ty_bot) { ret ures_ok(expected); }
+ case (_) { /* fall through */ }
+ }
+
alt (struct(cx.tcx, expected)) {
case (ty::ty_nil) { ret struct_cmp(cx, expected, actual); }
// _|_ unifies with anything
- case (ty::ty_bot) { ret ures_ok(expected); }
+ case (ty::ty_bot) { ret ures_ok(actual); }
case (ty::ty_bool) { ret struct_cmp(cx, expected, actual); }
case (ty::ty_int) { ret struct_cmp(cx, expected, actual); }
case (ty::ty_uint) { ret struct_cmp(cx, expected, actual); }
@@ -2313,7 +2218,7 @@ mod unify {
case (ty::ty_tag(?actual_id, ?actual_tps)) {
if (expected_id._0 != actual_id._0 ||
expected_id._1 != actual_id._1) {
- ret ures_err(terr_mismatch, expected, actual);
+ ret ures_err(terr_mismatch);
}
// TODO: factor this cruft out, see the TODO in the
@@ -2346,7 +2251,7 @@ mod unify {
case (_) { /* fall through */ }
}
- ret ures_err(terr_mismatch, expected, actual);
+ ret ures_err(terr_mismatch);
}
case (ty::ty_box(?expected_mt)) {
@@ -2354,10 +2259,7 @@ mod unify {
case (ty::ty_box(?actual_mt)) {
auto mut;
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
- case (none) {
- ret ures_err(terr_box_mutability, expected,
- actual);
- }
+ case (none) { ret ures_err(terr_box_mutability); }
case (some(?m)) { mut = m; }
}
@@ -2375,9 +2277,7 @@ mod unify {
}
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2386,10 +2286,7 @@ mod unify {
case (ty::ty_vec(?actual_mt)) {
auto mut;
alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
- case (none) {
- ret ures_err(terr_vec_mutability, expected,
- actual);
- }
+ case (none) { ret ures_err(terr_vec_mutability); }
case (some(?m)) { mut = m; }
}
@@ -2407,9 +2304,7 @@ mod unify {
}
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2429,9 +2324,7 @@ mod unify {
}
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2451,9 +2344,7 @@ mod unify {
}
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2465,7 +2356,7 @@ mod unify {
if (expected_len != actual_len) {
auto err = terr_tuple_size(expected_len,
actual_len);
- ret ures_err(err, expected, actual);
+ ret ures_err(err);
}
// TODO: implement an iterator that can iterate over
@@ -2481,7 +2372,7 @@ mod unify {
actual_elem.mut)) {
case (none) {
auto err = terr_tuple_mutability;
- ret ures_err(err, expected, actual);
+ ret ures_err(err);
}
case (some(?m)) { mut = m; }
}
@@ -2505,9 +2396,7 @@ mod unify {
ret ures_ok(mk_tup(cx.tcx, result_elems));
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2519,7 +2408,7 @@ mod unify {
if (expected_len != actual_len) {
auto err = terr_record_size(expected_len,
actual_len);
- ret ures_err(err, expected, actual);
+ ret ures_err(err);
}
// TODO: implement an iterator that can iterate over
@@ -2534,8 +2423,7 @@ mod unify {
alt (unify_mut(expected_field.mt.mut,
actual_field.mt.mut)) {
case (none) {
- ret ures_err(terr_record_mutability,
- expected, actual);
+ ret ures_err(terr_record_mutability);
}
case (some(?m)) { mut = m; }
}
@@ -2545,7 +2433,7 @@ mod unify {
auto err =
terr_record_fields(expected_field.ident,
actual_field.ident);
- ret ures_err(err, expected, actual);
+ ret ures_err(err);
}
auto result = unify_step(cx,
@@ -2569,9 +2457,7 @@ mod unify {
ret ures_ok(mk_rec(cx.tcx, result_fields));
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2587,9 +2473,7 @@ mod unify {
expected_cf, actual_cf);
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2603,9 +2487,7 @@ mod unify {
expected_inputs, expected_output,
actual_inputs, actual_output);
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
@@ -2615,150 +2497,87 @@ mod unify {
ret unify_obj(cx, expected, actual,
expected_meths, actual_meths);
}
- case (_) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ case (_) { ret ures_err(terr_mismatch); }
}
}
-
- case (ty::ty_var(?expected_id)) {
- // Add a binding. (`actual` can't actually be a var here.)
- alt (record_binding[int](cx, cx.bindings, expected_id,
- actual)) {
- case (ures_ok(_)) { /* fall through */ }
- case (?res) { ret res; }
- }
- ret ures_ok(expected);
- }
-
- case (ty::ty_local(?expected_id)) {
- auto result_ty;
- alt (cx.handler.resolve_local(expected_id)) {
- case (none) { result_ty = actual; }
- case (some(?expected_ty)) {
- auto result = unify_step(cx, expected_ty, actual);
- alt (result) {
- case (ures_ok(?rty)) { result_ty = rty; }
- case (_) { ret result; }
- }
- }
- }
-
- cx.handler.record_local(expected_id, result_ty);
- ret ures_ok(result_ty);
- }
-
- case (ty::ty_bound_param(?expected_id)) {
- ret cx.handler.record_param(expected_id, actual);
- }
}
}
- // Performs type binding substitution.
- fn substitute(&ty_ctxt tcx,
- &@bindings[int] bindings,
- &vec[t] set_types,
- &t typ) -> t {
- if (!type_contains_vars(tcx, typ)) {
- ret typ;
- }
+ fn unify(&t expected,
+ &t actual,
+ &@var_bindings vb,
+ &ty_ctxt tcx) -> result {
+ auto cx = @rec(vb=vb, tcx=tcx);
+ ret unify_step(cx, expected, actual);
+ }
- fn substituter(ty_ctxt tcx,
- @bindings[int] bindings,
- vec[t] types,
- t typ) -> t {
+ fn dump_var_bindings(ty_ctxt tcx, @var_bindings vb) {
+ auto i = 0u;
+ while (i < vec::len[ufind::node](vb.sets.nodes)) {
+ auto sets = "";
+ auto j = 0u;
+ while (j < vec::len[option::t[uint]](vb.sets.nodes)) {
+ if (ufind::find(vb.sets, j) == i) { sets += #fmt(" %u", j); }
+ j += 1u;
+ }
+
+ auto typespec;
+ alt (smallintmap::find[t](vb.types, i)) {
+ case (none[t]) { typespec = ""; }
+ case (some[t](?typ)) {
+ typespec = " =" + ty_to_str(tcx, typ);
+ }
+ }
+
+ log_err #fmt("set %u:%s%s", i, typespec, sets);
+ i += 1u;
+ }
+ }
+
+ // Fixups and substitutions
+
+ fn fixup_vars(ty_ctxt tcx, @var_bindings vb, t typ) -> fixup_result {
+ fn subst_vars(ty_ctxt tcx, @var_bindings vb,
+ @mutable option::t[int] unresolved, t typ) -> t {
alt (struct(tcx, typ)) {
- case (ty_var(?id)) {
- alt (bindings.ids.find(id)) {
- case (some(?n)) {
- auto root = ufind::find(bindings.sets, n);
- ret types.(root);
+ case (ty::ty_var(?vid)) {
+ if ((vid as uint) >= ufind::set_count(vb.sets)) {
+ *unresolved = some[int](vid);
+ ret typ;
+ }
+
+ auto root_id = ufind::find(vb.sets, vid as uint);
+ alt (smallintmap::find[t](vb.types, root_id)) {
+ case (none[t]) {
+ *unresolved = some[int](vid);
+ ret typ;
+ }
+ case (some[t](?rt)) {
+ ret fold_ty(tcx,
+ bind subst_vars(tcx, vb, unresolved, _), rt);
}
- case (none) { ret typ; }
}
}
case (_) { ret typ; }
}
}
- auto f = bind substituter(tcx, bindings, set_types, _);
- ret fold_ty(tcx, f, typ);
+ auto unresolved = @mutable none[int];
+ auto rty = fold_ty(tcx, bind subst_vars(tcx, vb, unresolved, _), typ);
+
+ auto ur = *unresolved;
+ alt (ur) {
+ case (none[int]) { ret fix_ok(rty); }
+ case (some[int](?var_id)) { ret fix_err(var_id); }
+ }
}
- fn unify_sets[T](&ty_ctxt tcx, &@bindings[T] bindings) -> set_result {
- obj handler() {
- fn resolve_local(ast::def_id id) -> option::t[t] {
- log_err "resolve_local in unify_sets";
- fail;
- }
- fn record_local(ast::def_id id, t ty) {
- log_err "record_local in unify_sets";
- fail;
- }
- fn record_param(uint index, t binding) -> unify::result {
- log_err "record_param in unify_sets";
- fail;
- }
- }
-
- auto node_count = vec::len[option::t[t]](bindings.types);
-
- let vec[option::t[t]] results =
- vec::init_elt[option::t[t]](none[t], node_count);
-
- auto i = 0u;
- while (i < node_count) {
- auto root = ufind::find(bindings.sets, i);
- alt (bindings.types.(i)) {
- case (none) { /* nothing to do */ }
- case (some(?actual)) {
- alt (results.(root)) {
- case (none) { results.(root) = some[t](actual); }
- case (some(?expected)) {
- // FIXME: Is this right?
- auto bindings = mk_bindings[int](int::hash,
- int::eq_alias);
- alt (unify(expected, actual, handler(), bindings,
- tcx)) {
- case (ures_ok(?result_ty)) {
- results.(i) = some[t](result_ty);
- }
- case (ures_err(?e, ?t_a, ?t_b)) {
- ret usr_err(e, t_a, t_b);
- }
- }
- }
- }
- }
- }
- i += 1u;
- }
-
- // FIXME: This is equivalent to map(option::get, results) but it
- // causes an assertion in typeck at the moment.
- let vec[t] real_results = [];
- for (option::t[t] typ in results) {
- real_results += [option::get[t](typ)];
- }
-
- ret usr_ok(real_results);
- }
-
- fn unify(&t expected,
- &t actual,
- &unify_handler handler,
- &@bindings[int] bindings,
- &ty_ctxt tcx) -> result {
- auto cx = @rec(bindings=bindings, handler=handler, tcx=tcx);
- ret unify_step(cx, expected, actual);
- }
-
- fn fixup(&ty_ctxt tcx, &@bindings[int] bindings, t typ) -> result {
- alt (unify_sets[int](tcx, bindings)) {
- case (usr_ok(?set_types)) {
- ret ures_ok(substitute(tcx, bindings, set_types, typ));
- }
- case (usr_err(?terr, ?t0, ?t1)) { ret ures_err(terr, t0, t1); }
+ fn resolve_type_var(&ty_ctxt tcx, &@var_bindings vb, int vid)
+ -> fixup_result {
+ auto root_id = ufind::find(vb.sets, vid as uint);
+ alt (smallintmap::find[t](vb.types, root_id)) {
+ case (none[t]) { ret fix_ok(mk_var(tcx, vid)); }
+ case (some[t](?rt)) { ret fixup_vars(tcx, vb, rt); }
}
}
}
@@ -2813,47 +2632,46 @@ fn type_err_to_str(&ty::type_err err) -> str {
}
}
-// Performs bound type parameter replacement using the supplied mapping from
-// parameter IDs to types.
-fn substitute_type_params(&ctxt cx, &vec[t] bindings, &t typ) -> t {
- if (!type_contains_bound_params(cx, typ)) {
- ret typ;
+// Converts type parameters in a type to type variables and returns the
+// resulting type along with a list of type variable IDs.
+fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
+ uint ty_param_count)
+ -> tup(vec[int], t) {
+ let vec[int] param_var_ids = [];
+ auto i = 0u;
+ while (i < ty_param_count) {
+ param_var_ids += [next_ty_var()];
+ i += 1u;
}
- fn replacer(&ctxt cx, vec[t] bindings, t typ) -> t {
+
+ fn binder(ctxt cx, vec[int] param_var_ids, fn()->int next_ty_var, t typ)
+ -> t {
alt (struct(cx, typ)) {
- case (ty_bound_param(?param_index)) {
- ret bindings.(param_index);
- }
+ case (ty_param(?index)) { ret mk_var(cx, param_var_ids.(index)); }
case (_) { ret typ; }
}
}
- auto f = bind replacer(cx, bindings, _);
- ret fold_ty(cx, f, typ);
+ auto f = bind binder(cx, param_var_ids, next_ty_var, _);
+ auto new_typ = fold_ty(cx, f, typ);
+ ret tup(param_var_ids, new_typ);
}
-// Converts type parameters in a type to bound type parameters.
-fn bind_params_in_type(&ctxt cx, &t typ) -> t {
- if (!type_contains_params(cx, typ)) {
- ret typ;
- }
- fn binder(&ctxt cx, t typ) -> t {
+// Replaces type parameters in the given type using the given list of
+// substitions.
+fn substitute_type_params(&ctxt cx, vec[ty::t] substs, t typ) -> t {
+ if (!type_contains_params(cx, typ)) { ret typ; }
+
+ fn substituter(ctxt cx, vec[ty::t] substs, t typ) -> t {
alt (struct(cx, typ)) {
- case (ty_bound_param(?index)) {
- log_err "bind_params_in_type() called on type that already " +
- "has bound params in it";
- fail;
- }
- case (ty_param(?index)) { ret mk_bound_param(cx, index); }
+ case (ty_param(?idx)) { ret substs.(idx); }
case (_) { ret typ; }
}
}
- auto f = bind binder(cx, _);
- ret fold_ty(cx, f, typ);
+ ret fold_ty(cx, bind substituter(cx, substs, _), typ);
}
-
fn def_has_ty_params(&ast::def def) -> bool {
alt (def) {
case (ast::def_fn(_)) { ret true; }
@@ -2924,9 +2742,9 @@ fn tag_variant_with_id(&ctxt cx,
}
i += 1u;
}
+
+ cx.sess.bug("tag_variant_with_id(): no variant exists with that ID");
- log_err "tag_variant_with_id(): no variant exists with that ID";
- fail;
}
// If the given item is in an external crate, looks up its type and adds it to
@@ -2948,19 +2766,19 @@ fn lookup_item_type(ctxt cx, ast::def_id did) -> ty_param_count_and_ty {
}
}
-fn ret_ty_of_fn_ty(ty_ctxt tcx, t a_ty) -> t {
- alt (ty::struct(tcx, a_ty)) {
+fn ret_ty_of_fn_ty(ctxt cx, t a_ty) -> t {
+ alt (ty::struct(cx, a_ty)) {
case (ty::ty_fn(_, _, ?ret_ty, _)) {
ret ret_ty;
}
case (_) {
- fail;
+ cx.sess.bug("ret_ty_of_fn_ty() called on non-function type");
}
}
}
-fn ret_ty_of_fn(ty_ctxt tcx, ast::ann ann) -> t {
- ret ret_ty_of_fn_ty(tcx, ann_to_type(tcx.node_types, ann));
+fn ret_ty_of_fn(ctxt cx, ast::ann ann) -> t {
+ ret ret_ty_of_fn_ty(cx, ann_to_type(cx, ann));
}
// Local Variables:
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 11fbab4ddde..db3f3ede0c7 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -31,9 +31,13 @@ import middle::ty::ty_param_count_and_ty;
import middle::ty::ty_nil;
import middle::ty::unify::ures_ok;
import middle::ty::unify::ures_err;
+import middle::ty::unify::fixup_result;
+import middle::ty::unify::fix_ok;
+import middle::ty::unify::fix_err;
import std::int;
import std::str;
+import std::ufind;
import std::uint;
import std::vec;
import std::map;
@@ -62,76 +66,41 @@ type crate_ctxt = rec(mutable vec[obj_info] obj_infos,
type fn_ctxt = rec(ty::t ret_ty,
ast::purity purity,
- @ty_table locals,
+ @ty::unify::var_bindings var_bindings,
+ hashmap[ast::def_id,int] locals,
+ hashmap[ast::def_id,ast::ident] local_names,
+ mutable int next_var_id,
+ mutable vec[uint] fixups,
@crate_ctxt ccx);
-type stmt_ctxt = rec(@fn_ctxt fcx,
- mutable int next_var_id,
- mutable vec[uint] fixups);
-
// Used for ast_ty_to_ty() below.
type ty_getter = fn(&ast::def_id) -> ty::ty_param_count_and_ty;
-// Creates a statement context and passes it to the given thunk, then runs
-// fixups. This function has the signature it does so that the caller can
-// never forget to run fixups!
-fn with_stmt_ctxt(&@fn_ctxt fcx, fn(&@stmt_ctxt) f) {
- let vec[uint] fixups = [];
- auto scx = @rec(fcx=fcx, mutable next_var_id=0, mutable fixups=fixups);
- f(scx);
- // TODO: run fixups
-}
-
-// Substitutes the user's explicit types for the parameters in a path
-// expression.
-fn substitute_ty_params(&@crate_ctxt ccx,
- &ty::t typ,
- uint ty_param_count,
- &vec[ty::t] supplied,
- &span sp) -> ty::t {
- fn substituter(@crate_ctxt ccx, vec[ty::t] supplied, ty::t typ) -> ty::t {
- alt (struct(ccx.tcx, typ)) {
- case (ty::ty_bound_param(?pid)) { ret supplied.(pid); }
- case (_) { ret typ; }
- }
- }
-
- auto supplied_len = vec::len[ty::t](supplied);
- if (ty_param_count != supplied_len) {
- ccx.tcx.sess.span_err(sp, "expected " +
- uint::to_str(ty_param_count, 10u) +
- " type parameter(s) but found " +
- uint::to_str(supplied_len, 10u) + " parameter(s)");
- }
-
- if (!ty::type_contains_bound_params(ccx.tcx, typ)) {
- ret typ;
- }
-
- auto f = bind substituter(ccx, supplied, _);
- ret ty::fold_ty(ccx.tcx, f, typ);
-}
-
// 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)
-> ty_param_count_and_ty {
alt (defn) {
case (ast::def_arg(?id)) {
- // assert (fcx.locals.contains_key(id));
- ret tup(0u, fcx.locals.get(id));
+ assert (fcx.locals.contains_key(id));
+ auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
+ typ = ty::unify::resolve_all_vars(fcx.ccx.tcx, fcx.var_bindings,
+ typ);
+ ret tup(0u, typ);
}
case (ast::def_local(?id)) {
- auto t;
- alt (fcx.locals.find(id)) {
- case (some(?t1)) { t = t1; }
- case (none) { t = ty::mk_local(fcx.ccx.tcx, id); }
- }
- ret tup(0u, t);
+ assert (fcx.locals.contains_key(id));
+ auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
+ typ = ty::unify::resolve_all_vars(fcx.ccx.tcx, fcx.var_bindings,
+ typ);
+ ret tup(0u, typ);
}
case (ast::def_obj_field(?id)) {
- // assert (fcx.locals.contains_key(id));
- ret tup(0u, fcx.locals.get(id));
+ assert (fcx.locals.contains_key(id));
+ auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
+ typ = ty::unify::resolve_all_vars(fcx.ccx.tcx, fcx.var_bindings,
+ typ);
+ ret tup(0u, typ);
}
case (ast::def_fn(?id)) {
ret ty::lookup_item_type(fcx.ccx.tcx, id);
@@ -146,8 +115,11 @@ fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn)
ret ty::lookup_item_type(fcx.ccx.tcx, vid);
}
case (ast::def_binding(?id)) {
- // assert (fcx.locals.contains_key(id));
- ret tup(0u, fcx.locals.get(id));
+ assert (fcx.locals.contains_key(id));
+ auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
+ typ = ty::unify::resolve_all_vars(fcx.ccx.tcx, fcx.var_bindings,
+ typ);
+ ret tup(0u, typ);
}
case (ast::def_obj(?id)) {
ret ty::lookup_item_type(fcx.ccx.tcx, id);
@@ -172,12 +144,18 @@ fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn)
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
-fn instantiate_path(&@stmt_ctxt scx,
+fn instantiate_path(&@fn_ctxt fcx,
&ast::path pth,
&ty_param_count_and_ty tpt,
&span sp) -> ty_param_substs_opt_and_ty {
auto ty_param_count = tpt._0;
- auto t = bind_params_in_type(scx.fcx.ccx.tcx, tpt._1);
+
+ auto bind_result = bind_params_in_type(fcx.ccx.tcx,
+ bind next_ty_var_id(fcx),
+ tpt._1,
+ ty_param_count);
+ auto ty_param_vars = bind_result._0;
+ auto t = bind_result._1;
auto ty_substs_opt;
auto ty_substs_len = vec::len[@ast::ty](pth.node.types);
@@ -185,16 +163,20 @@ fn instantiate_path(&@stmt_ctxt scx,
let vec[ty::t] ty_substs = [];
auto i = 0u;
while (i < ty_substs_len) {
- ty_substs += [ast_ty_to_ty_crate(scx.fcx.ccx,
- pth.node.types.(i))];
+ // TODO: Report an error if the number of type params in the item
+ // and the supplied number of type params don't match.
+ auto ty_var = ty::mk_var(fcx.ccx.tcx, ty_param_vars.(i));
+ auto ty_subst = ast_ty_to_ty_crate(fcx.ccx,
+ pth.node.types.(i));
+ auto res_ty = demand::simple(fcx, pth.span, ty_var, ty_subst);
+ ty_substs += [res_ty];
i += 1u;
}
ty_substs_opt = some[vec[ty::t]](ty_substs);
if (ty_param_count == 0u) {
- scx.fcx.ccx.tcx.sess.span_err(sp,
- "this item does not take type " +
- "parameters");
+ fcx.ccx.tcx.sess.span_err(sp, "this item does not take type " +
+ "parameters");
fail;
}
} else {
@@ -202,13 +184,13 @@ fn instantiate_path(&@stmt_ctxt scx,
let vec[ty::t] ty_substs = [];
auto i = 0u;
while (i < ty_param_count) {
- ty_substs += [next_ty_var(scx)];
+ ty_substs += [ty::mk_var(fcx.ccx.tcx, ty_param_vars.(i))];
i += 1u;
}
ty_substs_opt = some[vec[ty::t]](ty_substs);
}
- ret tup(ty_substs_opt, t);
+ ret tup(ty_substs_opt, tpt._1);
}
fn ast_mode_to_mode(ast::mode mode) -> ty::mode {
@@ -245,7 +227,6 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
// TODO: maybe record cname chains so we can do
// "foo = int" like OCaml?
auto params_opt_and_ty = getter(id);
-
if (params_opt_and_ty._0 == 0u) {
ret params_opt_and_ty._1;
}
@@ -254,12 +235,14 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
//
// TODO: Make sure the number of supplied bindings matches the number
// of type parameters in the typedef. Emit a friendly error otherwise.
- auto bound_ty = bind_params_in_type(tcx, params_opt_and_ty._1);
let vec[ty::t] param_bindings = [];
for (@ast::ty ast_ty in args) {
param_bindings += [ast_ty_to_ty(tcx, getter, ast_ty)];
}
- ret ty::substitute_type_params(tcx, param_bindings, bound_ty);
+
+ auto typ = ty::substitute_type_params(tcx, param_bindings,
+ params_opt_and_ty._1);
+ ret typ;
}
auto mut = ast::imm;
@@ -398,11 +381,11 @@ mod write {
// Writes a type parameter count and type pair into the node type table.
// This function allows for the possibility of type variables, which will
// be rewritten later during the fixup phase.
- fn ty_fixup(&@stmt_ctxt scx, uint node_id,
+ fn ty_fixup(@fn_ctxt fcx, uint node_id,
&ty_param_substs_opt_and_ty tpot) {
- inner(scx.fcx.ccx.tcx.node_types, node_id, tpot);
- if (ty::type_contains_vars(scx.fcx.ccx.tcx, tpot._1)) {
- scx.fixups += [node_id];
+ inner(fcx.ccx.tcx.node_types, node_id, tpot);
+ if (ty::type_contains_vars(fcx.ccx.tcx, tpot._1)) {
+ fcx.fixups += [node_id];
}
}
@@ -413,8 +396,8 @@ mod write {
// Writes a type with no type parameters into the node type table. This
// function allows for the possibility of type variables.
- fn ty_only_fixup(&@stmt_ctxt scx, uint node_id, ty::t typ) {
- be ty_fixup(scx, node_id, tup(none[vec[ty::t]], typ));
+ fn ty_only_fixup(@fn_ctxt fcx, uint node_id, ty::t typ) {
+ be ty_fixup(fcx, node_id, tup(none[vec[ty::t]], typ));
}
// Writes a nil type into the node type table.
@@ -835,105 +818,32 @@ mod collect {
// Type unification
mod unify {
- fn simple(&@stmt_ctxt scx, &ty::t expected, &ty::t actual)
+ fn simple(&@fn_ctxt fcx, &ty::t expected, &ty::t actual)
-> ty::unify::result {
- // FIXME: horrid botch
- let vec[mutable ty::t] param_substs =
- [mutable ty::mk_nil(scx.fcx.ccx.tcx)];
- vec::pop(param_substs);
- ret with_params(scx, expected, actual, param_substs);
- }
-
- fn with_params(&@stmt_ctxt scx,
- &ty::t expected,
- &ty::t actual,
- &vec[mutable ty::t] param_substs) -> ty::unify::result {
- auto cache_key = tup(expected, actual, param_substs);
- alt (scx.fcx.ccx.unify_cache.find(cache_key)) {
+ /*auto cache_key = tup(expected, actual, param_substs);
+ alt (fcx.ccx.unify_cache.find(cache_key)) {
case (some(?r)) {
- scx.fcx.ccx.cache_hits += 1u;
+ fcx.ccx.cache_hits += 1u;
ret r;
}
case (none) {
- scx.fcx.ccx.cache_misses += 1u;
+ fcx.ccx.cache_misses += 1u;
}
+ }*/
+
+ auto result = ty::unify::unify(expected, actual, fcx.var_bindings,
+ fcx.ccx.tcx);
+
+ //fcx.ccx.unify_cache.insert(cache_key, result);
+
+ // FIXME: Shouldn't be necessary, but is until we remove pushdown.
+ alt (result) {
+ case (ures_ok(?typ)) {
+ ret ures_ok(ty::unify::resolve_all_vars(fcx.ccx.tcx,
+ fcx.var_bindings, typ));
+ }
+ case (_) { ret result; }
}
-
- obj unify_handler(@stmt_ctxt scx, vec[mutable ty::t] param_substs) {
- fn resolve_local(ast::def_id id) -> option::t[ty::t] {
- alt (scx.fcx.locals.find(id)) {
- case (none) { ret none[ty::t]; }
- case (some(?existing_type)) {
- if (ty::type_contains_vars(scx.fcx.ccx.tcx,
- existing_type)) {
- // Not fully resolved yet. The writeback phase
- // will mop up.
- ret none[ty::t];
- }
- ret some[ty::t](existing_type);
- }
- }
- }
- fn record_local(ast::def_id id, ty::t new_type) {
- auto unified_type;
- alt (scx.fcx.locals.find(id)) {
- case (none) { unified_type = new_type; }
- case (some(?old_type)) {
- alt (with_params(scx, old_type, new_type,
- param_substs)) {
- case (ures_ok(?ut)) { unified_type = ut; }
- case (_) { fail; /* FIXME */ }
- }
- }
- }
-
- // TODO: "freeze"
- let vec[ty::t] param_substs_1 = [];
- for (ty::t subst in param_substs) {
- param_substs_1 += [subst];
- }
-
- unified_type = ty::substitute_type_params(scx.fcx.ccx.tcx,
- param_substs_1,
- unified_type);
- scx.fcx.locals.insert(id, unified_type);
- }
- fn record_param(uint index, ty::t binding) -> ty::unify::result {
- // Unify with the appropriate type in the parameter
- // substitution list:
- auto old_subst = param_substs.(index);
-
- auto result = with_params(scx, old_subst, binding,
- param_substs);
- alt (result) {
- case (ures_ok(?new_subst)) {
- param_substs.(index) = new_subst;
- ret ures_ok(ty::mk_bound_param(scx.fcx.ccx.tcx,
- index));
- }
- case (_) { ret result; }
- }
- }
- }
-
-
- auto handler = unify_handler(scx, param_substs);
-
- auto bindings = ty::unify::mk_bindings[int](int::hash, int::eq_alias);
- auto result = ty::unify::unify(expected, actual, handler, bindings,
- scx.fcx.ccx.tcx);
-
- alt ({result}) {
- case (ures_ok(?rty)) {
- if (ty::type_contains_vars(scx.fcx.ccx.tcx, rty)) {
- result = ty::unify::fixup(scx.fcx.ccx.tcx, bindings, rty);
- }
- }
- case (_) { /* nothing */ }
- }
-
- scx.fcx.ccx.unify_cache.insert(cache_key, result);
- ret result;
}
}
@@ -983,22 +893,22 @@ fn count_boxes(&ty::ctxt tcx, &ty::t t) -> uint {
type ty_param_substs_and_ty = tup(vec[ty::t], ty::t);
mod demand {
- fn simple(&@stmt_ctxt scx, &span sp, &ty::t expected, &ty::t actual)
+ fn simple(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual)
-> ty::t {
let vec[ty::t] tps = [];
- ret full(scx, sp, expected, actual, tps, NO_AUTODEREF)._1;
+ ret full(fcx, sp, expected, actual, tps, NO_AUTODEREF)._1;
}
- fn autoderef(&@stmt_ctxt scx, &span sp, &ty::t expected, &ty::t actual,
+ fn autoderef(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
autoderef_kind adk) -> ty::t {
let vec[ty::t] tps = [];
- ret full(scx, sp, expected, actual, tps, adk)._1;
+ ret full(fcx, sp, expected, actual, tps, adk)._1;
}
// Requires that the two types unify, and prints an error message if they
// don't. Returns the unified type and the type parameter substitutions.
- fn full(&@stmt_ctxt scx, &span sp, &ty::t expected, &ty::t actual,
+ fn full(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
&vec[ty::t] ty_param_substs_0, autoderef_kind adk)
-> ty_param_substs_and_ty {
@@ -1007,35 +917,41 @@ mod demand {
auto implicit_boxes = 0u;
if (adk == AUTODEREF_OK) {
- expected_1 = strip_boxes(scx.fcx.ccx.tcx, expected_1);
- actual_1 = strip_boxes(scx.fcx.ccx.tcx, actual_1);
- implicit_boxes = count_boxes(scx.fcx.ccx.tcx, actual);
+ expected_1 = strip_boxes(fcx.ccx.tcx, expected_1);
+ actual_1 = strip_boxes(fcx.ccx.tcx, actual_1);
+ implicit_boxes = count_boxes(fcx.ccx.tcx, actual);
}
- let vec[mutable ty::t] ty_param_substs =
- [mutable ty::mk_nil(scx.fcx.ccx.tcx)];
- vec::pop(ty_param_substs); // FIXME: horrid botch
+ let vec[mutable ty::t] ty_param_substs = [mutable];
+ let vec[int] ty_param_subst_var_ids = [];
for (ty::t ty_param_subst in ty_param_substs_0) {
- ty_param_substs += [mutable ty_param_subst];
+ // Generate a type variable and unify it with the type parameter
+ // substitution. We will then pull out these type variables.
+ auto t_0 = next_ty_var(fcx);
+ ty_param_substs += [mutable t_0];
+ ty_param_subst_var_ids += [ty::ty_var_id(fcx.ccx.tcx, t_0)];
+
+ simple(fcx, sp, ty_param_subst, t_0);
}
- alt (unify::with_params(scx, expected_1, actual_1, ty_param_substs)) {
+ alt (unify::simple(fcx, expected_1, actual_1)) {
case (ures_ok(?t)) {
- // TODO: Use "freeze", when we have it.
let vec[ty::t] result_ty_param_substs = [];
- for (ty::t ty_param_subst in ty_param_substs) {
- result_ty_param_substs += [ty_param_subst];
+ for (int var_id in ty_param_subst_var_ids) {
+ auto tp_subst = ty::unify::resolve_all_vars(fcx.ccx.tcx,
+ fcx.var_bindings, ty::mk_var(fcx.ccx.tcx, var_id));
+ result_ty_param_substs += [tp_subst];
}
ret tup(result_ty_param_substs,
- add_boxes(scx.fcx.ccx, implicit_boxes, t));
+ add_boxes(fcx.ccx, implicit_boxes, t));
}
- case (ures_err(?err, ?expected, ?actual)) {
- scx.fcx.ccx.tcx.sess.span_err
+ case (ures_err(?err)) {
+ fcx.ccx.tcx.sess.span_err
(sp, "mismatched types: expected "
- + ty_to_str(scx.fcx.ccx.tcx, expected) + " but found "
- + ty_to_str(scx.fcx.ccx.tcx, actual) + " ("
+ + ty_to_str(fcx.ccx.tcx, expected_1) + " but found "
+ + ty_to_str(fcx.ccx.tcx, actual_1) + " ("
+ ty::type_err_to_str(err) + ")");
// TODO: In the future, try returning "expected", reporting
@@ -1047,10 +963,10 @@ mod demand {
// Returns true if the two types unify and false if they don't.
-fn are_compatible(&@stmt_ctxt scx, &ty::t expected, &ty::t actual) -> bool {
- alt (unify::simple(scx, expected, actual)) {
- case (ures_ok(_)) { ret true; }
- case (ures_err(_, _, _)) { ret false; }
+fn are_compatible(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) -> bool {
+ alt (unify::simple(fcx, expected, actual)) {
+ case (ures_ok(_)) { ret true; }
+ case (ures_err(_)) { ret false; }
}
}
@@ -1066,9 +982,8 @@ fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
case (ty::ty_fn(_, ?ins, _, _)) {
// N-ary variant.
for (ty::arg arg in ins) {
- auto arg_ty = bind_params_in_type(ccx.tcx, arg.ty);
- arg_ty = substitute_ty_params(ccx, arg_ty, ty_param_count,
- tag_ty_params, sp);
+ auto arg_ty = ty::substitute_type_params(ccx.tcx,
+ tag_ty_params, arg.ty);
result += [arg_ty];
}
}
@@ -1105,22 +1020,22 @@ mod pushdown {
// TODO: enforce this via a predicate.
// TODO: This function is incomplete.
- fn pushdown_expr(&@stmt_ctxt scx, &ty::t expected, &@ast::expr e) {
- be pushdown_expr_full(scx, expected, e, NO_AUTODEREF);
+ fn pushdown_expr(&@fn_ctxt fcx, &ty::t expected, &@ast::expr e) {
+ be pushdown_expr_full(fcx, expected, e, NO_AUTODEREF);
}
- fn pushdown_expr_full(&@stmt_ctxt scx, &ty::t expected, &@ast::expr e,
+ fn pushdown_expr_full(&@fn_ctxt fcx, &ty::t expected, &@ast::expr e,
autoderef_kind adk) {
alt (e.node) {
case (ast::expr_vec(?es_0, ?mut, ?ann)) {
// TODO: enforce mutability
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- alt (struct(scx.fcx.ccx.tcx, t)) {
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ alt (struct(fcx.ccx.tcx, t)) {
case (ty::ty_vec(?mt)) {
for (@ast::expr e_0 in es_0) {
- pushdown_expr(scx, mt.ty, e_0);
+ pushdown_expr(fcx, mt.ty, e_0);
}
}
case (_) {
@@ -1128,16 +1043,16 @@ mod pushdown {
fail;
}
}
- write::ty_only_fixup(scx, ann.id, t);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_tup(?es_0, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- alt (struct(scx.fcx.ccx.tcx, t)) {
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ alt (struct(fcx.ccx.tcx, t)) {
case (ty::ty_tup(?mts)) {
auto i = 0u;
for (ast::elt elt_0 in es_0) {
- pushdown_expr(scx, mts.(i).ty, elt_0.expr);
+ pushdown_expr(fcx, mts.(i).ty, elt_0.expr);
i += 1u;
}
}
@@ -1146,13 +1061,13 @@ mod pushdown {
fail;
}
}
- write::ty_only_fixup(scx, ann.id, t);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_rec(?fields_0, ?base_0, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- alt (struct(scx.fcx.ccx.tcx, t)) {
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ alt (struct(fcx.ccx.tcx, t)) {
case (ty::ty_rec(?field_mts)) {
alt (base_0) {
case (none) {
@@ -1160,7 +1075,7 @@ mod pushdown {
for (ast::field field_0 in fields_0) {
assert (str::eq(field_0.node.ident,
field_mts.(i).ident));
- pushdown_expr(scx,
+ pushdown_expr(fcx,
field_mts.(i).mt.ty,
field_0.node.expr);
i += 1u;
@@ -1175,7 +1090,7 @@ mod pushdown {
for (ty::field ft in field_mts) {
if (str::eq(field_0.node.ident,
ft.ident)) {
- pushdown_expr(scx, ft.mt.ty,
+ pushdown_expr(fcx, ft.mt.ty,
field_0.node.expr);
}
}
@@ -1188,161 +1103,163 @@ mod pushdown {
fail;
}
}
- write::ty_only_fixup(scx, ann.id, t);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_bind(?sube, ?es, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_call(?sube, ?es, ?ann)) {
// NB: we call 'demand::autoderef' and pass in adk only in
// cases where e is an expression that could *possibly*
// produce a box; things like expr_binary or expr_bind can't,
// so there's no need.
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_self_method(?id, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_binary(?bop, ?lhs, ?rhs, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_unary(?uop, ?sube, ?ann)) {
// See note in expr_unary for why we're calling
// demand::autoderef.
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
/* The following is a bit special-cased, but takes care of
the case where we say let @vec[whatever] v = @[]; */
auto inner_ty = t;
alt (uop) {
case (ast::box(?mut)) {
- alt (struct(scx.fcx.ccx.tcx, t)) {
+ alt (struct(fcx.ccx.tcx, t)) {
case (ty::ty_box(?inner)) { inner_ty = inner.ty; }
case (_) {
- scx.fcx.ccx.tcx.sess.span_err(e.span,
- "Expecting an application of box"
- + " to have a box type");
+ fcx.ccx.tcx.sess.span_err(e.span,
+ "Expecting an application of box " +
+ "to have a box type; it had type " +
+ ty::ty_to_str(fcx.ccx.tcx, t));
}
}
}
case (ast::deref) {
- inner_ty = ty::mk_box(scx.fcx.ccx.tcx,
+ inner_ty = ty::mk_box(fcx.ccx.tcx,
// maybe_mut should work because it'll unify with
// the existing type?
rec(ty=t, mut=ast::maybe_mut));
}
- case (_) { inner_ty = strip_boxes(scx.fcx.ccx.tcx, t); }
+ case (_) { inner_ty = strip_boxes(fcx.ccx.tcx, t); }
}
- pushdown_expr(scx, inner_ty, sube);
+ pushdown_expr(fcx, inner_ty, sube);
}
case (ast::expr_lit(?lit, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_cast(?sube, ?ast_ty, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_if(?cond, ?then_0, ?else_0, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
- auto then_t = ty::block_ty(scx.fcx.ccx.tcx, then_0);
- pushdown_block(scx, expected, then_0);
+ auto then_t = ty::block_ty(fcx.ccx.tcx, then_0);
+ pushdown_block(fcx, expected, then_0);
alt (else_0) {
case (none) { /* no-op */ }
case (some(?e_0)) {
- auto else_t = ty::expr_ty(scx.fcx.ccx.tcx, e_0);
- pushdown_expr(scx, expected, e_0);
+ auto else_t = ty::expr_ty(fcx.ccx.tcx, e_0);
+ pushdown_expr(fcx, expected, e_0);
}
}
- write::ty_only_fixup(scx, ann.id, t);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_for(?decl, ?seq, ?bloc, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_for_each(?decl, ?seq, ?bloc, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_while(?cond, ?bloc, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_do_while(?bloc, ?cond, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_block(?bloc, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
- pushdown_block(scx, t, bloc);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
+ pushdown_block(fcx, t, bloc);
}
case (ast::expr_move(?lhs_0, ?rhs_0, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- pushdown_expr(scx, expected, lhs_0);
- pushdown_expr(scx, expected, rhs_0);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ pushdown_expr(fcx, expected, lhs_0);
+ pushdown_expr(fcx, expected, rhs_0);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_assign(?lhs_0, ?rhs_0, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- pushdown_expr(scx, expected, lhs_0);
- pushdown_expr(scx, expected, rhs_0);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ pushdown_expr(fcx, expected, lhs_0);
+ pushdown_expr(fcx, expected, rhs_0);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_assign_op(?op, ?lhs_0, ?rhs_0, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- pushdown_expr(scx, expected, lhs_0);
- pushdown_expr(scx, expected, rhs_0);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ pushdown_expr(fcx, expected, lhs_0);
+ pushdown_expr(fcx, expected, rhs_0);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_field(?lhs, ?rhs, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_index(?base, ?index, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_path(?pth, ?ann)) {
auto tp_substs_0 =
- ty::ann_to_type_params(scx.fcx.ccx.tcx.node_types, ann);
- auto t_0 = ann_to_type(scx.fcx.ccx.tcx.node_types, ann);
+ ty::ann_to_type_params(fcx.ccx.tcx, ann);
+ auto t_0 = ty::ann_to_monotype(fcx.ccx.tcx, ann);
- auto result_0 = demand::full(scx, e.span, expected, t_0,
+ auto result_0 = demand::full(fcx, e.span, expected, t_0,
tp_substs_0, adk);
- auto t = result_0._1;
+ auto t = ann_to_type(fcx.ccx.tcx, ann);
// Fill in the type parameter substitutions if they weren't
// provided by the programmer.
auto ty_params_opt;
- alt (ty::ann_to_ty_param_substs_opt_and_ty
- (scx.fcx.ccx.tcx.node_types, ann)._0) {
+
+ alt (ty::ann_to_ty_param_substs_opt_and_ty(fcx.ccx.tcx,
+ ann)._0) {
case (none) {
ty_params_opt = none[vec[ty::t]];
}
@@ -1351,12 +1268,12 @@ mod pushdown {
}
}
- write::ty_fixup(scx, ann.id, tup(ty_params_opt, t));
+ write::ty_fixup(fcx, ann.id, tup(ty_params_opt, t));
}
case (ast::expr_ext(?p, ?args, ?body, ?expanded, ?ann)) {
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
}
/* FIXME: should this check the type annotations? */
case (ast::expr_fail(_)) { /* no-op */ }
@@ -1370,47 +1287,47 @@ mod pushdown {
case (ast::expr_assert(_,_)) { /* no-op */ }
case (ast::expr_port(?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_chan(?es, ?ann)) {
- auto t = demand::simple(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann));
- alt (struct(scx.fcx.ccx.tcx, t)) {
+ auto t = demand::simple(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann));
+ alt (struct(fcx.ccx.tcx, t)) {
case (ty::ty_chan(?subty)) {
- auto pt = ty::mk_port(scx.fcx.ccx.tcx, subty);
- pushdown_expr(scx, pt, es);
+ auto pt = ty::mk_port(fcx.ccx.tcx, subty);
+ pushdown_expr(fcx, pt, es);
}
case (_) {
log "chan expr doesn't have a chan type!";
fail;
}
}
- write::ty_only_fixup(scx, ann.id, t);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_alt(?discrim, ?arms_0, ?ann)) {
auto t = expected;
for (ast::arm arm_0 in arms_0) {
- pushdown_block(scx, expected, arm_0.block);
- auto bty = block_ty(scx.fcx.ccx.tcx, arm_0.block);
- t = demand::simple(scx, e.span, t, bty);
+ pushdown_block(fcx, expected, arm_0.block);
+ auto bty = block_ty(fcx.ccx.tcx, arm_0.block);
+ t = demand::simple(fcx, e.span, t, bty);
}
- write::ty_only_fixup(scx, ann.id, t);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_recv(?lval, ?expr, ?ann)) {
- pushdown_expr(scx, next_ty_var(scx), lval);
- auto t = expr_ty(scx.fcx.ccx.tcx, lval);
- write::ty_only_fixup(scx, ann.id, t);
+ pushdown_expr(fcx, next_ty_var(fcx), lval);
+ auto t = expr_ty(fcx.ccx.tcx, lval);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_send(?lval, ?expr, ?ann)) {
- pushdown_expr(scx, next_ty_var(scx), expr);
- auto t = expr_ty(scx.fcx.ccx.tcx, expr);
- pushdown_expr(scx, ty::mk_chan(scx.fcx.ccx.tcx, t), lval);
+ pushdown_expr(fcx, next_ty_var(fcx), expr);
+ auto t = expr_ty(fcx.ccx.tcx, expr);
+ pushdown_expr(fcx, ty::mk_chan(fcx.ccx.tcx, t), lval);
}
case (ast::expr_spawn(?dom, ?name, ?func, ?args, ?ann)) {
@@ -1418,21 +1335,21 @@ mod pushdown {
// cases where e is an expression that could *possibly*
// produce a box; things like expr_binary or expr_bind can't,
// so there's no need.
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (ast::expr_anon_obj(?anon_obj, ?tps, ?odid, ?ann)) {
// NB: Not sure if this is correct, but not worrying too much
// about it since pushdown is going away anyway.
- auto t = demand::autoderef(scx, e.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
- write::ty_only_fixup(scx, ann.id, t);
+ auto t = demand::autoderef(fcx, e.span, expected,
+ ann_to_type(fcx.ccx.tcx, ann), adk);
+ write::ty_only_fixup(fcx, ann.id, t);
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_unimpl(e.span,
+ fcx.ccx.tcx.sess.span_unimpl(e.span,
#fmt("type unification for expression variant: %s",
pretty::pprust::expr_to_str(e)));
}
@@ -1440,89 +1357,99 @@ mod pushdown {
}
// Push-down over typed blocks.
- fn pushdown_block(&@stmt_ctxt scx, &ty::t expected, &ast::block bloc) {
+ fn pushdown_block(&@fn_ctxt fcx, &ty::t expected, &ast::block bloc) {
alt (bloc.node.expr) {
case (some(?e_0)) {
- pushdown_expr(scx, expected, e_0);
+ pushdown_expr(fcx, expected, e_0);
}
case (none) {
/* empty */
}
}
- demand::simple(scx, bloc.span, expected,
- ann_to_type(scx.fcx.ccx.tcx.node_types, bloc.node.a));
+ demand::simple(fcx, bloc.span, expected, ann_to_type(fcx.ccx.tcx,
+ bloc.node.a));
}
}
-// Local variable resolution: the phase that finds all the types in the AST
-// and replaces opaque "ty_local" types with the resolved local types.
+// Type resolution: the phase that finds all the types in the AST with
+// unresolved type variables and replaces "ty_var" types with their
+// substitutions.
+//
+// TODO: inefficient since not all types have vars in them. It would be better
+// to maintain a list of fixups.
mod writeback {
- fn wb_local(&@fn_ctxt fcx, &span sp, &@ast::local local) {
- auto local_ty;
- alt (fcx.locals.find(local.id)) {
- case (none) {
- fcx.ccx.tcx.sess.span_err(sp,
- "unable to determine type of local: " + local.ident);
- }
- case (some(?lt)) {
- local_ty = lt;
- }
- }
+ fn resolve_type_vars_in_type(&@fn_ctxt fcx, &span sp, ty::t typ)
+ -> ty::t {
+ if (!ty::type_contains_vars(fcx.ccx.tcx, typ)) { ret typ; }
- if (ty::type_contains_vars(fcx.ccx.tcx, local_ty)) {
- fcx.ccx.tcx.sess.span_err(sp,
- "Ambiguous type " + ty_to_str(fcx.ccx.tcx, local_ty)
- + "\n(Try adding more type annotations.)");
+ alt (ty::unify::fixup_vars(fcx.ccx.tcx, fcx.var_bindings, typ)) {
+ case (fix_ok(?new_type)) { ret new_type; }
+ case (fix_err(?vid)) {
+ fcx.ccx.tcx.sess.span_err(sp,
+ "cannot determine a type for this expression");
+ }
}
- write::ty_only(fcx.ccx.tcx, local.ann.id, local_ty);
}
- fn resolve_local_types(&@fn_ctxt fcx, &ast::ann ann) {
- fn resolver(@fn_ctxt fcx, ty::t typ) -> ty::t {
- alt (struct(fcx.ccx.tcx, typ)) {
- case (ty::ty_local(?lid)) { ret fcx.locals.get(lid); }
- case (_) { ret typ; }
+ fn resolve_type_vars_for_node(&@fn_ctxt fcx, &span sp, &ast::ann ann) {
+ auto tpot = ty::ann_to_ty_param_substs_opt_and_ty(fcx.ccx.tcx, ann);
+ auto new_ty = resolve_type_vars_in_type(fcx, sp, tpot._1);
+
+ auto new_substs_opt;
+ alt (tpot._0) {
+ case (none[vec[ty::t]]) { new_substs_opt = none[vec[ty::t]]; }
+ case (some[vec[ty::t]](?substs)) {
+ let vec[ty::t] new_substs = [];
+ for (ty::t subst in substs) {
+ new_substs += [resolve_type_vars_in_type(fcx, sp, subst)];
+ }
+ new_substs_opt = some[vec[ty::t]](new_substs);
}
}
- auto tpot =
- ty::ann_to_ty_param_substs_opt_and_ty(fcx.ccx.tcx.node_types,
- ann);
- auto tt = tpot._1;
- if (!ty::type_contains_locals(fcx.ccx.tcx, tt)) { ret; }
-
- auto f = bind resolver(fcx, _);
- auto new_type = ty::fold_ty(fcx.ccx.tcx, f, tt);
- write::ty(fcx.ccx.tcx, ann.id, tup(tpot._0, new_type));
+ write::ty(fcx.ccx.tcx, ann.id, tup(new_substs_opt, new_ty));
}
fn visit_stmt_pre(@fn_ctxt fcx, &@ast::stmt s) {
- resolve_local_types(fcx, ty::stmt_ann(s));
+ resolve_type_vars_for_node(fcx, s.span, ty::stmt_ann(s));
}
fn visit_expr_pre(@fn_ctxt fcx, &@ast::expr e) {
- resolve_local_types(fcx, ty::expr_ann(e));
+ resolve_type_vars_for_node(fcx, e.span, ty::expr_ann(e));
}
fn visit_block_pre(@fn_ctxt fcx, &ast::block b) {
- resolve_local_types(fcx, b.node.a);
+ resolve_type_vars_for_node(fcx, b.span, b.node.a);
}
- fn visit_arm_pre(@fn_ctxt fcx, &ast::arm a) {
- // FIXME: Need a visit_pat_pre
- resolve_local_types(fcx, ty::pat_ann(a.pat));
+ fn visit_pat_pre(@fn_ctxt fcx, &@ast::pat p) {
+ resolve_type_vars_for_node(fcx, p.span, ty::pat_ann(p));
}
fn visit_decl_pre(@fn_ctxt fcx, &@ast::decl d) {
alt (d.node) {
- case (ast::decl_local(?l)) { wb_local(fcx, d.span, l); }
- case (ast::decl_item(_)) { /* no annotation */ }
+ case (ast::decl_local(?l)) {
+ auto var_id = fcx.locals.get(l.id);
+ auto fix_rslt = ty::unify::resolve_type_var(fcx.ccx.tcx,
+ fcx.var_bindings, var_id);
+ alt (fix_rslt) {
+ case (fix_ok(?lty)) {
+ write::ty_only(fcx.ccx.tcx, l.ann.id, lty);
+ }
+ case (fix_err(_)) {
+ fcx.ccx.tcx.sess.span_err(d.span,
+ "cannot determine a type for this local " +
+ "variable");
+ }
+ }
+ }
+ case (_) { /* no-op */ }
}
}
- fn resolve_local_types_in_block(&@fn_ctxt fcx, &ast::block block) {
+ fn resolve_type_vars_in_block(&@fn_ctxt fcx, &ast::block block) {
// A trick to ignore any contained items.
auto ignore = @mutable false;
fn visit_item_pre(@mutable bool ignore, &@ast::item item) {
@@ -1539,7 +1466,7 @@ mod writeback {
visit_stmt_pre=bind visit_stmt_pre(fcx, _),
visit_expr_pre=bind visit_expr_pre(fcx, _),
visit_block_pre=bind visit_block_pre(fcx, _),
- visit_arm_pre=bind visit_arm_pre(fcx, _),
+ visit_pat_pre=bind visit_pat_pre(fcx, _),
visit_decl_pre=bind visit_decl_pre(fcx, _)
with walk::default_visitor());
walk::walk_block(visit, block);
@@ -1547,19 +1474,151 @@ mod writeback {
}
+// Local variable gathering. We gather up all locals and create variable IDs
+// for them before typechecking the function.
+
+type gather_result = rec(
+ @ty::unify::var_bindings var_bindings,
+ hashmap[ast::def_id,int] locals,
+ hashmap[ast::def_id,ast::ident] local_names,
+ int next_var_id
+);
+
+fn gather_locals(&@crate_ctxt ccx, &ast::fn_decl decl, &ast::block body,
+ &ast::ann ann) -> gather_result {
+ fn next_var_id(@mutable int nvi) -> int {
+ auto rv = *nvi;
+ *nvi += 1;
+ ret rv;
+ }
+
+ fn assign(&ty::ctxt tcx,
+ &@ty::unify::var_bindings var_bindings,
+ &hashmap[ast::def_id,int] locals,
+ &hashmap[ast::def_id,ast::ident] local_names,
+ @mutable int nvi,
+ ast::def_id lid,
+ &ast::ident ident,
+ option::t[ty::t] ty_opt) {
+ auto var_id = next_var_id(nvi);
+ locals.insert(lid, var_id);
+ local_names.insert(lid, ident);
+
+ alt (ty_opt) {
+ case (none[ty::t]) { /* nothing to do */ }
+ case (some[ty::t](?typ)) {
+ ty::unify::unify(ty::mk_var(tcx, var_id), typ, var_bindings,
+ tcx);
+ }
+ }
+ }
+
+ auto vb = ty::unify::mk_var_bindings();
+ auto locals = new_def_hash[int]();
+ auto local_names = new_def_hash[ast::ident]();
+ auto nvi = @mutable 0;
+
+ // Add object fields, if any.
+ alt (get_obj_info(ccx)) {
+ case (option::some(?oinfo)) {
+ for (ast::obj_field f in oinfo.obj_fields) {
+ auto field_ty = ty::ann_to_type(ccx.tcx, f.ann);
+ assign(ccx.tcx, vb, locals, local_names, nvi, f.id, f.ident,
+ some[ty::t](field_ty));
+ }
+ }
+ case (option::none) { /* no fields */ }
+ }
+
+ // Add formal parameters.
+ auto args = ty::ty_fn_args(ccx.tcx, ty::ann_to_type(ccx.tcx, ann));
+ auto i = 0u;
+ for (ty::arg arg in args) {
+ assign(ccx.tcx, vb, locals, local_names, nvi, decl.inputs.(i).id,
+ decl.inputs.(i).ident, some[ty::t](arg.ty));
+ i += 1u;
+ }
+
+ // Add explicitly-declared locals.
+ fn visit_decl_pre(@crate_ctxt ccx,
+ @ty::unify::var_bindings vb,
+ hashmap[ast::def_id,int] locals,
+ hashmap[ast::def_id,ast::ident] local_names,
+ @mutable int nvi,
+ &@ast::decl d) {
+ alt (d.node) {
+ case (ast::decl_local(?local)) {
+ alt (local.ty) {
+ case (none) {
+ // Auto slot.
+ assign(ccx.tcx, vb, locals, local_names, nvi,
+ local.id, local.ident, none[ty::t]);
+ }
+ case (some(?ast_ty)) {
+ // Explicitly typed slot.
+ auto local_ty = ast_ty_to_ty_crate(ccx, ast_ty);
+ assign(ccx.tcx, vb, locals, local_names, nvi,
+ local.id, local.ident, some[ty::t](local_ty));
+ }
+ }
+ }
+ case (_) { /* no-op */ }
+ }
+ }
+
+ // Add pattern bindings.
+ fn visit_pat_pre(@crate_ctxt ccx,
+ @ty::unify::var_bindings vb,
+ hashmap[ast::def_id,int] locals,
+ hashmap[ast::def_id,ast::ident] local_names,
+ @mutable int nvi,
+ &@ast::pat p) {
+ alt (p.node) {
+ case (ast::pat_bind(?ident, ?did, _)) {
+ assign(ccx.tcx, vb, locals, local_names, nvi, did, ident,
+ none[ty::t]);
+ }
+ case (_) { /* no-op */ }
+ }
+ }
+
+ auto visit =
+ rec(visit_decl_pre=bind visit_decl_pre(ccx, vb, locals, local_names,
+ nvi, _),
+ visit_pat_pre=bind visit_pat_pre(ccx, vb, locals, local_names,
+ nvi, _)
+ with walk::default_visitor());
+ walk::walk_block(visit, body);
+
+ ret rec(
+ var_bindings=vb,
+ locals=locals,
+ local_names=local_names,
+ next_var_id=*nvi
+ );
+}
+
+
// AST fragment utilities
-fn replace_expr_type(&@stmt_ctxt scx,
+fn replace_expr_type(&@fn_ctxt fcx,
&@ast::expr expr,
&tup(vec[ty::t], ty::t) new_tyt) {
auto new_tps;
- if (ty::expr_has_ty_params(scx.fcx.ccx.tcx.node_types, expr)) {
+ if (ty::expr_has_ty_params(fcx.ccx.tcx, expr)) {
new_tps = some[vec[ty::t]](new_tyt._0);
} else {
new_tps = none[vec[ty::t]];
}
- write::ty_fixup(scx, ty::expr_ann(expr).id, tup(new_tps, new_tyt._1));
+ write::ty_fixup(fcx, ty::expr_ann(expr).id, tup(new_tps, new_tyt._1));
+}
+
+fn replace_node_type_only(&ty::ctxt tcx, uint fixup, ty::t new_t) {
+ auto fixup_opt = tcx.node_types.(fixup);
+ auto tps = option::get[ty::ty_param_substs_opt_and_ty](fixup_opt)._0;
+ tcx.node_types.(fixup) =
+ some[ty::ty_param_substs_opt_and_ty](tup(tps, new_t));
}
@@ -1581,50 +1640,53 @@ fn check_lit(@crate_ctxt ccx, &@ast::lit lit) -> ty::t {
// Pattern checking is top-down rather than bottom-up so that bindings get
// their types immediately.
-fn check_pat(&@stmt_ctxt scx, &@ast::pat pat, ty::t expected) {
+fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
alt (pat.node) {
case (ast::pat_wild(?ann)) {
- write::ty_only_fixup(scx, ann.id, expected);
+ write::ty_only_fixup(fcx, ann.id, expected);
}
case (ast::pat_lit(?lt, ?ann)) {
- auto typ = check_lit(scx.fcx.ccx, lt);
- typ = demand::simple(scx, pat.span, expected, typ);
- write::ty_only_fixup(scx, ann.id, typ);
+ auto typ = check_lit(fcx.ccx, lt);
+ typ = demand::simple(fcx, pat.span, expected, typ);
+ write::ty_only_fixup(fcx, ann.id, typ);
}
case (ast::pat_bind(?id, ?def_id, ?ann)) {
- scx.fcx.locals.insert(def_id, expected);
- write::ty_only_fixup(scx, ann.id, expected);
+ auto vid = fcx.locals.get(def_id);
+ auto typ = ty::mk_var(fcx.ccx.tcx, vid);
+ typ = demand::simple(fcx, pat.span, expected, typ);
+ write::ty_only_fixup(fcx, ann.id, typ);
}
case (ast::pat_tag(?path, ?subpats, ?ann)) {
// Typecheck the path.
- auto v_def = scx.fcx.ccx.tcx.def_map.get(ann.id);
+ auto v_def = fcx.ccx.tcx.def_map.get(ann.id);
auto v_def_ids = ast::variant_def_ids(v_def);
- auto tag_tpt = ty::lookup_item_type(scx.fcx.ccx.tcx,
+ auto tag_tpt = ty::lookup_item_type(fcx.ccx.tcx,
v_def_ids._0);
- auto path_tpot = instantiate_path(scx, path, tag_tpt, pat.span);
+ auto path_tpot = instantiate_path(fcx, path, tag_tpt, pat.span);
// Take the tag type params out of `expected`.
auto expected_tps;
- alt (struct(scx.fcx.ccx.tcx, expected)) {
+ alt (struct(fcx.ccx.tcx, expected)) {
case (ty::ty_tag(_, ?tps)) { expected_tps = tps; }
case (_) {
// FIXME: Switch expected and actual in this message? I
// can never tell.
- scx.fcx.ccx.tcx.sess.span_err(pat.span,
+ fcx.ccx.tcx.sess.span_err(pat.span,
#fmt("mismatched types: expected tag but found %s",
- ty::ty_to_str(scx.fcx.ccx.tcx, expected)));
+ ty::ty_to_str(fcx.ccx.tcx, expected)));
}
}
// Unify with the expected tag type.
- auto path_tpt = demand::full(scx, pat.span, expected,
- path_tpot._1, expected_tps,
- NO_AUTODEREF);
+ auto ctor_ty = ty::ty_param_substs_opt_and_ty_to_monotype(
+ fcx.ccx.tcx, path_tpot);
+ auto path_tpt = demand::full(fcx, pat.span, expected, ctor_ty,
+ expected_tps, NO_AUTODEREF);
path_tpot = tup(some[vec[ty::t]](path_tpt._0), path_tpt._1);
// Get the number of arguments in this tag variant.
- auto arg_types = variant_arg_types(scx.fcx.ccx, pat.span,
+ auto arg_types = variant_arg_types(fcx.ccx, pat.span,
v_def_ids._1, expected_tps);
auto subpats_len = vec::len[@ast::pat](subpats);
@@ -1636,7 +1698,7 @@ fn check_pat(&@stmt_ctxt scx, &@ast::pat pat, ty::t expected) {
// TODO: note definition of tag variant
// TODO (issue #448): Wrap a #fmt string over multiple
// lines...
- scx.fcx.ccx.tcx.sess.span_err(pat.span, #fmt(
+ fcx.ccx.tcx.sess.span_err(pat.span, #fmt(
"this pattern has %u field%s, but the corresponding variant has %u field%s",
subpats_len,
if (subpats_len == 0u) { "" } else { "s" },
@@ -1647,20 +1709,20 @@ fn check_pat(&@stmt_ctxt scx, &@ast::pat pat, ty::t expected) {
// TODO: vec::iter2
auto i = 0u;
for (@ast::pat subpat in subpats) {
- check_pat(scx, subpat, arg_types.(i));
+ check_pat(fcx, subpat, arg_types.(i));
i += 1u;
}
} else if (subpats_len > 0u) {
// TODO: note definition of tag variant
// TODO (issue #448): Wrap a #fmt string over multiple
// lines...
- scx.fcx.ccx.tcx.sess.span_err(pat.span, #fmt(
+ fcx.ccx.tcx.sess.span_err(pat.span, #fmt(
"this pattern has %u field%s, but the corresponding variant has no fields",
subpats_len,
if (subpats_len == 0u) { "" } else { "s" }));
}
- write::ty_fixup(scx, ann.id, path_tpot);
+ write::ty_fixup(fcx, ann.id, path_tpot);
}
}
}
@@ -1727,16 +1789,16 @@ fn require_pure_function(@crate_ctxt ccx, &ast::def_id d_id, &span sp) -> () {
}
}
-fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
- // scx.fcx.ccx.tcx.sess.span_warn(expr.span, "typechecking expr " +
+fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
+ // fcx.ccx.tcx.sess.span_warn(expr.span, "typechecking expr " +
// pretty::pprust::expr_to_str(expr));
// A generic function to factor out common logic from call and bind
// expressions.
- fn check_call_or_bind(&@stmt_ctxt scx, &@ast::expr f,
+ fn check_call_or_bind(&@fn_ctxt fcx, &@ast::expr f,
&vec[option::t[@ast::expr]] args) {
// Check the function.
- check_expr(scx, f);
+ check_expr(fcx, f);
// Check the arguments and generate the argument signature.
let vec[option::t[@ast::expr]] args_0 = [];
@@ -1744,223 +1806,225 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
for (option::t[@ast::expr] a_opt in args) {
alt (a_opt) {
case (some(?a)) {
- check_expr(scx, a);
- auto typ = expr_ty(scx.fcx.ccx.tcx, a);
+ check_expr(fcx, a);
+ auto typ = expr_ty(fcx.ccx.tcx, a);
vec::push[arg](arg_tys_0, rec(mode=mo_either, ty=typ));
}
case (none) {
- auto typ = next_ty_var(scx);
+ auto typ = next_ty_var(fcx);
vec::push[arg](arg_tys_0, rec(mode=mo_either, ty=typ));
}
}
}
- auto rt_0 = next_ty_var(scx);
+ auto rt_0 = next_ty_var(fcx);
auto t_0;
- alt (struct(scx.fcx.ccx.tcx, expr_ty(scx.fcx.ccx.tcx, f))) {
+ alt (struct(fcx.ccx.tcx, expr_ty(fcx.ccx.tcx, f))) {
case (ty::ty_fn(?proto, _, _, ?cf)) {
- t_0 = ty::mk_fn(scx.fcx.ccx.tcx, proto, arg_tys_0, rt_0, cf);
+ t_0 = ty::mk_fn(fcx.ccx.tcx, proto, arg_tys_0, rt_0, cf);
}
case (ty::ty_native_fn(?abi, _, _)) {
- t_0 = ty::mk_native_fn(scx.fcx.ccx.tcx, abi, arg_tys_0, rt_0);
+ t_0 = ty::mk_native_fn(fcx.ccx.tcx, abi, arg_tys_0, rt_0);
}
case (?u) {
- scx.fcx.ccx.tcx.sess.span_err(f.span,
+ fcx.ccx.tcx.sess.span_err(f.span,
"check_call_or_bind(): fn expr doesn't have fn type,"
+ " instead having: " +
- ty_to_str(scx.fcx.ccx.tcx,
- expr_ty(scx.fcx.ccx.tcx, f)));
+ ty_to_str(fcx.ccx.tcx,
+ expr_ty(fcx.ccx.tcx, f)));
}
}
// Unify the callee and arguments.
- auto tpt_0 = ty::expr_ty_params_and_ty(scx.fcx.ccx.tcx, f);
- auto tpt_1 = demand::full(scx, f.span, tpt_0._1, t_0, tpt_0._0,
+ auto f_ty = ty::expr_ty(fcx.ccx.tcx, f);
+ auto f_tps = ty::expr_ty_params_and_ty(fcx.ccx.tcx, f)._0;
+ auto tpt_1 = demand::full(fcx, f.span, f_ty, t_0, f_tps,
NO_AUTODEREF);
- replace_expr_type(scx, f, tpt_1);
+ //replace_expr_type(fcx, f, tpt_1);
}
// A generic function for checking assignment expressions
- fn check_assignment(&@stmt_ctxt scx, &@ast::expr lhs, &@ast::expr rhs,
+ fn check_assignment(&@fn_ctxt fcx, &@ast::expr lhs, &@ast::expr rhs,
&ast::ann a) {
- check_expr(scx, lhs);
- check_expr(scx, rhs);
- auto lhs_t0 = expr_ty(scx.fcx.ccx.tcx, lhs);
- auto rhs_t0 = expr_ty(scx.fcx.ccx.tcx, rhs);
+ check_expr(fcx, lhs);
+ check_expr(fcx, rhs);
+ auto lhs_t0 = expr_ty(fcx.ccx.tcx, lhs);
+ auto rhs_t0 = expr_ty(fcx.ccx.tcx, rhs);
- pushdown::pushdown_expr(scx, rhs_t0, lhs);
- auto lhs_t1 = expr_ty(scx.fcx.ccx.tcx, lhs);
- pushdown::pushdown_expr(scx, lhs_t1, rhs);
- auto rhs_t1 = expr_ty(scx.fcx.ccx.tcx, rhs);
+ pushdown::pushdown_expr(fcx, rhs_t0, lhs);
+ auto lhs_t1 = expr_ty(fcx.ccx.tcx, lhs);
+ pushdown::pushdown_expr(fcx, lhs_t1, rhs);
+ auto rhs_t1 = expr_ty(fcx.ccx.tcx, rhs);
- write::ty_only_fixup(scx, a.id, rhs_t1);
+ write::ty_only_fixup(fcx, a.id, rhs_t1);
}
// A generic function for checking call expressions
- fn check_call(&@stmt_ctxt scx, &@ast::expr f, &vec[@ast::expr] args) {
+ fn check_call(&@fn_ctxt fcx, &@ast::expr f, &vec[@ast::expr] args) {
let vec[option::t[@ast::expr]] args_opt_0 = [];
for (@ast::expr arg in args) {
args_opt_0 += [some[@ast::expr](arg)];
}
// Call the generic checker.
- check_call_or_bind(scx, f, args_opt_0);
+ check_call_or_bind(fcx, f, args_opt_0);
}
// A generic function for checking for or for-each loops
- fn check_for_or_for_each(&@stmt_ctxt scx, &@ast::decl decl,
+ fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::decl decl,
&ty::t element_ty, &ast::block body,
uint node_id) {
- check_decl_local(scx.fcx, decl);
- check_block(scx, body);
+ check_decl_local(fcx, decl);
+ check_block(fcx, body);
// Unify type of decl with element type of the seq
- demand::simple(scx, decl.span, ty::decl_local_ty(scx.fcx.ccx.tcx,
+ demand::simple(fcx, decl.span, ty::decl_local_ty(fcx.ccx.tcx,
decl),
element_ty);
- auto typ = ty::mk_nil(scx.fcx.ccx.tcx);
- write::ty_only_fixup(scx, node_id, typ);
+ auto typ = ty::mk_nil(fcx.ccx.tcx);
+ write::ty_only_fixup(fcx, node_id, typ);
}
alt (expr.node) {
case (ast::expr_lit(?lit, ?a)) {
- auto typ = check_lit(scx.fcx.ccx, lit);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = check_lit(fcx.ccx, lit);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (ast::expr_binary(?binop, ?lhs, ?rhs, ?a)) {
- check_expr(scx, lhs);
- check_expr(scx, rhs);
- auto lhs_t0 = expr_ty(scx.fcx.ccx.tcx, lhs);
- auto rhs_t0 = expr_ty(scx.fcx.ccx.tcx, rhs);
+ check_expr(fcx, lhs);
+ check_expr(fcx, rhs);
+ auto lhs_t0 = expr_ty(fcx.ccx.tcx, lhs);
+ auto rhs_t0 = expr_ty(fcx.ccx.tcx, rhs);
// FIXME: Binops have a bit more subtlety than this.
- pushdown::pushdown_expr_full(scx, rhs_t0, lhs, AUTODEREF_OK);
- auto lhs_t1 = expr_ty(scx.fcx.ccx.tcx, lhs);
- pushdown::pushdown_expr_full(scx, lhs_t1, rhs, AUTODEREF_OK);
+ pushdown::pushdown_expr_full(fcx, rhs_t0, lhs, AUTODEREF_OK);
+ auto lhs_t1 = expr_ty(fcx.ccx.tcx, lhs);
+ pushdown::pushdown_expr_full(fcx, lhs_t1, rhs, AUTODEREF_OK);
- auto t = strip_boxes(scx.fcx.ccx.tcx, lhs_t0);
+ auto t = strip_boxes(fcx.ccx.tcx, lhs_t0);
alt (binop) {
- case (ast::eq) { t = ty::mk_bool(scx.fcx.ccx.tcx); }
- case (ast::lt) { t = ty::mk_bool(scx.fcx.ccx.tcx); }
- case (ast::le) { t = ty::mk_bool(scx.fcx.ccx.tcx); }
- case (ast::ne) { t = ty::mk_bool(scx.fcx.ccx.tcx); }
- case (ast::ge) { t = ty::mk_bool(scx.fcx.ccx.tcx); }
- case (ast::gt) { t = ty::mk_bool(scx.fcx.ccx.tcx); }
+ case (ast::eq) { t = ty::mk_bool(fcx.ccx.tcx); }
+ case (ast::lt) { t = ty::mk_bool(fcx.ccx.tcx); }
+ case (ast::le) { t = ty::mk_bool(fcx.ccx.tcx); }
+ case (ast::ne) { t = ty::mk_bool(fcx.ccx.tcx); }
+ case (ast::ge) { t = ty::mk_bool(fcx.ccx.tcx); }
+ case (ast::gt) { t = ty::mk_bool(fcx.ccx.tcx); }
case (_) { /* fall through */ }
}
- write::ty_only_fixup(scx, a.id, t);
+ write::ty_only_fixup(fcx, a.id, t);
}
case (ast::expr_unary(?unop, ?oper, ?a)) {
- check_expr(scx, oper);
+ check_expr(fcx, oper);
- auto oper_t = expr_ty(scx.fcx.ccx.tcx, oper);
+ auto oper_t = expr_ty(fcx.ccx.tcx, oper);
alt (unop) {
case (ast::box(?mut)) {
- oper_t = ty::mk_box(scx.fcx.ccx.tcx,
+ oper_t = ty::mk_box(fcx.ccx.tcx,
rec(ty=oper_t, mut=mut));
}
case (ast::deref) {
- alt (struct(scx.fcx.ccx.tcx, oper_t)) {
+ alt (struct(fcx.ccx.tcx, oper_t)) {
case (ty::ty_box(?inner)) { oper_t = inner.ty; }
case (_) {
- scx.fcx.ccx.tcx.sess.span_err
+ fcx.ccx.tcx.sess.span_err
(expr.span,
"dereferencing non-box type: "
- + ty_to_str(scx.fcx.ccx.tcx, oper_t));
+ + ty_to_str(fcx.ccx.tcx, oper_t));
}
}
}
- case (_) { oper_t = strip_boxes(scx.fcx.ccx.tcx, oper_t); }
+ case (_) { oper_t = strip_boxes(fcx.ccx.tcx, oper_t); }
}
- write::ty_only_fixup(scx, a.id, oper_t);
+ write::ty_only_fixup(fcx, a.id, oper_t);
}
case (ast::expr_path(?pth, ?old_ann)) {
- auto t = ty::mk_nil(scx.fcx.ccx.tcx);
- auto defn = scx.fcx.ccx.tcx.def_map.get(old_ann.id);
+ auto t = ty::mk_nil(fcx.ccx.tcx);
+ auto defn = fcx.ccx.tcx.def_map.get(old_ann.id);
- auto tpt = ty_param_count_and_ty_for_def(scx.fcx, expr.span,
+ 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(scx, pth, tpt, expr.span);
- write::ty_fixup(scx, old_ann.id, path_tpot);
+ auto path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
+ write::ty_fixup(fcx, old_ann.id, path_tpot);
ret;
}
// The definition doesn't take type parameters. If the programmer
// supplied some, that's an error.
if (vec::len[@ast::ty](pth.node.types) > 0u) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"this kind of value does not take type parameters");
}
- write::ty_only_fixup(scx, old_ann.id, tpt._1);
+ write::ty_only_fixup(fcx, old_ann.id, tpt._1);
}
case (ast::expr_ext(?p, ?args, ?body, ?expanded, ?a)) {
- check_expr(scx, expanded);
- auto t = expr_ty(scx.fcx.ccx.tcx, expanded);
- write::ty_only_fixup(scx, a.id, t);
+ check_expr(fcx, expanded);
+ auto t = expr_ty(fcx.ccx.tcx, expanded);
+ write::ty_only_fixup(fcx, a.id, t);
}
case (ast::expr_fail(?a)) {
- write::bot_ty(scx.fcx.ccx.tcx, a.id);
+ write::bot_ty(fcx.ccx.tcx, a.id);
}
case (ast::expr_break(?a)) {
- write::bot_ty(scx.fcx.ccx.tcx, a.id);
+ write::bot_ty(fcx.ccx.tcx, a.id);
}
case (ast::expr_cont(?a)) {
- write::bot_ty(scx.fcx.ccx.tcx, a.id);
+ write::bot_ty(fcx.ccx.tcx, a.id);
}
case (ast::expr_ret(?expr_opt, ?a)) {
alt (expr_opt) {
case (none) {
- auto nil = ty::mk_nil(scx.fcx.ccx.tcx);
- if (!are_compatible(scx, scx.fcx.ret_ty, nil)) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ auto nil = ty::mk_nil(fcx.ccx.tcx);
+ if (!are_compatible(fcx, fcx.ret_ty, nil)) {
+ fcx.ccx.tcx.sess.span_err(expr.span,
"ret; in function returning non-nil");
}
- write::bot_ty(scx.fcx.ccx.tcx, a.id);
+ write::bot_ty(fcx.ccx.tcx, a.id);
}
case (some(?e)) {
- check_expr(scx, e);
- pushdown::pushdown_expr(scx, scx.fcx.ret_ty, e);
+ check_expr(fcx, e);
- write::bot_ty(scx.fcx.ccx.tcx, a.id);
+ pushdown::pushdown_expr(fcx, fcx.ret_ty, e);
+
+ write::bot_ty(fcx.ccx.tcx, a.id);
}
}
}
case (ast::expr_put(?expr_opt, ?a)) {
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
alt (expr_opt) {
case (none) {
- auto nil = ty::mk_nil(scx.fcx.ccx.tcx);
- if (!are_compatible(scx, scx.fcx.ret_ty, nil)) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ auto nil = ty::mk_nil(fcx.ccx.tcx);
+ if (!are_compatible(fcx, fcx.ret_ty, nil)) {
+ fcx.ccx.tcx.sess.span_err(expr.span,
"put; in iterator yielding non-nil");
}
- write::nil_ty(scx.fcx.ccx.tcx, a.id);
+ write::nil_ty(fcx.ccx.tcx, a.id);
}
case (some(?e)) {
- check_expr(scx, e);
- pushdown::pushdown_expr(scx, scx.fcx.ret_ty, e);
+ check_expr(fcx, e);
+ pushdown::pushdown_expr(fcx, fcx.ret_ty, e);
- write::nil_ty(scx.fcx.ccx.tcx, a.id);
+ write::nil_ty(fcx.ccx.tcx, a.id);
}
}
}
@@ -1969,21 +2033,21 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
// FIXME: prove instead of assert
assert (ast::is_call_expr(e));
- check_expr(scx, e);
- pushdown::pushdown_expr(scx, scx.fcx.ret_ty, e);
+ check_expr(fcx, e);
+ pushdown::pushdown_expr(fcx, fcx.ret_ty, e);
- write::nil_ty(scx.fcx.ccx.tcx, a.id);
+ write::nil_ty(fcx.ccx.tcx, a.id);
}
case (ast::expr_log(?l, ?e, ?a)) {
- auto expr_t = check_expr(scx, e);
- write::nil_ty(scx.fcx.ccx.tcx, a.id);
+ auto expr_t = check_expr(fcx, e);
+ write::nil_ty(fcx.ccx.tcx, a.id);
}
case (ast::expr_check(?e, ?a)) {
- check_expr(scx, e);
- demand::simple(scx, expr.span, ty::mk_bool(scx.fcx.ccx.tcx),
- expr_ty(scx.fcx.ccx.tcx, e));
+ check_expr(fcx, e);
+ demand::simple(fcx, expr.span, ty::mk_bool(fcx.ccx.tcx),
+ expr_ty(fcx.ccx.tcx, e));
/* e must be a call expr where all arguments are either
literals or slots */
alt (e.node) {
@@ -1991,237 +2055,237 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
alt (operator.node) {
case (ast::expr_path(?oper_name, ?ann)) {
auto d_id;
- alt (scx.fcx.ccx.tcx.def_map.get(ann.id)) {
+ alt (fcx.ccx.tcx.def_map.get(ann.id)) {
case (ast::def_fn(?_d_id)) { d_id = _d_id; }
}
for (@ast::expr operand in operands) {
if (! ast::is_constraint_arg(operand)) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"Constraint args must be "
+ "slot variables or literals");
}
}
- require_pure_function(scx.fcx.ccx, d_id,
+ require_pure_function(fcx.ccx, d_id,
expr.span);
- write::nil_ty(scx.fcx.ccx.tcx, a.id);
+ write::nil_ty(fcx.ccx.tcx, a.id);
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"In a constraint, expected the constraint name "
+ "to be an explicit name");
}
}
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"check on non-predicate");
}
}
}
case (ast::expr_assert(?e, ?a)) {
- check_expr(scx, e);
- auto ety = expr_ty(scx.fcx.ccx.tcx, e);
- demand::simple(scx, expr.span, ty::mk_bool(scx.fcx.ccx.tcx), ety);
+ check_expr(fcx, e);
+ auto ety = expr_ty(fcx.ccx.tcx, e);
+ demand::simple(fcx, expr.span, ty::mk_bool(fcx.ccx.tcx), ety);
- write::nil_ty(scx.fcx.ccx.tcx, a.id);
+ write::nil_ty(fcx.ccx.tcx, a.id);
}
case (ast::expr_move(?lhs, ?rhs, ?a)) {
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
- check_assignment(scx, lhs, rhs, a);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
+ check_assignment(fcx, lhs, rhs, a);
}
case (ast::expr_assign(?lhs, ?rhs, ?a)) {
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
- check_assignment(scx, lhs, rhs, a);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
+ check_assignment(fcx, lhs, rhs, a);
}
case (ast::expr_assign_op(?op, ?lhs, ?rhs, ?a)) {
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
- check_assignment(scx, lhs, rhs, a);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
+ check_assignment(fcx, lhs, rhs, a);
}
case (ast::expr_send(?lhs, ?rhs, ?a)) {
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
- check_expr(scx, lhs);
- check_expr(scx, rhs);
- auto rhs_t = expr_ty(scx.fcx.ccx.tcx, rhs);
+ check_expr(fcx, lhs);
+ check_expr(fcx, rhs);
+ auto rhs_t = expr_ty(fcx.ccx.tcx, rhs);
- auto chan_t = ty::mk_chan(scx.fcx.ccx.tcx, rhs_t);
- pushdown::pushdown_expr(scx, chan_t, lhs);
+ auto chan_t = ty::mk_chan(fcx.ccx.tcx, rhs_t);
+ pushdown::pushdown_expr(fcx, chan_t, lhs);
auto item_t;
- auto lhs_t = expr_ty(scx.fcx.ccx.tcx, lhs);
- alt (struct(scx.fcx.ccx.tcx, lhs_t)) {
+ auto lhs_t = expr_ty(fcx.ccx.tcx, lhs);
+ alt (struct(fcx.ccx.tcx, lhs_t)) {
case (ty::ty_chan(?it)) { item_t = it; }
case (_) { fail; }
}
- pushdown::pushdown_expr(scx, item_t, rhs);
+ pushdown::pushdown_expr(fcx, item_t, rhs);
- write::ty_only_fixup(scx, a.id, chan_t);
+ write::ty_only_fixup(fcx, a.id, chan_t);
}
case (ast::expr_recv(?lhs, ?rhs, ?a)) {
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
- check_expr(scx, lhs);
- check_expr(scx, rhs);
- auto lhs_t1 = expr_ty(scx.fcx.ccx.tcx, lhs);
+ check_expr(fcx, lhs);
+ check_expr(fcx, rhs);
+ auto lhs_t1 = expr_ty(fcx.ccx.tcx, lhs);
- auto port_t = ty::mk_port(scx.fcx.ccx.tcx, lhs_t1);
- pushdown::pushdown_expr(scx, port_t, rhs);
+ auto port_t = ty::mk_port(fcx.ccx.tcx, lhs_t1);
+ pushdown::pushdown_expr(fcx, port_t, rhs);
auto item_t;
- auto rhs_t = expr_ty(scx.fcx.ccx.tcx, rhs);
- alt (struct(scx.fcx.ccx.tcx, rhs_t)) {
+ auto rhs_t = expr_ty(fcx.ccx.tcx, rhs);
+ alt (struct(fcx.ccx.tcx, rhs_t)) {
case (ty::ty_port(?it)) { item_t = it; }
case (_) { fail; }
}
- pushdown::pushdown_expr(scx, item_t, lhs);
+ pushdown::pushdown_expr(fcx, item_t, lhs);
- write::ty_only_fixup(scx, a.id, item_t);
+ write::ty_only_fixup(fcx, a.id, item_t);
}
case (ast::expr_if(?cond, ?thn, ?elsopt, ?a)) {
- check_expr(scx, cond);
- pushdown::pushdown_expr(scx, ty::mk_bool(scx.fcx.ccx.tcx),
+ check_expr(fcx, cond);
+ pushdown::pushdown_expr(fcx, ty::mk_bool(fcx.ccx.tcx),
cond);
- check_block(scx, thn);
+ check_block(fcx, thn);
auto if_t = alt (elsopt) {
case (some(?els)) {
- check_expr(scx, els);
+ check_expr(fcx, els);
- auto thn_t = block_ty(scx.fcx.ccx.tcx, thn);
- auto elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
- if (!ty::type_is_bot(scx.fcx.ccx.tcx, elsopt_t)) {
+ auto thn_t = block_ty(fcx.ccx.tcx, thn);
+ auto elsopt_t = expr_ty(fcx.ccx.tcx, els);
+ if (!ty::type_is_bot(fcx.ccx.tcx, elsopt_t)) {
elsopt_t
} else {
thn_t
}
}
case (none) {
- ty::mk_nil(scx.fcx.ccx.tcx)
+ ty::mk_nil(fcx.ccx.tcx)
}
};
- write::ty_only_fixup(scx, a.id, if_t);
+ write::ty_only_fixup(fcx, a.id, if_t);
}
case (ast::expr_for(?decl, ?seq, ?body, ?a)) {
- check_expr(scx, seq);
- alt (struct (scx.fcx.ccx.tcx,
- expr_ty(scx.fcx.ccx.tcx, seq))) {
+ check_expr(fcx, seq);
+ alt (struct (fcx.ccx.tcx,
+ expr_ty(fcx.ccx.tcx, seq))) {
// FIXME: I include the check_for_or_each call in
// each case because of a bug in typestate.
// The bug is fixed; once there's a new snapshot,
// the call can be moved out of the alt expression
case (ty::ty_vec(?vec_elt_ty)) {
auto elt_ty = vec_elt_ty.ty;
- check_for_or_for_each(scx, decl, elt_ty, body, a.id);
+ check_for_or_for_each(fcx, decl, elt_ty, body, a.id);
}
case (ty::ty_str) {
- auto elt_ty = ty::mk_mach(scx.fcx.ccx.tcx,
+ auto elt_ty = ty::mk_mach(fcx.ccx.tcx,
util::common::ty_u8);
- check_for_or_for_each(scx, decl, elt_ty, body, a.id);
+ check_for_or_for_each(fcx, decl, elt_ty, body, a.id);
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"type of for loop iterator is not a vector or string");
}
}
}
case (ast::expr_for_each(?decl, ?seq, ?body, ?a)) {
- check_expr(scx, seq);
- check_for_or_for_each(scx, decl, expr_ty(scx.fcx.ccx.tcx, seq),
+ check_expr(fcx, seq);
+ check_for_or_for_each(fcx, decl, expr_ty(fcx.ccx.tcx, seq),
body, a.id);
}
case (ast::expr_while(?cond, ?body, ?a)) {
- check_expr(scx, cond);
- pushdown::pushdown_expr(scx, ty::mk_bool(scx.fcx.ccx.tcx), cond);
- check_block(scx, body);
+ check_expr(fcx, cond);
+ pushdown::pushdown_expr(fcx, ty::mk_bool(fcx.ccx.tcx), cond);
+ check_block(fcx, body);
- auto typ = ty::mk_nil(scx.fcx.ccx.tcx);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_nil(fcx.ccx.tcx);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (ast::expr_do_while(?body, ?cond, ?a)) {
- check_expr(scx, cond);
- pushdown::pushdown_expr(scx, ty::mk_bool(scx.fcx.ccx.tcx), cond);
- check_block(scx, body);
+ check_expr(fcx, cond);
+ pushdown::pushdown_expr(fcx, ty::mk_bool(fcx.ccx.tcx), cond);
+ check_block(fcx, body);
- auto typ = block_ty(scx.fcx.ccx.tcx, body);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = block_ty(fcx.ccx.tcx, body);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (ast::expr_alt(?expr, ?arms, ?a)) {
- check_expr(scx, expr);
+ check_expr(fcx, expr);
// Typecheck the patterns first, so that we get types for all the
// bindings.
- auto pattern_ty = ty::expr_ty(scx.fcx.ccx.tcx, expr);
+ auto pattern_ty = ty::expr_ty(fcx.ccx.tcx, expr);
let vec[@ast::pat] pats = [];
for (ast::arm arm in arms) {
- check_pat(scx, arm.pat, pattern_ty);
+ check_pat(fcx, arm.pat, pattern_ty);
pats += [arm.pat];
}
// Now typecheck the blocks.
- auto result_ty = next_ty_var(scx);
+ auto result_ty = next_ty_var(fcx);
let vec[ast::block] blocks = [];
for (ast::arm arm in arms) {
- check_block(scx, arm.block);
+ check_block(fcx, arm.block);
- auto bty = block_ty(scx.fcx.ccx.tcx, arm.block);
+ auto bty = block_ty(fcx.ccx.tcx, arm.block);
// Failing alt arms don't need to have a matching type
- if (!ty::type_is_bot(scx.fcx.ccx.tcx, bty)) {
- result_ty = demand::simple(scx, arm.block.span,
+ if (!ty::type_is_bot(fcx.ccx.tcx, bty)) {
+ result_ty = demand::simple(fcx, arm.block.span,
result_ty, bty);
}
}
auto i = 0u;
for (ast::block bloc in blocks) {
- pushdown::pushdown_block(scx, result_ty, bloc);
+ pushdown::pushdown_block(fcx, result_ty, bloc);
}
- pushdown::pushdown_expr(scx, pattern_ty, expr);
+ pushdown::pushdown_expr(fcx, pattern_ty, expr);
- write::ty_only_fixup(scx, a.id, result_ty);
+ write::ty_only_fixup(fcx, a.id, result_ty);
}
case (ast::expr_block(?b, ?a)) {
- check_block(scx, b);
+ check_block(fcx, b);
alt (b.node.expr) {
case (some(?expr)) {
- auto typ = expr_ty(scx.fcx.ccx.tcx, expr);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = expr_ty(fcx.ccx.tcx, expr);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (none) {
- auto typ = ty::mk_nil(scx.fcx.ccx.tcx);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_nil(fcx.ccx.tcx);
+ write::ty_only_fixup(fcx, a.id, typ);
}
}
}
case (ast::expr_bind(?f, ?args, ?a)) {
// Call the generic checker.
- check_call_or_bind(scx, f, args);
+ check_call_or_bind(fcx, f, args);
// Pull the argument and return types out.
auto proto_1;
let vec[ty::arg] arg_tys_1 = [];
auto rt_1;
- auto fty = expr_ty(scx.fcx.ccx.tcx, f);
+ auto fty = expr_ty(fcx.ccx.tcx, f);
auto t_1;
- alt (struct(scx.fcx.ccx.tcx, fty)) {
+ alt (struct(fcx.ccx.tcx, fty)) {
case (ty::ty_fn(?proto, ?arg_tys, ?rt, ?cf)) {
proto_1 = proto;
rt_1 = rt;
@@ -2238,7 +2302,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
}
i += 1u;
}
- t_1 = ty::mk_fn(scx.fcx.ccx.tcx, proto_1, arg_tys_1, rt_1,
+ t_1 = ty::mk_fn(fcx.ccx.tcx, proto_1, arg_tys_1, rt_1,
cf);
}
case (_) {
@@ -2246,7 +2310,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
fail;
}
}
- write::ty_only_fixup(scx, a.id, t_1);
+ write::ty_only_fixup(fcx, a.id, t_1);
}
case (ast::expr_call(?f, ?args, ?a)) {
@@ -2254,14 +2318,14 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
need to restrict it to being an explicit expr_path if we're
inside a pure function, and need an environment mapping from
function name onto purity-designation */
- require_pure_call(scx.fcx.ccx, scx.fcx.purity, f, expr.span);
+ require_pure_call(fcx.ccx, fcx.purity, f, expr.span);
- check_call(scx, f, args);
+ check_call(fcx, f, args);
// Pull the return type out of the type of the function.
- auto rt_1 = ty::mk_nil(scx.fcx.ccx.tcx); // FIXME: typestate botch
- auto fty = expr_ty(scx.fcx.ccx.tcx, f);
- alt (struct(scx.fcx.ccx.tcx, fty)) {
+ auto rt_1 = ty::mk_nil(fcx.ccx.tcx); // FIXME: typestate botch
+ auto fty = ty::expr_ty(fcx.ccx.tcx, f);
+ alt (struct(fcx.ccx.tcx, fty)) {
case (ty::ty_fn(_,_,?rt,_)) { rt_1 = rt; }
case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
case (_) {
@@ -2270,14 +2334,14 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
}
}
- write::ty_only_fixup(scx, a.id, rt_1);
+ write::ty_only_fixup(fcx, a.id, rt_1);
}
case (ast::expr_self_method(?id, ?a)) {
- auto t = ty::mk_nil(scx.fcx.ccx.tcx);
+ auto t = ty::mk_nil(fcx.ccx.tcx);
let ty::t this_obj_ty;
- let option::t[obj_info] this_obj_info = get_obj_info(scx.fcx.ccx);
+ let option::t[obj_info] this_obj_info = get_obj_info(fcx.ccx);
alt (this_obj_info) {
// If we're inside a current object, grab its type.
@@ -2285,7 +2349,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
// FIXME: In the case of anonymous objects with methods
// containing self-calls, this lookup fails because
// obj_info.this_obj is not in the type cache
- this_obj_ty = ty::lookup_item_type(scx.fcx.ccx.tcx,
+ this_obj_ty = ty::lookup_item_type(fcx.ccx.tcx,
obj_info.this_obj)._1;
}
@@ -2293,11 +2357,11 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
}
// Grab this method's type out of the current object type.
- alt (struct(scx.fcx.ccx.tcx, this_obj_ty)) {
+ alt (struct(fcx.ccx.tcx, this_obj_ty)) {
case (ty::ty_obj(?methods)) {
for (ty::method method in methods) {
if (method.ident == id) {
- t = ty::method_ty_to_fn_ty(scx.fcx.ccx.tcx,
+ t = ty::method_ty_to_fn_ty(fcx.ccx.tcx,
method);
}
}
@@ -2305,86 +2369,86 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
case (_) { fail; }
}
- write::ty_only_fixup(scx, a.id, t);
+ write::ty_only_fixup(fcx, a.id, t);
- require_impure(scx.fcx.ccx.tcx.sess, scx.fcx.purity, expr.span);
+ require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
}
case (ast::expr_spawn(_, _, ?f, ?args, ?a)) {
- check_call(scx, f, args);
+ check_call(fcx, f, args);
- auto fty = expr_ty(scx.fcx.ccx.tcx, f);
- auto ret_ty = ty::ret_ty_of_fn_ty(scx.fcx.ccx.tcx, fty);
+ auto fty = expr_ty(fcx.ccx.tcx, f);
+ auto ret_ty = ty::ret_ty_of_fn_ty(fcx.ccx.tcx, fty);
- demand::simple(scx, f.span, ty::mk_nil(scx.fcx.ccx.tcx), ret_ty);
+ demand::simple(fcx, f.span, ty::mk_nil(fcx.ccx.tcx), ret_ty);
// FIXME: Other typechecks needed
- auto typ = ty::mk_task(scx.fcx.ccx.tcx);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_task(fcx.ccx.tcx);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (ast::expr_cast(?e, ?t, ?a)) {
- check_expr(scx, e);
- auto t_1 = ast_ty_to_ty_crate(scx.fcx.ccx, t);
+ check_expr(fcx, e);
+ auto t_1 = ast_ty_to_ty_crate(fcx.ccx, t);
// FIXME: there are more forms of cast to support, eventually.
- if (! (type_is_scalar(scx.fcx.ccx.tcx,
- expr_ty(scx.fcx.ccx.tcx, e)) &&
- type_is_scalar(scx.fcx.ccx.tcx, t_1))) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ if (! (type_is_scalar(fcx.ccx.tcx,
+ expr_ty(fcx.ccx.tcx, e)) &&
+ type_is_scalar(fcx.ccx.tcx, t_1))) {
+ fcx.ccx.tcx.sess.span_err(expr.span,
"non-scalar cast: " +
- ty_to_str(scx.fcx.ccx.tcx,
- expr_ty(scx.fcx.ccx.tcx, e)) +
- " as " + ty_to_str(scx.fcx.ccx.tcx, t_1));
+ ty_to_str(fcx.ccx.tcx,
+ expr_ty(fcx.ccx.tcx, e)) +
+ " as " + ty_to_str(fcx.ccx.tcx, t_1));
}
- write::ty_only_fixup(scx, a.id, t_1);
+ write::ty_only_fixup(fcx, a.id, t_1);
}
case (ast::expr_vec(?args, ?mut, ?a)) {
let ty::t t;
if (vec::len[@ast::expr](args) == 0u) {
- t = next_ty_var(scx);
+ t = next_ty_var(fcx);
} else {
- check_expr(scx, args.(0));
- t = expr_ty(scx.fcx.ccx.tcx, args.(0));
+ check_expr(fcx, args.(0));
+ t = expr_ty(fcx.ccx.tcx, args.(0));
}
for (@ast::expr e in args) {
- check_expr(scx, e);
- auto expr_t = expr_ty(scx.fcx.ccx.tcx, e);
- demand::simple(scx, expr.span, t, expr_t);
+ check_expr(fcx, e);
+ auto expr_t = expr_ty(fcx.ccx.tcx, e);
+ demand::simple(fcx, expr.span, t, expr_t);
}
- auto typ = ty::mk_vec(scx.fcx.ccx.tcx, rec(ty=t, mut=mut));
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_vec(fcx.ccx.tcx, rec(ty=t, mut=mut));
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (ast::expr_tup(?elts, ?a)) {
let vec[ty::mt] elts_mt = [];
for (ast::elt e in elts) {
- check_expr(scx, e.expr);
- auto ety = expr_ty(scx.fcx.ccx.tcx, e.expr);
+ check_expr(fcx, e.expr);
+ auto ety = expr_ty(fcx.ccx.tcx, e.expr);
elts_mt += [rec(ty=ety, mut=e.mut)];
}
- auto typ = ty::mk_tup(scx.fcx.ccx.tcx, elts_mt);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_tup(fcx.ccx.tcx, elts_mt);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (ast::expr_rec(?fields, ?base, ?a)) {
alt (base) {
case (none) { /* no-op */}
- case (some(?b_0)) { check_expr(scx, b_0); }
+ case (some(?b_0)) { check_expr(fcx, b_0); }
}
let vec[field] fields_t = [];
for (ast::field f in fields) {
- check_expr(scx, f.node.expr);
- auto expr_t = expr_ty(scx.fcx.ccx.tcx, f.node.expr);
+ check_expr(fcx, f.node.expr);
+ auto expr_t = expr_ty(fcx.ccx.tcx, f.node.expr);
auto expr_mt = rec(ty=expr_t, mut=f.node.mut);
vec::push[field](fields_t, rec(ident=f.node.ident,
@@ -2393,38 +2457,38 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
alt (base) {
case (none) {
- auto typ = ty::mk_rec(scx.fcx.ccx.tcx, fields_t);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_rec(fcx.ccx.tcx, fields_t);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (some(?bexpr)) {
- check_expr(scx, bexpr);
- auto bexpr_t = expr_ty(scx.fcx.ccx.tcx, bexpr);
+ check_expr(fcx, bexpr);
+ auto bexpr_t = expr_ty(fcx.ccx.tcx, bexpr);
let vec[field] base_fields = [];
- alt (struct(scx.fcx.ccx.tcx, bexpr_t)) {
+ alt (struct(fcx.ccx.tcx, bexpr_t)) {
case (ty::ty_rec(?flds)) { base_fields = flds; }
case (_) {
- scx.fcx.ccx.tcx.sess.span_err
+ fcx.ccx.tcx.sess.span_err
(expr.span,
"record update non-record base");
}
}
- write::ty_only_fixup(scx, a.id, bexpr_t);
+ write::ty_only_fixup(fcx, a.id, bexpr_t);
for (ty::field f in fields_t) {
auto found = false;
for (ty::field bf in base_fields) {
if (str::eq(f.ident, bf.ident)) {
- demand::simple(scx, expr.span, f.mt.ty,
+ demand::simple(fcx, expr.span, f.mt.ty,
bf.mt.ty);
found = true;
}
}
if (!found) {
- scx.fcx.ccx.tcx.sess.span_err
+ fcx.ccx.tcx.sess.span_err
(expr.span,
"unknown field in record update: "
+ f.ident);
@@ -2435,106 +2499,108 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
}
case (ast::expr_field(?base, ?field, ?a)) {
- check_expr(scx, base);
- auto base_t = expr_ty(scx.fcx.ccx.tcx, base);
- base_t = strip_boxes(scx.fcx.ccx.tcx, base_t);
- alt (struct(scx.fcx.ccx.tcx, base_t)) {
+ check_expr(fcx, base);
+ auto base_t = expr_ty(fcx.ccx.tcx, base);
+ base_t = strip_boxes(fcx.ccx.tcx, base_t);
+ base_t = ty::unify::resolve_all_vars(fcx.ccx.tcx,
+ fcx.var_bindings, base_t);
+ alt (struct(fcx.ccx.tcx, base_t)) {
case (ty::ty_tup(?args)) {
- let uint ix = ty::field_num(scx.fcx.ccx.tcx.sess,
+ let uint ix = ty::field_num(fcx.ccx.tcx.sess,
expr.span, field);
if (ix >= vec::len[ty::mt](args)) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"bad index on tuple");
}
- write::ty_only_fixup(scx, a.id, args.(ix).ty);
+ write::ty_only_fixup(fcx, a.id, args.(ix).ty);
}
case (ty::ty_rec(?fields)) {
- let uint ix = ty::field_idx(scx.fcx.ccx.tcx.sess,
+ let uint ix = ty::field_idx(fcx.ccx.tcx.sess,
expr.span, field, fields);
if (ix >= vec::len[ty::field](fields)) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"bad index on record");
}
- write::ty_only_fixup(scx, a.id, fields.(ix).mt.ty);
+ write::ty_only_fixup(fcx, a.id, fields.(ix).mt.ty);
}
case (ty::ty_obj(?methods)) {
- let uint ix = ty::method_idx(scx.fcx.ccx.tcx.sess,
+ let uint ix = ty::method_idx(fcx.ccx.tcx.sess,
expr.span, field, methods);
if (ix >= vec::len[ty::method](methods)) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"bad index on obj");
}
auto meth = methods.(ix);
- auto t = ty::mk_fn(scx.fcx.ccx.tcx, meth.proto,
+ auto t = ty::mk_fn(fcx.ccx.tcx, meth.proto,
meth.inputs, meth.output, meth.cf);
- write::ty_only_fixup(scx, a.id, t);
+ write::ty_only_fixup(fcx, a.id, t);
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_unimpl(expr.span,
+ fcx.ccx.tcx.sess.span_unimpl(expr.span,
"base type for expr_field in typeck::check_expr: " +
- ty_to_str(scx.fcx.ccx.tcx, base_t));
+ ty_to_str(fcx.ccx.tcx, base_t));
}
}
}
case (ast::expr_index(?base, ?idx, ?a)) {
- check_expr(scx, base);
- auto base_t = expr_ty(scx.fcx.ccx.tcx, base);
- base_t = strip_boxes(scx.fcx.ccx.tcx, base_t);
+ check_expr(fcx, base);
+ auto base_t = expr_ty(fcx.ccx.tcx, base);
+ base_t = strip_boxes(fcx.ccx.tcx, base_t);
- check_expr(scx, idx);
- auto idx_t = expr_ty(scx.fcx.ccx.tcx, idx);
- alt (struct(scx.fcx.ccx.tcx, base_t)) {
+ check_expr(fcx, idx);
+ auto idx_t = expr_ty(fcx.ccx.tcx, idx);
+ alt (struct(fcx.ccx.tcx, base_t)) {
case (ty::ty_vec(?mt)) {
- if (! type_is_integral(scx.fcx.ccx.tcx, idx_t)) {
- scx.fcx.ccx.tcx.sess.span_err
+ if (! type_is_integral(fcx.ccx.tcx, idx_t)) {
+ fcx.ccx.tcx.sess.span_err
(idx.span,
"non-integral type of vec index: "
- + ty_to_str(scx.fcx.ccx.tcx, idx_t));
+ + ty_to_str(fcx.ccx.tcx, idx_t));
}
- write::ty_only_fixup(scx, a.id, mt.ty);
+ write::ty_only_fixup(fcx, a.id, mt.ty);
}
case (ty::ty_str) {
- if (! type_is_integral(scx.fcx.ccx.tcx, idx_t)) {
- scx.fcx.ccx.tcx.sess.span_err
+ if (! type_is_integral(fcx.ccx.tcx, idx_t)) {
+ fcx.ccx.tcx.sess.span_err
(idx.span,
"non-integral type of str index: "
- + ty_to_str(scx.fcx.ccx.tcx, idx_t));
+ + ty_to_str(fcx.ccx.tcx, idx_t));
}
- auto typ = ty::mk_mach(scx.fcx.ccx.tcx, common::ty_u8);
- write::ty_only_fixup(scx, a.id, typ);
+ auto typ = ty::mk_mach(fcx.ccx.tcx, common::ty_u8);
+ write::ty_only_fixup(fcx, a.id, typ);
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_err
+ fcx.ccx.tcx.sess.span_err
(expr.span,
"vector-indexing bad type: "
- + ty_to_str(scx.fcx.ccx.tcx, base_t));
+ + ty_to_str(fcx.ccx.tcx, base_t));
}
}
}
case (ast::expr_port(?a)) {
- auto t = next_ty_var(scx);
- auto pt = ty::mk_port(scx.fcx.ccx.tcx, t);
- write::ty_only_fixup(scx, a.id, pt);
+ auto t = next_ty_var(fcx);
+ auto pt = ty::mk_port(fcx.ccx.tcx, t);
+ write::ty_only_fixup(fcx, a.id, pt);
}
case (ast::expr_chan(?x, ?a)) {
- check_expr(scx, x);
- auto port_t = expr_ty(scx.fcx.ccx.tcx, x);
- alt (struct(scx.fcx.ccx.tcx, port_t)) {
+ check_expr(fcx, x);
+ auto port_t = expr_ty(fcx.ccx.tcx, x);
+ alt (struct(fcx.ccx.tcx, port_t)) {
case (ty::ty_port(?subtype)) {
- auto ct = ty::mk_chan(scx.fcx.ccx.tcx, subtype);
- write::ty_only_fixup(scx, a.id, ct);
+ auto ct = ty::mk_chan(fcx.ccx.tcx, subtype);
+ write::ty_only_fixup(fcx, a.id, ct);
}
case (_) {
- scx.fcx.ccx.tcx.sess.span_err(expr.span,
+ fcx.ccx.tcx.sess.span_err(expr.span,
"bad port type: " +
- ty_to_str(scx.fcx.ccx.tcx, port_t));
+ ty_to_str(fcx.ccx.tcx, port_t));
}
}
}
@@ -2551,7 +2617,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
}
let ast::def_id di = obj_def_ids.ty;
- vec::push[obj_info](scx.fcx.ccx.obj_infos,
+ vec::push[obj_info](fcx.ccx.obj_infos,
rec(obj_fields=fields, this_obj=di));
// Typecheck 'with_obj', if it exists.
@@ -2562,16 +2628,16 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
// This had better have object type. TOOD: report an
// error if the user is trying to extend a non-object
// with_obj.
- check_expr(scx, e);
+ check_expr(fcx, e);
}
}
// Typecheck the methods.
for (@ast::method method in anon_obj.methods) {
- check_method(scx.fcx.ccx, method);
+ check_method(fcx.ccx, method);
}
- auto t = next_ty_var(scx);
+ auto t = next_ty_var(fcx);
// FIXME: These next three functions are largely ripped off from
@@ -2599,46 +2665,50 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
anon_obj.methods);
}
- auto methods = get_anon_obj_method_types(scx.fcx.ccx, anon_obj);
- auto ot = ty::mk_obj(scx.fcx.ccx.tcx,
+ auto methods = get_anon_obj_method_types(fcx.ccx, anon_obj);
+ auto ot = ty::mk_obj(fcx.ccx.tcx,
ty::sort_methods(methods));
- write::ty_only_fixup(scx, a.id, ot);
+ write::ty_only_fixup(fcx, a.id, ot);
// Now remove the info from the stack.
- vec::pop[obj_info](scx.fcx.ccx.obj_infos);
+ vec::pop[obj_info](fcx.ccx.obj_infos);
}
case (_) {
- scx.fcx.ccx.tcx.sess.unimpl("expr type in typeck::check_expr");
+ fcx.ccx.tcx.sess.unimpl("expr type in typeck::check_expr");
}
}
}
-fn next_ty_var(&@stmt_ctxt scx) -> ty::t {
- auto t = ty::mk_var(scx.fcx.ccx.tcx, scx.next_var_id);
- scx.next_var_id += 1;
- ret t;
+fn next_ty_var_id(@fn_ctxt fcx) -> int {
+ auto id = fcx.next_var_id;
+ fcx.next_var_id += 1;
+ ret id;
+}
+
+fn next_ty_var(&@fn_ctxt fcx) -> ty::t {
+ ret ty::mk_var(fcx.ccx.tcx, next_ty_var_id(fcx));
}
fn get_obj_info(&@crate_ctxt ccx) -> option::t[obj_info] {
ret vec::last[obj_info](ccx.obj_infos);
}
-fn check_decl_initializer(&@stmt_ctxt scx, &ast::def_id lid,
+fn check_decl_initializer(&@fn_ctxt fcx, &ast::def_id lid,
&ast::initializer init) {
- check_expr(scx, init.expr);
+ check_expr(fcx, init.expr);
- auto lty = ty::mk_local(scx.fcx.ccx.tcx, lid);
+ auto lty = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(lid));
alt (init.op) {
case (ast::init_assign) {
- pushdown::pushdown_expr(scx, lty, init.expr);
+ pushdown::pushdown_expr(fcx, lty, init.expr);
}
case (ast::init_move) {
- pushdown::pushdown_expr(scx, lty, init.expr);
+ pushdown::pushdown_expr(fcx, lty, init.expr);
}
case (ast::init_recv) {
- auto port_ty = ty::mk_port(scx.fcx.ccx.tcx, lty);
- pushdown::pushdown_expr(scx, port_ty, init.expr);
+ auto port_ty = ty::mk_port(fcx.ccx.tcx, lty);
+ pushdown::pushdown_expr(fcx, port_ty, init.expr);
}
}
}
@@ -2646,41 +2716,27 @@ fn check_decl_initializer(&@stmt_ctxt scx, &ast::def_id lid,
fn check_decl_local(&@fn_ctxt fcx, &@ast::decl decl) -> @ast::decl {
alt (decl.node) {
case (ast::decl_local(?local)) {
- auto t = ty::mk_nil(fcx.ccx.tcx);
-
- alt (local.ty) {
- case (none) {
- // Auto slot. Do nothing for now.
- }
-
- case (some(?ast_ty)) {
- auto local_ty = ast_ty_to_ty_crate(fcx.ccx, ast_ty);
- fcx.locals.insert(local.id, local_ty);
- t = local_ty;
- }
- }
-
auto a_res = local.ann;
- write::ty_only(fcx.ccx.tcx, a_res.id, t);
+ auto t = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(local.id));
+ write::ty_only_fixup(fcx, a_res.id, t);
auto initopt = local.init;
alt (local.init) {
case (some(?init)) {
- with_stmt_ctxt(fcx,
- bind check_decl_initializer(_, local.id, init));
+ check_decl_initializer(fcx, local.id, init);
}
case (_) { /* fall through */ }
}
- auto local_1 = @rec(init = initopt, ann = a_res with *local);
+ auto local_1 = @rec(init=initopt, ann=a_res with *local);
ret @rec(node=ast::decl_local(local_1) with *decl);
}
}
}
-fn check_and_pushdown_expr(&@stmt_ctxt scx, &@ast::expr expr) {
- check_expr(scx, expr);
- auto ety = expr_ty(scx.fcx.ccx.tcx, expr);
- pushdown::pushdown_expr(scx, ety, expr);
+fn check_and_pushdown_expr(&@fn_ctxt fcx, &@ast::expr expr) {
+ check_expr(fcx, expr);
+ auto ety = expr_ty(fcx.ccx.tcx, expr);
+ pushdown::pushdown_expr(fcx, ety, expr);
}
fn check_stmt(&@fn_ctxt fcx, &@ast::stmt stmt) {
@@ -2695,25 +2751,25 @@ fn check_stmt(&@fn_ctxt fcx, &@ast::stmt stmt) {
}
case (ast::stmt_expr(?expr,?a)) {
node_id = a.id;
- with_stmt_ctxt(fcx, bind check_and_pushdown_expr(_, expr));
+ check_and_pushdown_expr(fcx, expr);
}
}
write::nil_ty(fcx.ccx.tcx, node_id);
}
-fn check_block(&@stmt_ctxt scx, &ast::block block) {
- for (@ast::stmt s in block.node.stmts) { check_stmt(scx.fcx, s); }
+fn check_block(&@fn_ctxt fcx, &ast::block block) {
+ for (@ast::stmt s in block.node.stmts) { check_stmt(fcx, s); }
alt (block.node.expr) {
case (none) {
- write::nil_ty(scx.fcx.ccx.tcx, block.node.a.id);
+ write::nil_ty(fcx.ccx.tcx, block.node.a.id);
}
case (some(?e)) {
- check_expr(scx, e);
- auto ety = expr_ty(scx.fcx.ccx.tcx, e);
- pushdown::pushdown_expr(scx, ety, e);
- write::ty_only_fixup(scx, block.node.a.id, ety);
+ check_expr(fcx, e);
+ auto ety = expr_ty(fcx.ccx.tcx, e);
+ pushdown::pushdown_expr(fcx, ety, e);
+ write::ty_only_fixup(fcx, block.node.a.id, ety);
}
}
@@ -2722,46 +2778,36 @@ fn check_block(&@stmt_ctxt scx, &ast::block block) {
fn check_const(&@crate_ctxt ccx, &span sp, &@ast::expr e, &ast::ann ann) {
// FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression.
- auto rty = ann_to_type(ccx.tcx.node_types, ann);
- let @fn_ctxt fcx = @rec(ret_ty = rty,
- purity = ast::pure_fn,
- locals = @common::new_def_hash[ty::t](),
- ccx = ccx);
+ auto rty = ann_to_type(ccx.tcx, ann);
+ let vec[uint] fixups = [];
+ let @fn_ctxt fcx = @rec(ret_ty=rty,
+ purity=ast::pure_fn,
+ var_bindings=ty::unify::mk_var_bindings(),
+ locals=new_def_hash[int](),
+ local_names=new_def_hash[ast::ident](),
+ mutable next_var_id=0,
+ mutable fixups=fixups,
+ ccx=ccx);
- with_stmt_ctxt(fcx, bind check_and_pushdown_expr(_, e));
+ check_and_pushdown_expr(fcx, e);
}
fn check_fn(&@crate_ctxt ccx, &ast::fn_decl decl, ast::proto proto,
- &ast::block body) {
- auto local_ty_table = @common::new_def_hash[ty::t]();
+ &ast::block body, &ast::ann ann) {
+ auto gather_result = gather_locals(ccx, decl, body, ann);
- // FIXME: duplicate work: the item annotation already has the arg types
- // and return type translated to typeck::ty values. We don't need do to it
- // again here, we can extract them.
-
- alt (get_obj_info(ccx)) {
- case (option::some(?oinfo)) {
- for (ast::obj_field f in oinfo.obj_fields) {
- auto field_ty = ty::ann_to_type(ccx.tcx.node_types, f.ann);
- local_ty_table.insert(f.id, field_ty);
- }
- }
- case (option::none) { /* no fields */ }
- }
-
- // Store the type of each argument in the table.
- for (ast::arg arg in decl.inputs) {
- auto input_ty = ast_ty_to_ty_crate(ccx, arg.ty);
- local_ty_table.insert(arg.id, input_ty);
- }
-
- let @fn_ctxt fcx = @rec(ret_ty = ast_ty_to_ty_crate(ccx, decl.output),
- purity = decl.purity,
- locals = local_ty_table,
- ccx = ccx);
+ let vec[uint] fixups = [];
+ let @fn_ctxt fcx = @rec(ret_ty=ast_ty_to_ty_crate(ccx, decl.output),
+ purity=decl.purity,
+ var_bindings=gather_result.var_bindings,
+ locals=gather_result.locals,
+ local_names=gather_result.local_names,
+ mutable next_var_id=gather_result.next_var_id,
+ mutable fixups=fixups,
+ ccx=ccx);
// TODO: Make sure the type of the block agrees with the function type.
- with_stmt_ctxt(fcx, bind check_block(_, body));
+ check_block(fcx, body);
alt (decl.purity) {
case (ast::pure_fn) {
@@ -2775,12 +2821,12 @@ fn check_fn(&@crate_ctxt ccx, &ast::fn_decl decl, ast::proto proto,
case (_) {}
}
- writeback::resolve_local_types_in_block(fcx, body);
+ writeback::resolve_type_vars_in_block(fcx, body);
}
fn check_method(&@crate_ctxt ccx, &@ast::method method) {
- check_fn(ccx, method.node.meth.decl, method.node.meth.proto,
- method.node.meth.body);
+ auto m = method.node.meth;
+ check_fn(ccx, m.decl, m.proto, m.body, method.node.ann);
}
fn check_item(@crate_ctxt ccx, &@ast::item it) {
@@ -2788,8 +2834,8 @@ fn check_item(@crate_ctxt ccx, &@ast::item it) {
case (ast::item_const(_, _, ?e, _, ?a)) {
check_const(ccx, it.span, e, a);
}
- case (ast::item_fn(_, ?f, _, _, _)) {
- check_fn(ccx, f.decl, f.proto, f.body);
+ case (ast::item_fn(_, ?f, _, _, ?a)) {
+ check_fn(ccx, f.decl, f.proto, f.body, a);
}
case (ast::item_obj(_, ?ob, _, ?obj_def_ids, _)) {
// We're entering an object, so gather up the info we need.
diff --git a/src/comp/middle/walk.rs b/src/comp/middle/walk.rs
index 426f72d9bed..1ecafe1f02f 100644
--- a/src/comp/middle/walk.rs
+++ b/src/comp/middle/walk.rs
@@ -68,7 +68,7 @@ fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
case (ast::cdir_view_item(?vi)) {
walk_view_item(v, vi);
}
- case (ast::cdir_meta(_)) {}
+ case (ast::cdir_meta(_,_)) {}
case (ast::cdir_syntax(_)) {}
case (ast::cdir_auth(_, _)) {}
}
diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs
index be492d03a1a..2c7e65dcb22 100644
--- a/src/comp/pretty/pprust.rs
+++ b/src/comp/pretty/pprust.rs
@@ -945,7 +945,7 @@ fn print_decl(&ps s, &@ast::decl decl) {
case (mo_untyped) { /* no-op */ }
case (mo_typed(?tcx)) {
auto lty =
- ty::ann_to_type(tcx.node_types, loc.ann);
+ ty::ann_to_type(tcx, loc.ann);
word_space(s, ty::ty_to_str(tcx, lty));
}
case (mo_identified) { /* no-op */ }
diff --git a/src/lib/fs.rs b/src/lib/fs.rs
index d051d574fd2..92e90e62cbf 100644
--- a/src/lib/fs.rs
+++ b/src/lib/fs.rs
@@ -19,6 +19,20 @@ fn dirname(path p) -> path {
ret str::substr(p, 0u, i as uint);
}
+fn basename(path p) -> path {
+ let int i = str::rindex(p, os_fs::path_sep as u8);
+ if (i == -1) {
+ i = str::rindex(p, os_fs::alt_path_sep as u8);
+ if (i == -1) {
+ ret p;
+ }
+ }
+ auto len = str::byte_len(p);
+ if ((i+1) as uint >= len) { ret p; }
+
+ ret str::slice(p, i+1 as uint, len);
+}
+
// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
fn connect(path pre, path post) -> path {
auto len = str::byte_len(pre);
diff --git a/src/lib/smallintmap.rs b/src/lib/smallintmap.rs
index ca586eb6f05..49e9efa20f4 100644
--- a/src/lib/smallintmap.rs
+++ b/src/lib/smallintmap.rs
@@ -38,3 +38,7 @@ fn truncate[T](&smallintmap[T] m, uint len) {
m.v = vec::slice_mut[option::t[T]](m.v, 0u, len);
}
+fn max_key[T](&smallintmap[T] m) -> uint {
+ ret vec::len[option::t[T]](m.v);
+}
+
diff --git a/src/lib/std.rc b/src/lib/std.rc
index 3619ede40f8..b35b150528d 100644
--- a/src/lib/std.rc
+++ b/src/lib/std.rc
@@ -1,8 +1,10 @@
meta (name = "std",
- desc = "Rust standard library",
+ vers = "0.1",
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
- url = "http://rust-lang.org/src/std",
- ver = "0.0.1");
+ url = "http://rust-lang.org/src/std");
+
+meta (comment = "Rust standard library",
+ license = "BSD");
// Built-in types support modules.
diff --git a/src/lib/ufind.rs b/src/lib/ufind.rs
index 7dfa861c6ed..275efd813e4 100644
--- a/src/lib/ufind.rs
+++ b/src/lib/ufind.rs
@@ -20,6 +20,12 @@ fn make_set(&ufind ufnd) -> uint {
ret idx;
}
+/// Creates sets as necessary to ensure that least `n` sets are present in the
+/// data structure.
+fn grow(&ufind ufnd, uint n) {
+ while (set_count(ufnd) < n) { make_set(ufnd); }
+}
+
fn find(&ufind ufnd, uint n) -> uint {
alt (ufnd.nodes.(n)) {
case (none) { ret n; }
@@ -37,12 +43,17 @@ fn union(&ufind ufnd, uint m, uint n) {
}
}
+fn set_count(&ufind ufnd) -> uint {
+ ret vec::len[node](ufnd.nodes);
+}
+
// Removes all sets with IDs greater than or equal to the given value.
fn prune(&ufind ufnd, uint n) {
// TODO: Use "slice" once we get rid of "mutable?"
- while (n != 0u) {
+ auto len = vec::len[node](ufnd.nodes);
+ while (len != n) {
vec::pop[node](ufnd.nodes);
- n -= 1u;
+ len -= 1u;
}
}
diff --git a/src/lib/uint.rs b/src/lib/uint.rs
index 044eeff4fc4..c5aeb49d80b 100644
--- a/src/lib/uint.rs
+++ b/src/lib/uint.rs
@@ -12,6 +12,11 @@ fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }
+fn max(uint x, uint y) -> uint {
+ if (x > y) { ret x; }
+ ret y;
+}
+
iter range(uint lo, uint hi) -> uint {
auto lo_ = lo;
while (lo_ < hi) {
diff --git a/src/lib/vec.rs b/src/lib/vec.rs
index 374b55ed9be..2f82f330446 100644
--- a/src/lib/vec.rs
+++ b/src/lib/vec.rs
@@ -210,7 +210,7 @@ fn unshift[T](&mutable array[T] v, &T t) {
v = res;
}
-fn grow[T](&array[T] v, uint n, &T initval) {
+fn grow[T](&mutable array[T] v, uint n, &T initval) {
let uint i = n;
while (i > 0u) {
i -= 1u;
@@ -218,7 +218,7 @@ fn grow[T](&array[T] v, uint n, &T initval) {
}
}
-fn grow_set[T](&vec[mutable T] v, uint index, &T initval, &T val) {
+fn grow_set[T](&mutable vec[mutable T] v, uint index, &T initval, &T val) {
auto length = vec::len(v);
if (index >= length) {
grow(v, index - length + 1u, initval);
@@ -393,6 +393,12 @@ fn reversed[T](vec[T] v) -> vec[T] {
ret res;
}
+/// Truncates the vector to length `new_len`.
+/// FIXME: This relies on a typechecker bug (covariance vs. invariance).
+fn truncate[T](&mutable vec[mutable? T] v, uint new_len) {
+ v = slice[T](v, 0u, new_len);
+}
+
// Local Variables:
// mode: rust;
// fill-column: 78;
diff --git a/src/rt/main.ll.in b/src/rt/main.ll.in
new file mode 100644
index 00000000000..d956fb86817
--- /dev/null
+++ b/src/rt/main.ll.in
@@ -0,0 +1,24 @@
+%0 = type { i32, [1 x i32] }
+%1 = type { i32, i32 }
+%2 = type { i32, %3 }
+%3 = type { %tydesc*, %4, i1, {} }
+%4 = type { i1*, i1* }
+%5 = type { i32, i32, i32, i32, [0 x %6*] }
+%6 = type { i32, i32, i32, i32, [0 x i8] }
+
+
+@_rust_crate_map_toplevel = external global %0
+
+declare fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %5*);
+declare i32 @rust_start(i32, i32, i32, i32)
+
+%tydesc = type { %tydesc**, i32, i32, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*, i8*, i8)* }
+
+%task = type { i32, i32, i32, i32, i32, i32, i32, i32 }
+
+@_rust_fetch_this_object_hack = global i32 0
+
+define i32 @"MAIN"(i32, i32) {
+ %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %5*)* @_rust_main to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32))
+ ret i32 %3
+}
diff --git a/src/snapshots.txt b/src/snapshots.txt
index d64be8bffe1..5b41fb5a158 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,8 @@
+S 2011-06-07 a4ca75e
+ linux-i386 3de95184c59f5b0554df3da995090aaba26a190f
+ macos-i386 1537f2e01c746dc6ca2a9bfb4b2e81256bb01e96
+ winnt-i386 538765c5c4c31dfe8d6e998ef7503beb5cfa1525
+
S 2011-06-03 f29d046
linux-i386 76e4ee5b9148aae30ebfaabb12791bfee4fa8727
macos-i386 e146fa18f4b0f22fe4fd7fd104242837569d7702
diff --git a/src/test/compile-fail/ext-nonexistent.rs b/src/test/compile-fail/ext-nonexistent.rs
index e068bb3c4a4..9a7591ab7ce 100644
--- a/src/test/compile-fail/ext-nonexistent.rs
+++ b/src/test/compile-fail/ext-nonexistent.rs
@@ -1,5 +1,4 @@
-
// error-pattern:unknown syntax expander
fn main() {
#iamnotanextensionthatexists("");
-}
\ No newline at end of file
+}
diff --git a/src/test/compile-fail/vector-no-ann.rs b/src/test/compile-fail/vector-no-ann.rs
index 912fb0a388a..b492f103c20 100644
--- a/src/test/compile-fail/vector-no-ann.rs
+++ b/src/test/compile-fail/vector-no-ann.rs
@@ -1,6 +1,6 @@
// xfail-stage0
-// error-pattern:Ambiguous type
+// error-pattern:cannot determine a type
fn main() -> () {
auto foo = [];
}