diff --git a/Makefile.in b/Makefile.in index fc3912cb396..b5ce96ef2be 100644 --- a/Makefile.in +++ b/Makefile.in @@ -55,6 +55,10 @@ rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) \ include config.mk +# We track all of the object files we might build so that we can find +# and include all of the .d files in one fell swoop. +ALL_OBJ_FILES := + MKFILE_DEPS := config.stamp $(call rwildcard,$(CFG_SRC_DIR)mk/,*) NON_HOST_TRIPLES = $(filter-out $(CFG_HOST_TRIPLE),$(CFG_TARGET_TRIPLES)) @@ -527,3 +531,8 @@ ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \ CFG_INFO := $(info cfg: including ctags rules) include $(CFG_SRC_DIR)mk/ctags.mk endif + +# Find all of the .d files and include them to add information about +# header file dependencies. +ALL_DEP_FILES := $(ALL_OBJ_FILES:%.o=%.d) +-include $(ALL_DEP_FILES) diff --git a/mk/platform.mk b/mk/platform.mk index 61526f1f559..6216f867bc8 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -210,18 +210,20 @@ ifeq ($(CFG_C_COMPILER),clang) CXX=clang++ endif ifeq ($(origin CPP),default) - CPP=cpp + CPP=clang -E endif CFG_GCCISH_CFLAGS += -Wall -Werror -fno-rtti -g CFG_GCCISH_LINK_FLAGS += -g - CFG_DEPEND_C = $(CFG_GCCISH_CROSS)$(CXX) $(CFG_GCCISH_CFLAGS) -MT "$(1)" \ - -MM $(2) + # These flags will cause the compiler to produce a .d file + # next to the .o file that lists header deps. + CFG_DEPEND_FLAGS = -MMD -MP -MT $(1) -MF $(1:%.o=%.d) define CFG_MAKE_CC CFG_COMPILE_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \ $$(CFG_GCCISH_CFLAGS) $$(CFG_CLANG_CFLAGS) \ $$(CFG_GCCISH_CFLAGS_$$(HOST_$(1))) \ $$(CFG_CLANG_CFLAGS_$$(HOST_$(1))) \ + $$(CFG_DEPEND_FLAGS) \ -c -o $$(1) $$(2) CFG_LINK_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \ $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \ @@ -241,12 +243,13 @@ ifeq ($(CFG_C_COMPILER),gcc) CXX=g++ endif ifeq ($(origin CPP),default) - CPP=cpp + CPP=gcc -E endif CFG_GCCISH_CFLAGS += -Wall -Werror -fno-rtti -g CFG_GCCISH_LINK_FLAGS += -g - CFG_DEPEND_C = $(CFG_GCCISH_CROSS)$(CXX) $(CFG_GCCISH_CFLAGS) -MT "$(1)" \ - -MM $(2) + # These flags will cause the compiler to produce a .d file + # next to the .o file that lists header deps. + CFG_DEPEND_FLAGS = -MMD -MP -MT $(1) -MF $(1:%.o=%.d) define CFG_MAKE_CC CFG_COMPILE_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \ @@ -254,6 +257,7 @@ ifeq ($(CFG_C_COMPILER),gcc) $$(CFG_GCCISH_CFLAGS_$$(HOST_$(1))) \ $$(CFG_GCC_CFLAGS) \ $$(CFG_GCC_CFLAGS_$$(HOST_$(1))) \ + $$(CFG_DEPEND_FLAGS) \ -c -o $$(1) $$(2) CFG_LINK_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \ $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \ @@ -272,7 +276,7 @@ endif # We're using llvm-mc as our assembler because it supports # .cfi pseudo-ops on mac define CFG_MAKE_ASSEMBLER - CFG_ASSEMBLE_$(1)=$$(CPP) $$(2) | \ + CFG_ASSEMBLE_$(1)=$$(CPP) $$(CFG_DEPEND_FLAGS) $$(2) | \ $$(LLVM_MC_$$(CFG_HOST_TRIPLE)) \ -assemble \ -filetype=obj \ diff --git a/mk/rt.mk b/mk/rt.mk index cd382267301..02fcdc0def6 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -79,17 +79,6 @@ RUNTIME_S_$(1) := rt/arch/$$(HOST_$(1))/_context.S \ rt/arch/$$(HOST_$(1))/ccall.S \ rt/arch/$$(HOST_$(1))/record_sp.S -RUNTIME_HDR_$(1) := $$(wildcard \ - rt/*.h \ - rt/bigint/*.h \ - rt/isaac/*.h \ - rt/msvc/*.h \ - rt/sync/*.h \ - rt/uthash/*.h \ - rt/util/*.h \ - rt/vg/*.h \ - rt/arch/$$(HOST_$(1))/*.h) - ifeq ($$(HOST_$(1)), i386) LIBUV_ARCH_$(1) := ia32 else @@ -116,25 +105,28 @@ RUNTIME_INCS_$(1) := -I $$(S)src/rt -I $$(S)src/rt/isaac -I $$(S)src/rt/uthash \ -I $$(S)src/libuv/include RUNTIME_OBJS_$(1) := $$(RUNTIME_CS_$(1):rt/%.cpp=rt/$(1)/%.o) \ $$(RUNTIME_S_$(1):rt/%.S=rt/$(1)/%.o) +ALL_OBJ_FILES += $$(RUNTIME_OBJS_$(1)) + +MORESTACK_OBJ_$(1) := rt/$(1)/arch/$$(HOST_$(1))/morestack.o +ALL_OBJ_FILES += $$(MORESTACK_OBJS_$(1)) + RUNTIME_LIBS_$(1) := $$(LIBUV_LIB_$(1)) -rt/$(1)/%.o: rt/%.cpp $$(RUNTIME_HDR_$(1)) $$(MKFILE_DEPS) +rt/$(1)/%.o: rt/%.cpp $$(MKFILE_DEPS) @$$(call E, compile: $$@) $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, $$(RUNTIME_INCS_$(1)) \ $$(SNAP_DEFINES)) $$< -rt/$(1)/%.o: rt/%.S $$(RUNTIME_HDR_$(1)) $$(MKFILE_DEPS) \ +rt/$(1)/%.o: rt/%.S $$(MKFILE_DEPS) \ $$(LLVM_CONFIG_$$(CFG_HOST_TRIPLE)) @$$(call E, compile: $$@) $$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<) -rt/$(1)/arch/$$(HOST_$(1))/libmorestack.a: \ - rt/$(1)/arch/$$(HOST_$(1))/morestack.o +rt/$(1)/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJ_$(1)) @$$(call E, link: $$@) $$(Q)ar rcs $$@ $$< rt/$(1)/$(CFG_RUNTIME): $$(RUNTIME_OBJS_$(1)) $$(MKFILE_DEPS) \ - $$(RUNTIME_HDR_$(1)) \ $$(RUNTIME_DEF_$(1)) \ $$(RUNTIME_LIBS_$(1)) @$$(call E, link: $$@) diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index fea09dae5af..622f7d4fa09 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -20,6 +20,7 @@ RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \ -iquote $$(LLVM_INCDIR_$(1)) \ -iquote $$(S)src/rustllvm/include RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=rustllvm/$(1)/%.o) +ALL_OBJ_FILES += $$(RUSTLLVM_OBJS_OBJS_$(1)) rustllvm/$(1)/$(CFG_RUSTLLVM): $$(RUSTLLVM_OBJS_OBJS_$(1)) \ $$(MKFILE_DEPS) $$(RUSTLLVM_DEF_$(1)) diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index ccaab58553f..730206e3574 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -129,7 +129,7 @@ impl extensions for dvec { #[doc = "Overwrite the current contents"] fn set(+w: [mut A]) { self.check_not_borrowed(); - self.data <- w; //FIXME check for recursive use + self.data <- w; //FIXME check for recursive use (#2607) } } @@ -177,25 +177,28 @@ impl extensions for dvec { } } - //FIXME-- - //#[doc = " - // Append all elements of an iterable. - // - // Failure will occur if the iterable's `each()` method - // attempts to access this vector. - //"] - //fn append_iter>(ts: I) { - // self.data.swap { |v| - // alt ts.size_hint() { - // none {} - // some(h) { vec::reserve(v, len(v) + h) } - // } - // - // for ts.each { |t| v = v + [t] }; - // - // v - // } - //} + #[doc = " + Append all elements of an iterable. + + Failure will occur if the iterable's `each()` method + attempts to access this vector. + "] + fn append_iter>(ts: I) { + self.swap { |v| + let mut v = alt ts.size_hint() { + none { v } + some(h) { + let len = v.len() + h; + let mut v <- v; + vec::reserve(v, len); + v + } + }; + + for ts.each { |t| v += [t] }; + v + } + } #[doc = " Gets a copy of the current contents. diff --git a/src/libcore/float.rs b/src/libcore/float.rs index d55c0e0c371..f50719408d0 100644 --- a/src/libcore/float.rs +++ b/src/libcore/float.rs @@ -109,7 +109,7 @@ fn to_str_common(num: float, digits: uint, exact: bool) -> str { // stack of digits let mut fractionalParts = []; - // FIXME: + // FIXME: (#2608) // This used to return right away without rounding, as "[-]num", // but given epsilon like in f64.rs, I don't see how the comparison // to epsilon did much when only used there. diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 0599fa77f90..1ee91495c57 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -137,7 +137,7 @@ impl num of num::num for T { } -// FIXME: Has alignment issues on windows and 32-bit linux +// FIXME: Has alignment issues on windows and 32-bit linux (#2609) #[test] #[ignore] fn test_from_str() { @@ -157,7 +157,7 @@ fn test_from_str() { assert from_str("x") == none; } -// FIXME: Has alignment issues on windows and 32-bit linux +// FIXME: Has alignment issues on windows and 32-bit linux (#2609) #[test] #[ignore] fn test_parse_buf() { diff --git a/src/libcore/iter-trait.rs b/src/libcore/iter-trait.rs index 8c23bb0ac54..e58aa05f079 100644 --- a/src/libcore/iter-trait.rs +++ b/src/libcore/iter-trait.rs @@ -25,7 +25,7 @@ impl extensions for IMPL_T { fn map_to_vec(op: fn(A) -> B) -> [B] { iter::map_to_vec(self, op) } fn to_vec() -> [A] { iter::to_vec(self) } - // FIXME--bug in resolve prevents this from working + // FIXME--bug in resolve prevents this from working (#2611) // fn flat_map_to_vec>(op: fn(A) -> IB) -> [B] { // iter::flat_map_to_vec(self, op) // } diff --git a/src/libcore/num.rs b/src/libcore/num.rs index eb5073c14b8..2d192b4aab1 100644 --- a/src/libcore/num.rs +++ b/src/libcore/num.rs @@ -1,8 +1,8 @@ #[doc="An interface for numbers."] iface num { - // FIXME: Cross-crate overloading doesn't work yet. - // FIXME: Interface inheritance. + // FIXME: Cross-crate overloading doesn't work yet. (#2615) + // FIXME: Interface inheritance. (#2616) fn add(&&other: self) -> self; fn sub(&&other: self) -> self; fn mul(&&other: self) -> self; diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 8ebb946af21..34c38321f47 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -36,7 +36,7 @@ export last_os_error; export set_exit_status; export walk_dir; -// FIXME: move these to str perhaps? +// FIXME: move these to str perhaps? #2620 export as_c_charp, fill_charp_buf; native mod rustrt { @@ -86,7 +86,7 @@ mod win32 { fn fill_utf16_buf_and_decode(f: fn(*mut u16, dword) -> dword) -> option { - // FIXME: remove these when export globs work properly. + // FIXME: remove these when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::consts::os::extra::*; @@ -167,7 +167,7 @@ mod global_env { sched: some({ mode: task::single_threaded, // FIXME: This would be a good place to use - // a very small native stack + // a very small native stack (#2621) native_stack_size: none }) with task::get_opts(builder) @@ -227,7 +227,7 @@ mod global_env { #[cfg(unix)] fn setenv(n: str, v: str) { - // FIXME: remove this when export globs work properly. + // FIXME: remove this when export globs work properly. #1238 import libc::funcs::posix01::unistd::setenv; str::as_c_str(n) {|nbuf| str::as_c_str(v) {|vbuf| @@ -239,7 +239,7 @@ mod global_env { #[cfg(windows)] fn setenv(n: str, v: str) { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import win32::*; as_utf16_p(n) {|nbuf| @@ -329,7 +329,7 @@ fn pipe() -> {in: c_int, out: c_int} { #[cfg(windows)] fn pipe() -> {in: c_int, out: c_int} { - // FIXME: remove this when export globs work properly. + // FIXME: remove this when export globs work properly. #1238 import libc::consts::os::extra::*; // Windows pipes work subtly differently than unix pipes, and their // inheritance has to be handled in a different way that I do not fully @@ -387,7 +387,7 @@ fn self_exe_path() -> option { #[cfg(target_os = "macos")] fn load_self() -> option unsafe { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::*; fill_charp_buf() {|buf, sz| _NSGetExecutablePath(buf, ptr::mut_addr_of(sz as u32)) @@ -397,7 +397,7 @@ fn self_exe_path() -> option { #[cfg(windows)] fn load_self() -> option unsafe { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::types::os::arch::extra::*; import libc::funcs::extra::kernel32::*; import win32::*; @@ -500,7 +500,7 @@ fn path_exists(p: path) -> bool { } // FIXME: under Windows, we should prepend the current drive letter to paths -// that start with a slash. +// that start with a slash. #2622 #[doc = " Convert a relative path to an absolute path @@ -526,11 +526,11 @@ fn make_dir(p: path, mode: c_int) -> bool { #[cfg(windows)] fn mkdir(p: path, _mode: c_int) -> bool unsafe { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::types::os::arch::extra::*; import libc::funcs::extra::kernel32::*; import win32::*; - // FIXME: turn mode into something useful? + // FIXME: turn mode into something useful? #2623 as_utf16_p(p) {|buf| CreateDirectoryW(buf, unsafe::reinterpret_cast(0)) != (0 as BOOL) @@ -588,7 +588,7 @@ fn remove_dir(p: path) -> bool { #[cfg(windows)] fn rmdir(p: path) -> bool { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; @@ -610,7 +610,7 @@ fn change_dir(p: path) -> bool { #[cfg(windows)] fn chdir(p: path) -> bool { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; @@ -633,7 +633,7 @@ fn copy_file(from: path, to: path) -> bool { #[cfg(windows)] fn do_copy_file(from: path, to: path) -> bool { - // FIXME: remove imports when export globs work properly. + // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 2e62b73063d..560e4282411 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -12,20 +12,20 @@ export split; export splitext; export normalize; -// FIXME: This type should probably be constrained +// FIXME: This type should probably be constrained (#2624) #[doc = "A path or fragment of a filesystem path"] type path = str; #[cfg(unix)] mod consts { #[doc = " - The primary path seperator character for the platform + The primary path separator character for the platform On all platforms it is '/' "] const path_sep: char = '/'; #[doc = " - The secondary path seperator character for the platform + The secondary path separator character for the platform On Unixes it is '/'. On Windows it is '\\'. "] @@ -98,7 +98,6 @@ fn basename(pp: path) -> path { ret split_dirname_basename(pp).basename; } -// FIXME: Need some typestate to avoid bounds check when len(pre) == 0 #[doc = " Connects to path segments diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 56534d0075c..d8905730dc2 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -287,7 +287,7 @@ fn program_output(prog: str, args: [str]) -> // Spawn two entire schedulers to read both stdout and sterr // in parallel so we don't deadlock while blocking on one // or the other. FIXME: Surely there's a much more clever way - // to do this. + // to do this. (#2625) let p = comm::port(); let ch = comm::chan(p); task::spawn_sched(task::single_threaded) {|| @@ -387,7 +387,7 @@ mod tests { import io::writer_util; // Regression test for memory leaks - #[ignore(cfg(windows))] // FIXME + #[ignore(cfg(windows))] // FIXME (#2626) fn test_leaks() { run::run_program("echo", []); run::start_program("echo", []); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index cf81dcd7157..8f68ff8d4da 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -594,7 +594,7 @@ Section: Comparing strings #[doc = "Bytewise string equality"] pure fn eq(&&a: str, &&b: str) -> bool { // FIXME: This should just be "a == b" but that calls into the shape code - // :( + // :( (#2627) let a_len = a.len(); let b_len = b.len(); if a_len != b_len { ret false; } diff --git a/src/libcore/task.rs b/src/libcore/task.rs index a4d6f63dbd6..5f31b5090f0 100644 --- a/src/libcore/task.rs +++ b/src/libcore/task.rs @@ -879,7 +879,7 @@ fn test_avoid_copying_the_body_spawn() { #[test] fn test_avoid_copying_the_body_spawn_listener() { avoid_copying_the_body {|f| - spawn_listener(fn~[move f](_po: comm::port) { + spawn_listener(fn~(move f, _po: comm::port) { f(); }); } @@ -899,7 +899,7 @@ fn test_avoid_copying_the_body_run() { fn test_avoid_copying_the_body_run_listener() { avoid_copying_the_body {|f| let buildr = builder(); - run_listener(buildr, fn~[move f](_po: comm::port) { + run_listener(buildr, fn~(move f, _po: comm::port) { f(); }); } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 7058f2202b9..1eab5b12ea0 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1249,8 +1249,7 @@ mod unsafe { #[inline(always)] unsafe fn form_slice(p: *T, len: uint, f: fn([T]/&) -> U) -> U { let pair = (p, len * sys::size_of::()); - // FIXME: should use &blk not &static here, but a snapshot is req'd - let v : *([T]/&static) = + let v : *([T]/&blk) = ::unsafe::reinterpret_cast(ptr::addr_of(pair)); f(*v) } @@ -1335,7 +1334,7 @@ impl extensions/& for [const A]/& { fn map_to_vec(op: fn(A) -> B) -> [B] { iter::map_to_vec(self, op) } fn to_vec() -> [A] { iter::to_vec(self) } - // FIXME--bug in resolve prevents this from working + // FIXME--bug in resolve prevents this from working (#2611) // fn flat_map_to_vec>(op: fn(A) -> IB) -> [B] { // iter::flat_map_to_vec(self, op) // } diff --git a/src/libstd/par.rs b/src/libstd/par.rs index d12a7e71a63..ffca5989857 100644 --- a/src/libstd/par.rs +++ b/src/libstd/par.rs @@ -39,7 +39,7 @@ fn map_slices( log(info, "spawning tasks"); while base < len { let end = uint::min(len, base + items_per_task); - // FIXME: why is the :: annotation required here? + // FIXME: why is the :: annotation required here? (#2617) vec::unpack_slice::(xs) {|p, _len| let f = f(); futures += [future::spawn() {|copy base| diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index 9fdf6c8550a..3ee92e5f074 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -25,8 +25,6 @@ for *at least* that period of time. "] fn delayed_send(iotask: iotask, msecs: uint, ch: comm::chan, val: T) { - // FIME: Looks like we don't need to spawn here - task::spawn() {|| unsafe { let timer_done_po = comm::port::<()>(); let timer_done_ch = comm::chan(timer_done_po); @@ -59,7 +57,6 @@ fn delayed_send(iotask: iotask, comm::send(ch, copy(val)); // uv_close for this timer has been processed comm::recv(timer_done_po); - } }; } @@ -106,7 +103,7 @@ fn recv_timeout(iotask: iotask, let timeout_po = comm::port::<()>(); let timeout_ch = comm::chan(timeout_po); delayed_send(iotask, msecs, timeout_ch, ()); - // FIXME: This could be written clearer + // FIXME: This could be written clearer (#2618) either::either( {|left_val| log(debug, #fmt("recv_time .. left_val %?", diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 98a3a8e7bcc..e11e673494c 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -9,6 +9,7 @@ import diagnostic::span_handler; enum path_elt { path_mod(ident), path_name(ident) } type path = [path_elt]; +/* FIXMEs that say "bad" are as per #2543 */ fn path_to_str_with_sep(p: path, sep: str) -> str { let strs = vec::map(p) {|e| alt e { @@ -291,6 +292,7 @@ fn node_id_to_str(map: map, id: node_id) -> str { #fmt["expr %s (id=%?)", pprust::expr_to_str(expr), id] } + // FIXMEs are as per #2410 some(node_export(_, path)) { #fmt["export %s (id=%?)", // FIXME: add more info here path_to_str(*path), id] diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index d4efdb4bb0d..ef3b0332f19 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -24,7 +24,7 @@ pure fn dummy_sp() -> span { ret mk_sp(0u, 0u); } pure fn path_name(p: @path) -> str { path_name_i(p.idents) } pure fn path_name_i(idents: [ident]) -> str { - // FIXME: Bad copies + // FIXME: Bad copies (#2543 -- same for everything else that says "bad") str::connect(idents.map({|i|*i}), "::") } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 9138fed69c8..5dfe40b7ee0 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -88,6 +88,7 @@ fn get_attr_name(attr: ast::attribute) -> ast::ident { get_meta_item_name(@attr.node.value) } +// All "bad" FIXME copies are as per #2543 fn get_meta_item_name(meta: @ast::meta_item) -> ast::ident { alt meta.node { ast::meta_word(n) { /* FIXME bad */ copy n } @@ -372,7 +373,7 @@ fn require_unique_names(diagnostic: span_handler, for metas.each {|meta| let name = get_meta_item_name(meta); - // FIXME: How do I silence the warnings? --pcw + // FIXME: How do I silence the warnings? --pcw (#2619) if map.contains_key(*name) { diagnostic.span_fatal(meta.span, #fmt["duplicate meta item `%s`", *name]); diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 23c6a3714c3..ae76cbafef7 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -59,7 +59,7 @@ fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg, let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(), res_rel_file(cx, sp, file), parse::parser::SOURCE_FILE); - ret parse::parser::parse_expr(p) + ret p.parse_expr(); } fn expand_include_str(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e0029b2a222..20452cd8724 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -16,8 +16,6 @@ import dvec::{dvec, extensions}; export file_type; export parser; -export parse_expr; -export parse_pat; // FIXME: #ast expects to find this here but it's actually defined in `parse` // Fixing this will be easier when we have export decls on individual items -- @@ -26,12 +24,6 @@ export parse_pat; import parse_from_source_str; export parse_from_source_str; -// TODO: remove these once we go around a snapshot cycle. -// These are here for the old way that #ast (qquote.rs) worked -fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() } -fn parse_pat(p: parser) -> @ast::pat { p.parse_pat() } - - enum restriction { UNRESTRICTED, RESTRICT_STMT_EXPR, @@ -1231,8 +1223,6 @@ class parser { fn parse_fn_expr(proto: proto) -> @expr { let lo = self.last_span.lo; - let cc_old = self.parse_old_skool_capture_clause(); - // if we want to allow fn expression argument types to be inferred in // the future, just have to change parse_arg to parse_fn_block_arg. let (decl, capture_clause) = @@ -1241,8 +1231,7 @@ class parser { let body = self.parse_block(); ret self.mk_expr(lo, body.span.hi, - expr_fn(proto, decl, body, - @(*capture_clause + cc_old))); + expr_fn(proto, decl, body, capture_clause)); } fn parse_fn_block_expr() -> @expr { @@ -1731,55 +1720,6 @@ class parser { } else { [] } } - // FIXME Remove after snapshot - fn parse_old_skool_capture_clause() -> [capture_item] { - fn expect_opt_trailing_semi(p: parser) { - if !p.eat(token::SEMI) { - if p.token != token::RBRACKET { - p.fatal("expecting ; or ]"); - } - } - } - - fn eat_ident_list(p: parser, is_move: bool) -> [capture_item] { - let mut res = []; - loop { - alt p.token { - token::IDENT(_, _) { - let id = p.get_id(); - let sp = mk_sp(p.span.lo, p.span.hi); - let ident = p.parse_ident(); - res += [@{id:id, is_move: is_move, name:ident, span:sp}]; - if !p.eat(token::COMMA) { - ret res; - } - } - - _ { ret res; } - } - }; - } - - let mut cap_items = []; - - if self.eat(token::LBRACKET) { - while !self.eat(token::RBRACKET) { - if self.eat_keyword("copy") { - cap_items += eat_ident_list(self, false); - expect_opt_trailing_semi(self); - } else if self.eat_keyword("move") { - cap_items += eat_ident_list(self, true); - expect_opt_trailing_semi(self); - } else { - let s: str = "expecting send, copy, or move clause"; - self.fatal(s); - } - } - } - - ret cap_items; - } - fn parse_fn_decl(purity: purity, parse_arg_fn: fn(parser) -> arg_or_capture_item) -> (fn_decl, capture_clause) { diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 57e0751f319..d46a47f0bd0 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -706,12 +706,6 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { let bcx = drop_ty(bcx, body, body_mt.ty); trans_free(bcx, v) } - - ty::ty_estr(ty::vstore_box) { - let v = PointerCast(bcx, v, type_of(ccx, t)); - trans_free(bcx, v) - } - ty::ty_opaque_box { let v = PointerCast(bcx, v, type_of(ccx, t)); let td = Load(bcx, GEPi(bcx, v, [0u, abi::box_field_tydesc])); @@ -725,8 +719,11 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { uniq::make_free_glue(bcx, v, t) } ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) | + ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) | ty::ty_vec(_) | ty::ty_str { - tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of(ccx, t)), t) + make_free_glue(bcx, v, + tvec::expand_boxed_vec_ty(bcx.tcx(), t)); + ret; } ty::ty_evec(_, _) { bcx.sess().unimpl("trans::base::make_free_glue on other evec"); @@ -794,6 +791,9 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) { free_ty(bcx, Load(bcx, v0), t) } + ty::ty_unboxed_vec(_) { + tvec::make_drop_glue_unboxed(bcx, v0, t) + } ty::ty_res(did, inner, substs) { trans_res_drop(bcx, v0, did, inner, substs.tps) } @@ -1634,11 +1634,38 @@ fn cast_shift_rhs(op: ast::binop, } } +fn fail_if_zero(cx: block, span: span, divmod: ast::binop, + rhs: ValueRef, rhs_t: ty::t) -> block { + let text = if divmod == ast::div { + "divide by zero" + } else { + "modulo zero" + }; + let is_zero = alt ty::get(rhs_t).struct { + ty::ty_int(t) { + let zero = C_integral(T_int_ty(cx.ccx(), t), 0u64, False); + ICmp(cx, lib::llvm::IntEQ, rhs, zero) + } + ty::ty_uint(t) { + let zero = C_integral(T_uint_ty(cx.ccx(), t), 0u64, False); + ICmp(cx, lib::llvm::IntEQ, rhs, zero) + } + _ { + cx.tcx().sess.bug("fail-if-zero on unexpected type: " + + ty_to_str(cx.ccx().tcx, rhs_t)); + } + }; + with_cond(cx, is_zero) {|bcx| + trans_fail(bcx, some(span), text) + } +} + // Important to get types for both lhs and rhs, because one might be _|_ // and the other not. -fn trans_eager_binop(cx: block, op: ast::binop, lhs: ValueRef, +fn trans_eager_binop(cx: block, span: span, op: ast::binop, lhs: ValueRef, lhs_t: ty::t, rhs: ValueRef, rhs_t: ty::t, dest: dest) -> block { + let mut cx = cx; let _icx = cx.insn_ctxt("trans_eager_binop"); if dest == ignore { ret cx; } let intype = { @@ -1667,16 +1694,30 @@ fn trans_eager_binop(cx: block, op: ast::binop, lhs: ValueRef, else { Mul(cx, lhs, rhs) } } ast::div { - if is_float { FDiv(cx, lhs, rhs) } - else if ty::type_is_signed(intype) { - SDiv(cx, lhs, rhs) - } else { UDiv(cx, lhs, rhs) } + if is_float { + FDiv(cx, lhs, rhs) + } else { + // Only zero-check integers; fp /0 is NaN + cx = fail_if_zero(cx, span, op, rhs, rhs_t); + if ty::type_is_signed(intype) { + SDiv(cx, lhs, rhs) + } else { + UDiv(cx, lhs, rhs) + } + } } ast::rem { - if is_float { FRem(cx, lhs, rhs) } - else if ty::type_is_signed(intype) { - SRem(cx, lhs, rhs) - } else { URem(cx, lhs, rhs) } + if is_float { + FRem(cx, lhs, rhs) + } else { + // Only zero-check integers; fp %0 is NaN + cx = fail_if_zero(cx, span, op, rhs, rhs_t); + if ty::type_is_signed(intype) { + SRem(cx, lhs, rhs) + } else { + URem(cx, lhs, rhs) + } + } } ast::bitor { Or(cx, lhs, rhs) } ast::bitand { And(cx, lhs, rhs) } @@ -1744,7 +1785,8 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop, _ { } } } - ret trans_eager_binop(bcx, op, Load(bcx, lhs_res.val), t, rhs_val, t, + ret trans_eager_binop(bcx, ex.span, + op, Load(bcx, lhs_res.val), t, rhs_val, t, save_in(lhs_res.val)); } @@ -1885,7 +1927,8 @@ fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr, // Remaining cases are eager: let lhs_res = trans_temp_expr(bcx, lhs); let rhs_res = trans_temp_expr(lhs_res.bcx, rhs); - ret trans_eager_binop(rhs_res.bcx, op, lhs_res.val, + ret trans_eager_binop(rhs_res.bcx, ex.span, + op, lhs_res.val, expr_ty(bcx, lhs), rhs_res.val, expr_ty(bcx, rhs), dest); } diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 0eaeb651368..c2f804d42cd 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -156,6 +156,7 @@ impl methods for reflector { } // FIXME: fetch constants out of intrinsic:: for the numbers. + // (#2594) ty::ty_fn(fty) { let pureval = alt fty.purity { ast::pure_fn { 0u } @@ -217,7 +218,7 @@ impl methods for reflector { // FIXME: visiting all the variants in turn is probably // not ideal. It'll work but will get costly on big enums. // Maybe let the visitor tell us if it wants to visit only - // a particular variant? + // a particular variant? (#2595) ty::ty_enum(did, substs) { let bcx = self.bcx; let tcx = bcx.ccx().tcx; diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index cfd779460eb..1d35d6548ae 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -277,8 +277,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] { } ty::ty_evec(mt, ty::vstore_uniq) | ty::ty_vec(mt) { - shape_of(ccx, - ty::mk_imm_uniq(ccx.tcx, ty::mk_unboxed_vec(ccx.tcx, mt))) + shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t)) } ty::ty_estr(ty::vstore_fixed(n)) { diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index 1861f690f9e..3a543b968b7 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -5,13 +5,35 @@ import back::abi; import base::{call_memmove, INIT, copy_val, load_if_immediate, get_tydesc, sub_block, do_spill_noroot, - dest, bcx_icx, non_gc_box_cast}; + dest, bcx_icx, non_gc_box_cast, + heap, heap_exchange, heap_shared}; import syntax::codemap::span; import shape::llsize_of; import build::*; import common::*; import util::ppaux::ty_to_str; +// Boxed vector types are in some sense currently a "shorthand" for a box +// containing an unboxed vector. This expands a boxed vector type into such an +// expanded type. It doesn't respect mutability, but that doesn't matter at +// this point. +fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { + let unit_ty = ty::sequence_element_type(tcx, t); + let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty); + alt ty::get(t).struct { + ty::ty_vec(_) | ty::ty_str | + ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) { + ty::mk_imm_uniq(tcx, unboxed_vec_ty) + } + ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) { + ty::mk_imm_box(tcx, unboxed_vec_ty) + } + _ { tcx.sess.bug("non boxed-vec type \ + in tvec::expand_boxed_vec_ty"); + } + } +} + fn get_fill(bcx: block, vptr: ValueRef) -> ValueRef { let _icx = bcx.insn_ctxt("tvec::get_fill"); Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill])) @@ -40,21 +62,25 @@ fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef { ret PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty); } -fn alloc_uniq_raw(bcx: block, unit_ty: ty::t, - fill: ValueRef, alloc: ValueRef) -> result { - let _icx = bcx.insn_ctxt("tvec::alloc_uniq_raw"); +fn alloc_raw(bcx: block, unit_ty: ty::t, + fill: ValueRef, alloc: ValueRef, heap: heap) -> result { + let _icx = bcx.insn_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty); let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type)); - let {box, body} = base::malloc_unique_dyn(bcx, vecbodyty, vecsize); + let {box, body} = base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize); Store(bcx, fill, GEPi(bcx, body, [0u, abi::vec_elt_fill])); Store(bcx, alloc, GEPi(bcx, body, [0u, abi::vec_elt_alloc])); ret {bcx: bcx, val: box}; } +fn alloc_uniq_raw(bcx: block, unit_ty: ty::t, + fill: ValueRef, alloc: ValueRef) -> result { + alloc_raw(bcx, unit_ty, fill, alloc, heap_exchange) +} -fn alloc_uniq(bcx: block, unit_ty: ty::t, elts: uint) -> result { +fn alloc_vec(bcx: block, unit_ty: ty::t, elts: uint, heap: heap) -> result { let _icx = bcx.insn_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); let llunitty = type_of::type_of(ccx, unit_ty); @@ -63,7 +89,7 @@ fn alloc_uniq(bcx: block, unit_ty: ty::t, elts: uint) -> result { let fill = Mul(bcx, C_uint(ccx, elts), unit_sz); let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) } else { fill }; - let {bcx: bcx, val: vptr} = alloc_uniq_raw(bcx, unit_ty, fill, alloc); + let {bcx: bcx, val: vptr} = alloc_raw(bcx, unit_ty, fill, alloc, heap); ret {bcx: bcx, val: vptr}; } @@ -79,20 +105,18 @@ fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result { call_memmove(bcx, new_data_ptr, data_ptr, fill); let bcx = if ty::type_needs_drop(bcx.tcx(), unit_ty) { - iter_vec(bcx, newptr, vec_ty, base::take_ty) + iter_vec_raw(bcx, new_data_ptr, vec_ty, fill, base::take_ty) } else { bcx }; ret rslt(bcx, newptr); } -fn make_free_glue(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> + +fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> block { - let _icx = bcx.insn_ctxt("tvec::make_free_glue"); + let _icx = bcx.insn_ctxt("tvec::make_drop_glue_unboxed"); let tcx = bcx.tcx(), unit_ty = ty::sequence_element_type(tcx, vec_ty); - base::with_cond(bcx, IsNotNull(bcx, vptr)) {|bcx| - let bcx = if ty::type_needs_drop(tcx, unit_ty) { - iter_vec(bcx, vptr, vec_ty, base::drop_ty) - } else { bcx }; - base::trans_unique_free(bcx, vptr) - } + if ty::type_needs_drop(tcx, unit_ty) { + iter_vec_unboxed(bcx, vptr, vec_ty, base::drop_ty) + } else { bcx } } fn trans_evec(bcx: block, args: [@ast::expr], @@ -141,13 +165,18 @@ fn trans_evec(bcx: block, args: [@ast::expr], {bcx: bcx, val: p, dataptr: vp} } ast::vstore_uniq { - let {bcx, val} = alloc_uniq(bcx, unit_ty, args.len()); + let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(), + heap_exchange); add_clean_free(bcx, val, true); let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val)); {bcx: bcx, val: val, dataptr: dataptr} } ast::vstore_box { - bcx.ccx().sess.unimpl("unhandled tvec::trans_evec"); + let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(), + heap_shared); + add_clean_free(bcx, val, true); + let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val)); + {bcx: bcx, val: val, dataptr: dataptr} } }; @@ -223,13 +252,11 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t) let len = Load(cx, GEPi(cx, v, [0u, abi::slice_elt_len])); (base, len) } - ty::vstore_uniq { + ty::vstore_uniq | ty::vstore_box { + #debug["get_base_and_len: %s", val_str(ccx.tn, v)]; let body = tvec::get_bodyptr(cx, v); (tvec::get_dataptr(cx, body), tvec::get_fill(cx, body)) } - ty::vstore_box { - cx.ccx().sess.unimpl("unhandled tvec::get_base_and_len"); - } } } @@ -388,7 +415,7 @@ type iter_vec_block = fn(block, ValueRef, ty::t) -> block; fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t, fill: ValueRef, f: iter_vec_block) -> block { - let _icx = bcx.insn_ctxt("tvec::iter_vec_uniq"); + let _icx = bcx.insn_ctxt("tvec::iter_vec_raw"); let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); @@ -422,11 +449,12 @@ fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t, iter_vec_raw(bcx, data_ptr, vec_ty, fill, f) } -fn iter_vec(bcx: block, vptr: ValueRef, vec_ty: ty::t, - f: iter_vec_block) -> block { - let _icx = bcx.insn_ctxt("tvec::iter_vec"); - let fill = get_fill(bcx, get_bodyptr(bcx, vptr)); - ret iter_vec_uniq(bcx, vptr, vec_ty, fill, f); +fn iter_vec_unboxed(bcx: block, body_ptr: ValueRef, vec_ty: ty::t, + f: iter_vec_block) -> block { + let _icx = bcx.insn_ctxt("tvec::iter_vec_unboxed"); + let fill = get_fill(bcx, body_ptr); + let dataptr = get_dataptr(bcx, body_ptr); + ret iter_vec_raw(bcx, dataptr, vec_ty, fill, f); } // diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index fb9112fc751..0d6ef8c6d12 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -76,10 +76,13 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { // this then, e.g. `option<{myfield: bool}>` would be a different // type than `option`. let t_norm = ty::normalize_ty(cx.tcx, t); - let llty = if t != t_norm { - type_of(cx, t_norm) + + let mut llty; + if t != t_norm { + llty = type_of(cx, t_norm); + cx.lltypes.insert(t, llty); } else { - alt ty::get(t).struct { + llty = alt ty::get(t).struct { ty::ty_nil | ty::ty_bot { T_nil() } ty::ty_bool { T_bool() } ty::ty_int(t) { T_int_ty(cx, t) } @@ -91,7 +94,9 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { } ty::ty_enum(did, _) { type_of_enum(cx, did, t) } ty::ty_estr(ty::vstore_box) { T_box_ptr(T_box(cx, T_i8())) } - ty::ty_evec(mt, ty::vstore_box) | + ty::ty_evec(mt, ty::vstore_box) { + T_box_ptr(T_box(cx, T_vec(cx, type_of(cx, mt.ty)))) + } ty::ty_box(mt) { T_box_ptr(T_box(cx, type_of(cx, mt.ty))) } ty::ty_opaque_box { T_box_ptr(T_box(cx, T_i8())) } ty::ty_uniq(mt) { T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))) } @@ -147,20 +152,12 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { } ty::ty_opaque_closure_ptr(_) { T_opaque_box_ptr(cx) } ty::ty_constr(subt,_) { type_of(cx, subt) } - ty::ty_class(did, ts) { - // only instance vars are record fields at runtime - let fields = lookup_class_fields(cx.tcx, did); - let tys = vec::map(fields) {|f| - let t = ty::lookup_field_type(cx.tcx, did, f.id, ts); - type_of(cx, t) - }; - if ty::ty_dtor(cx.tcx, did) == none { - T_struct(tys) - } - else { - // resource type - T_struct([T_i8(), T_struct(tys)]) - } + ty::ty_class(*) { + // Only create the named struct, but don't fill it in. We fill it + // in *after* placing it into the type cache. This prevents + // infinite recursion with recursive class types. + + common::T_named_struct(llvm_type_name(cx, t)) } ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); } ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); } @@ -168,9 +165,33 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { ty::ty_var_integral(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral"); } + }; + + cx.lltypes.insert(t, llty); + + // If this was a class, fill in the type now. + alt ty::get(t).struct { + ty::ty_class(did, ts) { + // Only instance vars are record fields at runtime. + let fields = lookup_class_fields(cx.tcx, did); + let mut tys = vec::map(fields) {|f| + let t = ty::lookup_field_type(cx.tcx, did, f.id, ts); + type_of(cx, t) + }; + + if ty::ty_dtor(cx.tcx, did) != none { + // resource type + tys = [T_i8(), T_struct(tys)]; + } + + common::set_struct_body(llty, tys); + } + _ { + // Nothing more to do. + } } }; - cx.lltypes.insert(t, llty); + ret llty; } @@ -212,6 +233,9 @@ fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> str { ty::ty_enum(did, substs) { ("enum", did, substs.tps) } + ty::ty_class(did, substs) { + ("class", did, substs.tps) + } }; ret #fmt( "%s %s[#%d]", diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 02e683f4cbc..421bbf38e14 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -1112,7 +1112,7 @@ fn type_is_str(ty: t) -> bool { fn sequence_element_type(cx: ctxt, ty: t) -> t { alt get(ty).struct { ty_str | ty_estr(_) { ret mk_mach_uint(cx, ast::ty_u8); } - ty_vec(mt) | ty_evec(mt, _) { ret mt.ty; } + ty_vec(mt) | ty_evec(mt, _) | ty_unboxed_vec(mt) { ret mt.ty; } _ { cx.sess.bug("sequence_element_type called on non-sequence value"); } } } @@ -1134,7 +1134,8 @@ pure fn type_is_box(ty: t) -> bool { pure fn type_is_boxed(ty: t) -> bool { alt get(ty).struct { - ty_box(_) | ty_opaque_box { true } + ty_box(_) | ty_opaque_box | + ty_evec(_, vstore_box) | ty_estr(vstore_box) { true } _ { false } } } @@ -1212,6 +1213,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { ty_estr(vstore_fixed(_)) | ty_estr(vstore_slice(_)) | ty_evec(_, vstore_slice(_)) { false } ty_evec(mt, vstore_fixed(_)) { type_needs_drop(cx, mt.ty) } + ty_unboxed_vec(mt) { type_needs_drop(cx, mt.ty) } ty_rec(flds) { for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } } accum @@ -2693,9 +2695,11 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] { let result = if ast::local_crate != id.crate { @csearch::get_enum_variants(cx, id) } else { - // FIXME: Now that the variants are run through the type checker (to - // check the disr_expr if it exists), this code should likely be - // moved there to avoid having to call eval_const_expr twice. + /* + Although both this code and check_enum_variants in typeck/check + call eval_const_expr, it should never get called twice for the same + expr, since check_enum_variants also updates the enum_var_cache + */ alt cx.items.get(id.node) { ast_map::node_item(@{node: ast::item_enum(variants, _, _), _}, _) { let mut disr_val = -1; @@ -3032,9 +3036,16 @@ fn normalize_ty(cx: ctxt, t: t) -> t { alt r.self_r { some(_) { // This enum has a self region. Get rid of it - mk_enum(cx, did, {self_r: none, - self_ty: none, - tps: r.tps}) + mk_enum(cx, did, {self_r: none, self_ty: none, tps: r.tps}) + } + none { t } + } + } + ty_class(did, r) { + alt r.self_r { + some(_) { + // Ditto. + mk_class(cx, did, {self_r: none, self_ty: none, tps: r.tps}) } none { t } } diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 1957318095b..c142b22452f 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1201,14 +1201,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, none { alt sty { ty::ty_enum(*) { - tcx.sess.span_fatal( + tcx.sess.span_err( expr.span, "can only dereference enums \ with a single variant which has a \ single argument"); } _ { - tcx.sess.span_fatal( + tcx.sess.span_err( expr.span, #fmt["type %s cannot be dereferenced", fcx.infcx.ty_to_str(oper_t)]); @@ -1893,6 +1893,7 @@ fn check_enum_variants(ccx: @crate_ctxt, let fcx = blank_fn_ctxt(ccx, rty); let mut disr_vals: [int] = []; let mut disr_val = 0; + let mut variants = []; for vs.each {|v| alt v.node.disr_expr { some(e) { @@ -1921,9 +1922,19 @@ fn check_enum_variants(ccx: @crate_ctxt, "discriminator value already exists."); } disr_vals += [disr_val]; + let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id); + let arg_tys = if v.node.args.len() > 0u { + ty::ty_fn_args(ctor_ty).map {|a| a.ty } + } else { [] }; + variants += [@{args: arg_tys, ctor_ty: ctor_ty, + name: v.node.name, id: local_def(v.node.id), + disr_val: disr_val}]; disr_val += 1; } + // cache so that ty::enum_variants won't repeat this work + ccx.tcx.enum_var_cache.insert(local_def(id), @variants); + // Check that it is possible to represent this enum: let mut outer = true, did = local_def(id); if ty::type_structurally_contains(ccx.tcx, rty, {|sty| diff --git a/src/rustdoc/astsrv.rs b/src/rustdoc/astsrv.rs index 235a1c18ca5..7d8b5e1f7d5 100644 --- a/src/rustdoc/astsrv.rs +++ b/src/rustdoc/astsrv.rs @@ -97,7 +97,7 @@ fn exec( ) -> T { let po = comm::port(); let ch = comm::chan(po); - let msg = handle_request(fn~[move f](ctxt: ctxt) { + let msg = handle_request(fn~(move f, ctxt: ctxt) { comm::send(ch, f(ctxt)) }); comm::send(srv.ch, msg); diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs index c1532eba4f8..7f4c8aa6988 100644 --- a/src/rustdoc/doc.rs +++ b/src/rustdoc/doc.rs @@ -22,7 +22,7 @@ type section = { // FIXME: We currently give topmod the name of the crate. There would // probably be fewer special cases if the crate had its own name and -// topmod's name was the empty string. +// topmod's name was the empty string. (#2596) type cratedoc = { topmod: moddoc, }; diff --git a/src/rustdoc/reexport_pass.rs b/src/rustdoc/reexport_pass.rs index f9448bff082..ea58eea76cb 100644 --- a/src/rustdoc/reexport_pass.rs +++ b/src/rustdoc/reexport_pass.rs @@ -122,7 +122,7 @@ fn build_reexport_def_map( def_map: ast_util::new_def_hash() }; - // FIXME: Do a parallel fold + // FIXME: Do a parallel fold (#2597) let fold = fold::fold({ fold_mod: fold_mod, fold_nmod: fold_nmod diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 83af47e8d50..4c6cd7d9ae6 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -122,7 +122,7 @@ fn make_sequence_processor(sz: uint, from_parent: comm::port<[u8]>, to_parent: c fn main(args: [str]) { let rdr = if os::getenv("RUST_BENCH").is_some() { // FIXME: Using this compile-time env variable is a crummy way to - // get to this massive data set, but #include_bin chokes on it + // get to this massive data set, but #include_bin chokes on it (#2598) let path = path::connect( #env("CFG_SRC_DIR"), "src/test/bench/shootout-k-nucleotide.data" diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 082b93d2e0c..dee7ef70d81 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -59,14 +59,12 @@ fn solve_grid(g: grid_t) { drop_colors(g, avail, row, col); // find first remaining color that is available - let mut i = 1 as uint; - while i < (10 as uint) { /* FIXME llvm ctlhd */ + for uint::range(1u, 10u) {|i| if bitv::get(avail, i) { g[row][col] = i as u8; ret true; } - i += 1 as uint; /* else */ - } + }; } g[row][col] = 0u8; ret false; @@ -131,6 +129,7 @@ fn write_grid(f: io::writer, g: grid_t) { fn main(args: [str]) { let grid = if vec::len(args) == 1u { // FIXME create sudoku inline since nested vec consts dont work yet + // (#571) let g = vec::from_fn(10u, {|_i| vec::to_mut(vec::from_elem(10u, 0 as u8)) }); diff --git a/src/test/bench/task-perf-word-count-generic.rs b/src/test/bench/task-perf-word-count-generic.rs index 729dec9997e..71023b8207b 100644 --- a/src/test/bench/task-perf-word-count-generic.rs +++ b/src/test/bench/task-perf-word-count-generic.rs @@ -77,8 +77,7 @@ mod map_reduce { type putter = fn(K, V); - // FIXME: the first K1 parameter should probably be a -, but that - // doesn't parse at the moment. + // FIXME: the first K1 parameter should probably be a - (#2599) type mapper = fn~(K1, putter); type getter = fn() -> option; diff --git a/src/test/run-fail/divide-by-zero.rs b/src/test/run-fail/divide-by-zero.rs new file mode 100644 index 00000000000..8eb0d427ca4 --- /dev/null +++ b/src/test/run-fail/divide-by-zero.rs @@ -0,0 +1,5 @@ +// error-pattern:divide by zero +fn main() { + let y = 0; + let z = 1 / y; +} diff --git a/src/test/run-fail/mod-zero.rs b/src/test/run-fail/mod-zero.rs new file mode 100644 index 00000000000..7a10ed05aaf --- /dev/null +++ b/src/test/run-fail/mod-zero.rs @@ -0,0 +1,5 @@ +// error-pattern:modulo zero +fn main() { + let y = 0; + let z = 1 % y; +} diff --git a/src/test/run-pass/autobind.rs b/src/test/run-pass/autobind.rs index dc875c3133d..3269af16afa 100644 --- a/src/test/run-pass/autobind.rs +++ b/src/test/run-pass/autobind.rs @@ -1,8 +1,4 @@ -// FIXME: Autobind doesn't work for bare functions currently -// because it would have to convert them to shared closures -// xfail-test - -fn f(x: [T]) -> T { ret x[0]; } +fn f(x: [T]) -> T { ret x[0]; } fn g(act: fn([int]) -> int) -> int { ret act([1, 2, 3]); } diff --git a/src/test/run-pass/basic.rs b/src/test/run-pass/basic.rs index 8ef7d50b959..2b0dab5d1a8 100644 --- a/src/test/run-pass/basic.rs +++ b/src/test/run-pass/basic.rs @@ -39,7 +39,7 @@ fn main() { log(debug, x); n = recv(p); n = recv(p); - // FIXME: use signal-channel for this. + // FIXME: use signal-channel for this. (#2600) #debug("children finished, root finishing"); } diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index 87b71788e28..047e0d41e23 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -60,7 +60,7 @@ fn test_box() { } fn test_port() { - // FIXME: Re-enable this once we can compare resources. + // FIXME: Re-enable this once we can compare resources. (#2601) /* let p1 = comm::port::(); let p2 = comm::port::(); diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index 0df31019a4a..d4cb3822542 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -1,5 +1,3 @@ -// xfail-fast -// (Not sure why, though -- FIXME (tjc) import to_str::*; import to_str::to_str; diff --git a/src/test/run-pass/classes-self-referential.rs b/src/test/run-pass/classes-self-referential.rs new file mode 100644 index 00000000000..7add8fec1b1 --- /dev/null +++ b/src/test/run-pass/classes-self-referential.rs @@ -0,0 +1,10 @@ +class kitten { + let cat: option; + new(cat: option) { + self.cat = cat; + } +} + +type cat = @kitten; + +fn main() {} diff --git a/src/test/run-pass/issue-1895.rs b/src/test/run-pass/issue-1895.rs index 3be9fa65b83..21938a9594a 100644 --- a/src/test/run-pass/issue-1895.rs +++ b/src/test/run-pass/issue-1895.rs @@ -1,6 +1,6 @@ fn main() { let x = 1; - let y = fn@[move x]() -> int { + let y = fn@(move x) -> int { x }(); } diff --git a/src/test/run-pass/issue-2611.rs b/src/test/run-pass/issue-2611.rs new file mode 100644 index 00000000000..ebd77749354 --- /dev/null +++ b/src/test/run-pass/issue-2611.rs @@ -0,0 +1,11 @@ +// xfail-test +import iter; +import iter::base_iter; + +impl Q for base_iter { + fn flat_map_to_vec>(op: fn(B) -> IB) -> [B] { + iter::flat_map_to_vec(self, op) + } +} + +fn main() {} \ No newline at end of file diff --git a/src/test/run-pass/issue-506.rs b/src/test/run-pass/issue-506.rs index b1feb5df68e..6fc5b5ea6eb 100644 --- a/src/test/run-pass/issue-506.rs +++ b/src/test/run-pass/issue-506.rs @@ -2,6 +2,7 @@ // FIXME: This test is no longer testing what it was intended to. It should // be testing spawning of a native function, but is actually testing // spawning some other function, then executing a native function. +// #2602 /* A reduced test case for Issue #506, provided by Rob Arnold. diff --git a/src/test/run-pass/native-lib-path.rs b/src/test/run-pass/native-lib-path.rs index 2f9d416a223..288be15c385 100644 --- a/src/test/run-pass/native-lib-path.rs +++ b/src/test/run-pass/native-lib-path.rs @@ -1,4 +1,4 @@ -// xfail-test FIXME I don't know how to test this +// xfail-test FIXME I don't know how to test this (#2604) // compile-flags:-L. // The -L flag is also used for linking native libraries diff --git a/src/test/run-pass/pred-not-bool.rs b/src/test/run-pass/pred-not-bool.rs index 6d1ad3a72ad..58281b40b5e 100644 --- a/src/test/run-pass/pred-not-bool.rs +++ b/src/test/run-pass/pred-not-bool.rs @@ -1,12 +1,6 @@ -// FIXME should be in run-pass - -// -*- rust -*- - -// error-pattern: Non-boolean return type - // this checks that a pred with a non-bool return // type is rejected, even if the pred is never used -pure fn bad(a: int) -> int { ret 37; } +pure fn bad(a: int) -> int { ret 37; } //! ERROR Non-boolean return type fn main() { } diff --git a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs index ce4d5dcf21a..6272b20163c 100644 --- a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs +++ b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs @@ -15,7 +15,7 @@ fn test05() { log(error, *three + n); // will copy x into the closure assert(*three == 3); }; - task::spawn(fn~[move fn_to_send]() { + task::spawn(fn~(move fn_to_send) { test05_start(fn_to_send); }); } diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index b79134505c9..40936ce3a06 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -53,6 +53,7 @@ fn test_tag() { send(ch, tag2(10)); send(ch, tag3(10, 11u8, 'A')); // FIXME: Do port semantics really guarantee these happen in order? + // (#2605) let mut t1: t; t1 = recv(po); assert (t1 == tag1); diff --git a/src/test/run-pass/task-compare.rs b/src/test/run-pass/task-compare.rs index be7f658eb1a..9a8b5661e87 100644 --- a/src/test/run-pass/task-compare.rs +++ b/src/test/run-pass/task-compare.rs @@ -2,7 +2,7 @@ A test case for issue #577, which also exposes #588 */ -// FIXME: This won't work until we can compare resources +// FIXME: This won't work until we can compare resources (#2601) // xfail-test use std; diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs index 1758faaac50..cf98be6effb 100644 --- a/src/test/run-pass/task-spawn-move-and-copy.rs +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -8,7 +8,7 @@ fn main() { let y = ~2; let y_in_parent = ptr::addr_of(*y) as uint; - task::spawn(fn~[copy ch, y; move x]() { + task::spawn(fn~(copy ch, copy y, move x) { let x_in_child = ptr::addr_of(*x) as uint; comm::send(ch, x_in_child); diff --git a/src/test/run-pass/unused-move-capture.rs b/src/test/run-pass/unused-move-capture.rs index d6fa0e533d5..8e81e5277bf 100644 --- a/src/test/run-pass/unused-move-capture.rs +++ b/src/test/run-pass/unused-move-capture.rs @@ -1,5 +1,5 @@ fn main() { let x = ~1; - let lam_move = fn@[move x]() { }; + let lam_move = fn@(move x) { }; lam_move(); }