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();
}