]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis
authorbors <bors@rust-lang.org>
Thu, 31 Jul 2014 16:41:36 +0000 (16:41 +0000)
committerbors <bors@rust-lang.org>
Thu, 31 Jul 2014 16:41:36 +0000 (16:41 +0000)
Note: This PR is motivated by an attempt to write an custom syntax extension that tried to use `syntax::fold`, and that could only do so by fixing bugs in it and copying out private functions.

---

Refactored `syntax::fold`

Prior to this, the code there had a few issues:

- Default implementations inconsistenly either had the prefix `noop_` or
  not.
- Some default methods where implemented in terms of a public noop function
  for user code to call, others where implemented directly on the trait
  and did not allow users of the trait to reuse the code.
- Some of the default implementations where private, and thus not reusable
  for other implementors.
- There where some bugs where default implemntations called other default
  implementations directly, rather than to the underlying Folder, with the
  result of some ast nodes never being visted even if the user implemented that
  method. (For example, the current Folder never folded struct fields)

This commit solves this situation somewhat radically by making __all__
`fold_...` functions in the module into Folder methods, and implementing
them all in terms of public `noop_...` functions for other implementors to
call out to.

Some public functions had to be renamed to fit the new system, so this is a
breaking change.

---

Also added a few trait implementations to `ast` types

135 files changed:
configure
mk/platform.mk
mk/rt.mk
src/compiletest/header.rs
src/compiletest/runtest.rs
src/compiletest/util.rs
src/doc/guide.md
src/doc/index.md
src/doc/intro.md
src/doc/rust.md
src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang
src/etc/local_stage0.sh
src/etc/mklldeps.py
src/liballoc/arc.rs
src/libcollections/dlist.rs
src/libcollections/slice.rs
src/libcollections/string.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libfmt_macros/lib.rs
src/libgetopts/lib.rs
src/libgreen/sched.rs
src/libgreen/stack.rs
src/libgreen/task.rs
src/liblibc/lib.rs
src/liblog/directive.rs
src/libnative/io/c_unix.rs
src/libnative/io/mod.rs
src/libnative/io/net.rs
src/libnative/io/process.rs
src/libnative/task.rs
src/libnum/bigint.rs
src/libnum/integer.rs
src/libnum/rational.rs
src/librustc/back/link.rs
src/librustc/driver/config.rs
src/librustc/front/feature_gate.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/mod.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_match.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/closure.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/context.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/foreign.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/inline.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/writeback.rs
src/librustc/util/io.rs [new file with mode: 0644]
src/librustc_back/archive.rs
src/librustc_back/arm.rs
src/librustc_back/mips.rs
src/librustc_back/mipsel.rs
src/librustc_back/rpath.rs
src/librustc_back/x86.rs
src/librustc_back/x86_64.rs
src/librustdoc/flock.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.css
src/librustdoc/html/static/main.js
src/librustrt/args.rs
src/librustrt/bookkeeping.rs
src/librustrt/libunwind.rs
src/librustrt/local.rs
src/librustrt/mutex.rs
src/librustrt/stack.rs
src/librustrt/task.rs
src/librustrt/thread_local_storage.rs
src/librustuv/uvll.rs
src/libserialize/ebml.rs
src/libserialize/json.rs
src/libstd/ascii.rs
src/libstd/bitflags.rs
src/libstd/collections/hashmap.rs
src/libstd/dynamic_lib.rs
src/libstd/io/fs.rs
src/libstd/io/mem.rs
src/libstd/io/mod.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/rt/backtrace.rs
src/libstd/rtdeps.rs
src/libsyntax/abi.rs
src/libsyntax/ast.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/liburl/lib.rs
src/libuuid/lib.rs
src/llvm
src/rt/arch/x86_64/morestack.S
src/rt/rust_builtin.c
src/rustllvm/llvm-auto-clean-trigger
src/test/compile-fail/borrowck-lend-flow-match.rs
src/test/compile-fail/borrowck-mutate-in-guard.rs [new file with mode: 0644]
src/test/compile-fail/deprecated-url.rs [new file with mode: 0644]
src/test/pretty/issue-4264.pp [new file with mode: 0644]
src/test/pretty/issue-4264.rs [new file with mode: 0644]
src/test/pretty/match-block-expr.rs [new file with mode: 0644]
src/test/pretty/match-naked-expr-medium.rs
src/test/pretty/match-naked-expr.rs
src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot
src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot
src/test/run-make/issue-7349/Makefile [new file with mode: 0644]
src/test/run-make/issue-7349/foo.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/qquote.rs
src/test/run-pass-fulldeps/quote-tokens.rs
src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs
src/test/run-pass/dupe-first-attr.rc
src/test/run-pass/intrinsic-alignment.rs
src/test/run-pass/issue-10683.rs
src/test/run-pass/issue-11881.rs
src/test/run-pass/lang-item-public.rs
src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs [new file with mode: 0644]
src/test/run-pass/rec-align-u64.rs
src/test/run-pass/spawn-stack-too-big.rs [new file with mode: 0644]
src/test/run-pass/x86stdcall.rs

index 53fb8e25c5ff0282abbae0826200b5ba19cd16ce..e08e28e0aece0eecae3c97da8ca41244d511418e 100755 (executable)
--- a/configure
+++ b/configure
@@ -291,6 +291,10 @@ case $CFG_OSTYPE in
         CFG_OSTYPE=unknown-freebsd
         ;;
 
+    DragonFly)
+        CFG_OSTYPE=unknown-dragonfly
+        ;;
+
     Darwin)
         CFG_OSTYPE=apple-darwin
         ;;
index b72574f6fe326bf3d2385e2b0c7034749c1fad60..29643ea25f70714ecbc48eadf1c77767d644f5c6 100644 (file)
@@ -580,6 +580,33 @@ CFG_LDPATH_x86_64-unknown-freebsd :=
 CFG_RUN_x86_64-unknown-freebsd=$(2)
 CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2))
 
+# x86_64-pc-dragonfly-elf configuration
+CC_x86_64-unknown-dragonfly=$(CC)
+CXX_x86_64-unknown-dragonfly=$(CXX)
+CPP_x86_64-unknown-dragonfly=$(CPP)
+AR_x86_64-unknown-dragonfly=$(AR)
+CFG_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -I/usr/include -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread  -lrt
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_x86_64-unknown-dragonfly := .bsd.def
+CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
+CFG_INSTALL_NAME_x86_64-unknown-dragonfly =
+CFG_LIBUV_LINK_FLAGS_x86_64-unknown-dragonfly := -pthread  -lkvm
+CFG_EXE_SUFFIX_x86_64-unknown-dragonfly :=
+CFG_WINDOWSY_x86_64-unknown-dragonfly :=
+CFG_UNIXY_x86_64-unknown-dragonfly := 1
+CFG_PATH_MUNGE_x86_64-unknown-dragonfly :=
+CFG_LDPATH_x86_64-unknown-dragonfly :=
+CFG_RUN_x86_64-unknown-dragonfly=$(2)
+CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2))
+
 
 # The -Qunused-arguments sidesteps spurious warnings from clang
 define FILTER_FLAGS
index e41dc8f4daab342cc7240881f55f4e1066404bb4..13ed4abb438bf4a4e5ca00763f1dda4ad355ccb5 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -171,6 +171,10 @@ else ifeq ($(OSTYPE_$(1)), apple-ios)
   JEMALLOC_ARGS_$(1) := --disable-tls
 else ifeq ($(OSTYPE_$(1)), unknown-freebsd)
   LIBUV_OSTYPE_$(1) := freebsd
+else ifeq ($(OSTYPE_$(1)), unknown-dragonfly)
+  LIBUV_OSTYPE_$(1) := freebsd
+  # required on DragonFly, otherwise gyp fails with a Python exception
+  LIBUV_GYP_ARGS_$(1) := --no-parallel
 else ifeq ($(OSTYPE_$(1)), linux-androideabi)
   LIBUV_OSTYPE_$(1) := android
   LIBUV_ARGS_$(1) := PLATFORM=android host=android OS=linux
@@ -202,7 +206,7 @@ $$(LIBUV_MAKEFILE_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) $$(LIBUV_STAMP_$(1))
         $$(CFG_PYTHON) ./gyp_uv.py -f make -Dtarget_arch=$$(LIBUV_ARCH_$(1)) \
           -D ninja \
           -DOS=$$(LIBUV_OSTYPE_$(1)) \
-          -Goutput_dir=$$(@D) --generator-output $$(@D))
+          -Goutput_dir=$$(@D) $$(LIBUV_GYP_ARGS_$(1)) --generator-output $$(@D))
        touch $$@
 
 # Windows has a completely different build system for libuv because of mingw. In
index 6ef2a52086e2f2059bdf7409857469c4f0b1d413..aa96f3e272712e87165309ab37f122e01f122dbf 100644 (file)
@@ -36,6 +36,10 @@ pub struct TestProps {
     pub no_prefer_dynamic: bool,
     // Don't run --pretty expanded when running pretty printing tests
     pub no_pretty_expanded: bool,
+    // Which pretty mode are we testing with, default to 'normal'
+    pub pretty_mode: String,
+    // Only compare pretty output and don't try compiling
+    pub pretty_compare_only: bool,
 }
 
 // Load any test directives embedded in the file
@@ -51,6 +55,8 @@ pub fn load_props(testfile: &Path) -> TestProps {
     let mut check_stdout = false;
     let mut no_prefer_dynamic = false;
     let mut no_pretty_expanded = false;
+    let mut pretty_mode = None;
+    let mut pretty_compare_only = false;
     iter_header(testfile, |ln| {
         match parse_error_pattern(ln) {
           Some(ep) => error_patterns.push(ep),
@@ -85,6 +91,14 @@ pub fn load_props(testfile: &Path) -> TestProps {
             no_pretty_expanded = parse_no_pretty_expanded(ln);
         }
 
+        if pretty_mode.is_none() {
+            pretty_mode = parse_pretty_mode(ln);
+        }
+
+        if !pretty_compare_only {
+            pretty_compare_only = parse_pretty_compare_only(ln);
+        }
+
         match parse_aux_build(ln) {
             Some(ab) => { aux_builds.push(ab); }
             None => {}
@@ -115,6 +129,8 @@ pub fn load_props(testfile: &Path) -> TestProps {
         check_stdout: check_stdout,
         no_prefer_dynamic: no_prefer_dynamic,
         no_pretty_expanded: no_pretty_expanded,
+        pretty_mode: pretty_mode.unwrap_or("normal".to_string()),
+        pretty_compare_only: pretty_compare_only
     }
 }
 
@@ -205,6 +221,14 @@ fn parse_no_pretty_expanded(line: &str) -> bool {
     parse_name_directive(line, "no-pretty-expanded")
 }
 
+fn parse_pretty_mode(line: &str) -> Option<String> {
+    parse_name_value_directive(line, "pretty-mode")
+}
+
+fn parse_pretty_compare_only(line: &str) -> bool {
+    parse_name_directive(line, "pretty-compare-only")
+}
+
 fn parse_exec_env(line: &str) -> Option<(String, String)> {
     parse_name_value_directive(line, "exec-env").map(|nv| {
         // nv is either FOO or FOO=BAR
index 6720b9a530f230c509df0c17ba6d09fa4d30e336..851d12f814b56fd9b137bcedc8eac2219a31cd8f 100644 (file)
@@ -168,7 +168,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
                                     props,
                                     testfile,
                                     srcs[round].to_string(),
-                                    "normal");
+                                    props.pretty_mode.as_slice());
 
         if !proc_res.status.success() {
             fatal_proc_rec(format!("pretty-printing failed in round {}",
@@ -200,6 +200,9 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     compare_source(expected.as_slice(), actual.as_slice());
 
+    // If we're only making sure that the output matches then just stop here
+    if props.pretty_compare_only { return; }
+
     // Finally, let's make sure it actually appears to remain valid code
     let proc_res = typecheck_source(config, props, testfile, actual);
 
@@ -834,6 +837,7 @@ fn prefix_matches( line : &str, prefix : &str ) -> bool {
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     fn prefix_matches( line : &str, prefix : &str ) -> bool {
         line.starts_with( prefix )
     }
@@ -1237,6 +1241,7 @@ fn program_output(config: &Config, testfile: &Path, lib_path: &str, prog: String
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 fn make_cmdline(_libpath: &str, prog: &str, args: &[String]) -> String {
     format!("{} {}", prog, args.connect(" "))
 }
index 369e6b0af645c82505bf6e08e7ed0df5b6f852b6..445e814a1eb04fddb83b39e1bb54c3ef80a8eea7 100644 (file)
@@ -21,6 +21,7 @@
     ("android", "android"),
     ("linux", "linux"),
     ("freebsd", "freebsd"),
+    ("dragonfly", "dragonfly"),
 ];
 
 pub fn get_os(triple: &str) -> &'static str {
index 387841ab3fcefac72c86f748842a915adf86fe75..2216d829e4be83a5b0396926daf77d6c4ceb1065 100644 (file)
@@ -1770,7 +1770,7 @@ fn main() {
 
 ```{notrust,ignore}
 $ cargo build
-  Compiling guessing_game v0.1.0 (file:/home/steve/tmp/guessing_game)
+  Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
 $
 ```
 
@@ -2042,7 +2042,7 @@ Let's try it out!
 
 ```{notrust,ignore}
 $ cargo build
-   Compiling guessing_game v0.1.0 (file:/home/steve/tmp/guessing_game)
+   Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
 src/guessing_game.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option<uint>` (expected uint but found enum core::option::Option)
 src/guessing_game.rs:22     match cmp(input_num, secret_number) {
                                       ^~~~~~~~~
@@ -2246,7 +2246,7 @@ that `return`? If we give a non-number answer, we'll `return` and quit. Observe:
 ```{notrust,ignore}
 $ cargo build
    Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
-steve@computer:~/tmp/guessing_game$ ./target/guessing_game 
+$ ./target/guessing_game 
 Guess the number!
 The secret number is: 59
 Please input your guess.
@@ -2462,19 +2462,361 @@ rest of your Rust education.
 Now that you're an expert at the basics, it's time to learn about some of
 Rust's more unique features.
 
-# iterators
+# Crates and Modules
 
-# Lambdas
+Rust features a strong module system, but it works a bit differently than in
+other programming languages. Rust's module system has two main components:
+**crate**s, and **module**s.
+
+A crate is Rust's unit of independent compilation. Rust always compiles one
+crate at a time, producing either a library or an executable. However, executables
+usually depend on libraries, and many libraries depend on other libraries as well.
+To support this, crates can depend on other crates.
+
+Each crate contains a hierarchy of modules. This tree starts off with a single
+module, called the **crate root**. Within the crate root, we can declare other
+modules, which can contain other modules, as deeply as you'd like.
+
+Note that we haven't mentioned anything about files yet. Rust does not impose a
+particular relationship between your filesystem structure and your module
+structure. That said, there is a conventional approach to how Rust looks for
+modules on the file system, but it's also overrideable.
+
+Enough talk, let's build something! Let's make a new project called `modules`.
+
+```{bash,ignore}
+$ cd ~/projects
+$ mkdir modules
+$ cd modules
+$ mkdir src
+```
+
+We need to make our two 'hello world' files. In `src/main.rs`:
+
+```{rust}
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+And in `Cargo.toml`:
+
+```{notrust,ignore}
+[package]
+
+name = "modules"
+version = "0.1.0"
+authors = [ "someone@example.com" ]
+```
+
+Let's double check our work by compiling:
+
+```{bash,ignore}
+$ cargo build
+   Compiling modules v0.1.0 (file:/home/you/projects/modules)
+$ ./target/modules
+Hello, world!
+```
+
+Excellent! So, we already have a single crate here: our `src/main.rs` is a crate.
+Everything in that file is in the crate root. A crate that generates an executable
+defines a `main` function inside its root, as we've done here.
+
+Let's define a new module inside our crate. Edit `src/main.rs` to look
+like this:
+
+```
+fn main() {
+    println!("Hello, world!");
+}
+
+mod hello {
+    fn print_hello() {
+        println!("Hello, world!");
+    }
+}
+```
+
+We now have a module named `hello` inside of our crate root. Modules use
+`snake_case` naming, like functions and variable bindings.
+
+Inside the `hello` module, we've defined a `print_hello` function. This will
+also print out our hello world message. Modules allow you to split up your
+program into nice neat boxes of functionality, grouping common things together,
+and keeping different things apart. It's kinda like having a set of shelves:
+a place for everything and everything in its place.
+
+To call our `print_hello` function, we use the double colon (`::`):
+
+```{rust,ignore}
+hello::print_hello();
+```
+
+You've seen this before, with `io::stdin()` and `rand::random()`. Now you know
+how to make your own. However, crates and modules have rules about
+**visibility**, which controls who exactly may use the functions defined in a
+given module. By default, everything in a module is private, which means that
+it can only be used by other functions in the same module. This will not
+compile:
+
+```{rust,ignore}
+fn main() {
+    hello::print_hello();
+}
+
+mod hello {
+    fn print_hello() {
+        println!("Hello, world!");
+    }
+}
+```
+
+It gives an error:
+
+```{notrust,ignore}
+   Compiling modules v0.1.0 (file:/home/you/projects/modules)
+src/modules.rs:2:5: 2:23 error: function `print_hello` is private
+src/modules.rs:2     hello::print_hello();
+                     ^~~~~~~~~~~~~~~~~~
+```
+
+To make it public, we use the `pub` keyword:
+
+```{rust}
+fn main() {
+    hello::print_hello();
+}
+
+mod hello {
+    pub fn print_hello() {
+        println!("Hello, world!");
+    }
+}
+```
+
+This will work:
+
+```{notrust,ignore}
+$ cargo build
+   Compiling modules v0.1.0 (file:/home/you/projects/modules)
+$
+```
+
+Before we move on, let me show you one more Cargo command: `run`. `cargo run`
+is kind of like `cargo build`, but it also then runs the produced exectuable.
+Try it out:
+
+```{notrust,ignore}
+$ cargo run
+   Compiling modules v0.1.0 (file:/home/steve/tmp/modules)
+     Running `target/modules`
+Hello, world!
+$
+```
+
+Nice!
+
+There's a common pattern when you're building an executable: you build both an
+executable and a library, and put most of your logic in the library. That way,
+other programs can use that library to build their own functionality.
+
+Let's do that with our project. If you remember, libraries and executables
+are both crates, so while our project has one crate now, let's make a second:
+one for the library, and one for the executable.
+
+To make the second crate, open up `src/lib.rs` and put this code in it:
+
+```{rust}
+mod hello {
+    pub fn print_hello() {
+        println!("Hello, world!");
+    }
+}
+```
+
+And change your `src/main.rs` to look like this:
+
+```{rust,ignore}
+extern crate modules;
+
+fn main() {
+    modules::hello::print_hello();
+}
+```
+
+There's been a few changes. First, we moved our `hello` module into its own
+file, `src/lib.rs`. This is the file that Cargo expects a library crate to
+be named, by convention.
+
+Next, we added an `extern crate modules` to the top of our `src/main.rs`. This,
+as you can guess, lets Rust know that our crate relies on another, external
+crate. We also had to modify our call to `print_hello`: now that it's in
+another crate, we need to first specify the crate, then the module inside of it,
+then the function name.
+
+This doesn't _quite_ work yet. Try it:
+
+```{notrust,ignore}
+$ cargo build
+   Compiling modules v0.1.0 (file:/home/you/projects/modules)
+/home/you/projects/modules/src/lib.rs:2:5: 4:6 warning: code is never used: `print_hello`, #[warn(dead_code)] on by default
+/home/you/projects/modules/src/lib.rs:2     pub fn print_hello() {
+/home/you/projects/modules/src/lib.rs:3         println!("Hello, world!");
+/home/you/projects/modules/src/lib.rs:4     }
+/home/you/projects/modules/src/main.rs:4:5: 4:32 error: function `print_hello` is private
+/home/you/projects/modules/src/main.rs:4     modules::hello::print_hello();
+                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+error: aborting due to previous error
+Could not compile `modules`.
+```
+
+First, we get a warning that some code is never used. Odd. Next, we get an error:
+`print_hello` is private, so we can't call it. Notice that the first error came
+from `src/lib.rs`, and the second came from `src/main.rs`: cargo is smart enough
+to build it all with one command. Also, after seeing the second error, the warning
+makes sense: we never actually call `hello_world`, because we're not allowed to!
+
+Just like modules, crates also have private visibility by default. Any modules
+inside of a crate can only be used by other modules in the crate, unless they
+use `pub`. In `src/lib.rs`, change this line:
+
+```{rust,ignore}
+mod hello {
+```
+
+To this:
+
+```{rust,ignore}
+pub mod hello {
+```
+
+And everything should work:
+
+```{notrust,ignore}
+$ cargo run
+   Compiling modules v0.1.0 (file:/home/you/projects/modules)
+     Running `target/modules`
+Hello, world!
+```
+
+Let's do one more thing: add a `goodbye` module as well. Imagine a `src/lib.rs`
+that looks like this:
+
+```{rust,ignore}
+pub mod hello {
+    pub fn print_hello() {
+        println!("Hello, world!");
+    }
+}
+
+pub mod goodbye {
+    pub fn print_goodbye() {
+        println!("Goodbye for now!");
+    }
+}
+```
+
+Now, these two modules are pretty small, but imagine we've written a real, large
+program: they could both be huge. So maybe we want to move them into their own
+files. We can do that pretty easily, and there are two different conventions
+for doing it. Let's give each a try. First, make `src/lib.rs` look like this:
+
+```{rust,ignore}
+pub mod hello;
+pub mod goodbye;
+```
+
+This tells Rust that this crate has two public modules: `hello` and `goodbye`.
+
+Next, make a `src/hello.rs` that contains this:
+
+```{rust,ignore}
+pub fn print_hello() {
+    println!("Hello, world!");
+}
+```
+
+When we include a module like this, we don't need to make the `mod` declaration,
+it's just understood. This helps prevent 'rightward drift': when you end up
+indenting so many times that your code is hard to read.
+
+Finally, make a new directory, `src/goodbye`, and make a new file in it,
+`src/goodbye/mod.rs`:
+
+```{rust,ignore}
+pub fn print_goodbye() {
+    println!("Bye for now!");
+}
+```
+
+Same deal, but we can make a folder with a `mod.rs` instead of `mod_name.rs` in
+the same directory. If you have a lot of modules, nested folders can make
+sense.  For example, if the `goodbye` module had its _own_ modules inside of
+it, putting all of that in a folder helps keep our directory structure tidy.
+And in fact, if you place the modules in separate files, they're required to be
+in separate folders.
+
+This should all compile as usual:
+
+```{notrust,ignore}
+$ cargo build
+   Compiling modules v0.1.0 (file:/home/you/projects/modules)
+$
+```
+
+We've seen how the `::` operator can be used to call into modules, but when
+we have deep nesting like `modules::hello::say_hello`, it can get tedious.
+That's why we have the `use` keyword.
+
+`use` allows us to bring certain names into another scope. For example, here's
+our main program:
+
+```{rust,ignore}
+extern crate modules;
+
+fn main() {
+    modules::hello::print_hello();
+}
+```
+
+We could instead write this:
+
+```{rust,ignore}
+extern crate modules;
+
+use modules::hello::print_hello;
+
+fn main() {
+    print_hello();
+}
+```
+
+By bringing `print_hello` into scope, we don't need to qualify it anymore. However,
+it's considered proper style to do write this code like like this:
+
+```{rust,ignore}
+extern crate modules;
+
+use modules::hello;
+
+fn main() {
+    hello::print_hello();
+}
+```
+
+By just bringing the module into scope, we can keep one level of namespacing.
 
 # Testing
 
-attributes
+## Attributes
 
-stability markers
+## Stability Markers
 
-# Crates and Modules
+# Pointers
 
-visibility
+# Lambdas
+
+# iterators
 
 
 # Generics
index c54f4e00905de66048cea0a7c7eb55fd8acb7fa6..c96f10a0be8e6502ebe83bc3dfd744e43892aa9c 100644 (file)
@@ -84,6 +84,7 @@ as that for which this documentation was generated.*
 
 * [Reddit](http://reddit.com/r/rust)
 * [Stack Overflow](http://stackoverflow.com/questions/tagged/rust)
+* [Developer Forum](http://discuss.rust-lang.org/)
 * The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/):
     * [`#rust`](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) - general discussion
     * [`#rust-gamedev`](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-gamedev) - game development
index 32c5f346de12b52be11986ae1c00d2c35775e0f9..128d5c9d320595230ffa1d63caf406ef3fc10295 100644 (file)
@@ -36,8 +36,8 @@ int add_one(void)
 }
 ```
 
-**Note: obviously this is very simple and non-idiomatic C++.
-You wouldn't write it in practice; it is for illustrative purposes.**
+**Note: The above C++ code is deliberately simple and non-idiomatic for the purpose
+of demonstration. It is not representative of production-quality C++ code.**
 
 This function allocates an integer on the stack,
 and stores it in a variable, `i`.
index b015cb0fbb8c679bab536198dab5e54d42fad9e9..3f4be7bbf31e575fa52acd3135704911f39c1111 100644 (file)
@@ -1950,6 +1950,12 @@ interpreted:
 - `unsafe_no_drop_flag` - on structs, remove the flag that prevents
   destructors from being run twice. Destructors might be run multiple times on
   the same object with this attribute.
+- `phase` - on `extern crate` statements, allows specifying which "phase" of
+  compilation the crate should be loaded for. Currently, there are two
+  choices: `link` and `plugin`. `link` is the default. `plugin` will load the
+  crate at compile-time and use any syntax extensions or lints that the crate
+  defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
+  both at runtime and compiletime.
 
 ### Conditional compilation
 
@@ -2001,7 +2007,7 @@ The following configurations must be defined by the implementation:
    `"unix"` or `"windows"`. The value of this configuration option is defined as
    a configuration itself, like `unix` or `windows`.
  * `target_os = "..."`. Operating system of the target, examples include
-   `"win32"`, `"macos"`, `"linux"`, `"android"` or `"freebsd"`.
+   `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"` or `"dragonfly"`.
  * `target_word_size = "..."`. Target word size in bits. This is set to `"32"`
    for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit
    pointers.
@@ -2395,17 +2401,17 @@ The currently implemented features of the reference compiler are:
                closure as `once` is unlikely to be supported going forward. So
                they are hidden behind this feature until they are to be removed.
 
-* `managed_boxes` - Usage of `@` pointers is gated due to many
+* `asm` - The `asm!` macro provides a means for inline assembly. This is often
+          useful, but the exact syntax for this feature along with its semantics
+          are likely to change, so this macro usage must be opted into.
+
+* `managed_boxes` - Usage of `@` is gated due to many
                     planned changes to this feature. In the past, this has meant
                     "a GC pointer", but the current implementation uses
                     reference counting and will likely change drastically over
                     time. Additionally, the `@` syntax will no longer be used to
                     create GC boxes.
 
-* `asm` - The `asm!` macro provides a means for inline assembly. This is often
-          useful, but the exact syntax for this feature along with its semantics
-          are likely to change, so this macro usage must be opted into.
-
 * `non_ascii_idents` - The compiler supports the use of non-ascii identifiers,
                        but the implementation is a little rough around the
                        edges, so this can be seen as an experimental feature for
@@ -2427,6 +2433,66 @@ The currently implemented features of the reference compiler are:
                 if the system linker is not used then specifying custom flags
                 doesn't have much meaning.
 
+* `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins
+            for custom lints or syntax extensions. The implementation is considered
+            unwholesome and in need of overhaul, and it is not clear what they
+            will look like moving forward.
+
+* `plugin_registrar` - Indicates that a crate has compiler plugins that it
+                       wants to load. As with `phase`, the implementation is
+                       in need of a overhaul, and it is not clear that plugins
+                       defined using this will continue to work.
+
+* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
+                 nasty hack that will certainly be removed.
+
+* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
+                   hack that will certainly be removed.
+
+* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
+                    ways insufficient for concatenating identifiers, and may
+                    be removed entirely for something more wholsome.
+
+* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
+                        which is considered wildly unsafe and will be
+                        obsoleted by language improvements.
+
+* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
+                 are inherently unstable and no promise about them is made.
+
+* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`,
+                 lang items are inherently unstable and no promise about
+                 them is made.
+
+* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and
+           not the SIMD interface we want to expose in the long term.
+
+* `default_type_params` - Allows use of default type parameters. The future of
+                          this feature is uncertain.
+
+* `quote` - Allows use of the `quote_*!` family of macros, which are
+            implemented very poorly and will likely change significantly
+            with a proper implementation.
+
+* `linkage` - Allows use of the `linkage` attribute, which is not portable.
+
+* `struct_inherit` - Allows using struct inheritance, which is barely
+                     implemented and will probably be removed. Don't use this.
+
+* `overloaded_calls` - Allow implementing the `Fn*` family of traits on user
+                       types, allowing overloading the call operator (`()`).
+                       This feature may still undergo changes before being
+                       stabilized.
+
+* `unboxed_closure_sugar` - Allows using `|Foo| -> Bar` as a trait bound
+                            meaning one of the `Fn` traits.  Still
+                            experimental.
+
+* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
+                             of rustc, not meant for mortals.
+
+* `unboxed_closures` - A work in progress feature with many known bugs.
+
 If a feature is promoted to a language feature, then all existing programs will
 start to receive compilation warnings about #[feature] directives which enabled
 the new feature (because the directive is no longer necessary). However, if
index 7c9780456cf4763e5895d1c101cab31663586638..a934c426857e879f3eec4ca0e4bbefb5920119ba 100644 (file)
       <match>\\\%{common_escape}</match>
     </context>
 
+    <context id="raw-string" style-ref="string" class="string" class-disabled="no-spell-check">
+      <start>r(#*)"</start>
+      <end>"\%{1@start}</end>
+      <include>
+        <context ref="def:line-continue"/>
+      </include>
+    </context>
+
     <context id="string" style-ref="string" class="string" class-disabled="no-spell-check">
       <start>"</start>
       <end>"</end>
       <end>\]</end>
       <include>
         <context ref="def:in-comment"/>
+        <context ref="string"/>
+        <context ref="raw-string"/>
       </include>
     </context>
 
         <context ref="number"/>
         <context ref="scope"/>
         <context ref="string"/>
+        <context ref="raw-string"/>
         <context ref="char"/>
         <context ref="lifetime"/>
         <context ref="attribute"/>
index e78f231b9d78f850a316f47189029ed5ca89514e..56ebd4f140f523f0d517ec30be5c879b71909e40 100755 (executable)
@@ -18,7 +18,7 @@ LIB_PREFIX=lib
 
 OS=`uname -s`
 case $OS in
-    ("Linux"|"FreeBSD")
+    ("Linux"|"FreeBSD"|"DragonFly")
     BIN_SUF=
     LIB_SUF=.so
     break
@@ -58,3 +58,6 @@ cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_D
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
 cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}syntax*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
+
+# do not fail if one of the above fails, as all we need is a working rustc!
+exit 0
index f745f5d61cb9a19e3065e33303a67ed5412d618b..113c192ec07bf46b0a5c77e24965a5900b1eda88 100644 (file)
@@ -56,6 +56,8 @@ for llconfig in sys.argv[4:]:
         os = 'linux'
     elif 'freebsd' in os:
         os = 'freebsd'
+    elif 'dragonfly' in os:
+        os = 'dragonfly'
     elif 'android' in os:
         os = 'android'
     elif 'win' in os or 'mingw' in os:
index 1ac2c9fc6bec60520e0c1268350df722d7975dac..bf477781aabf6a8207d61956fc5682013783bb46 100644 (file)
@@ -92,7 +92,7 @@ pub fn new(data: T) -> Arc<T> {
     }
 
     #[inline]
-    fn inner<'a>(&'a self) -> &'a ArcInner<T> {
+    fn inner(&self) -> &ArcInner<T> {
         // This unsafety is ok because while this arc is alive we're guaranteed
         // that the inner pointer is valid. Furthermore, we know that the
         // `ArcInner` structure itself is `Share` because the inner data is
@@ -142,7 +142,7 @@ fn clone(&self) -> Arc<T> {
 #[experimental = "Deref is experimental."]
 impl<T: Send + Share> Deref<T> for Arc<T> {
     #[inline]
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         &self.inner().data
     }
 }
@@ -155,7 +155,7 @@ impl<T: Send + Share + Clone> Arc<T> {
     /// data is cloned if the reference count is greater than one.
     #[inline]
     #[experimental]
-    pub fn make_unique<'a>(&'a mut self) -> &'a mut T {
+    pub fn make_unique(&mut self) -> &mut T {
         // Note that we hold a strong reference, which also counts as
         // a weak reference, so we only clone if there is an
         // additional reference of either kind.
@@ -238,7 +238,7 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
     }
 
     #[inline]
-    fn inner<'a>(&'a self) -> &'a ArcInner<T> {
+    fn inner(&self) -> &ArcInner<T> {
         // See comments above for why this is "safe"
         unsafe { &*self._ptr }
     }
index 68b6416b69bf5c16142775cd1cbfd81b8f2d2634..5e3ce75eb9586bc56a085d28536b4bf3df4780ec 100644 (file)
@@ -29,6 +29,7 @@
 use core::iter;
 use core::mem;
 use core::ptr;
+use std::hash::{Writer, Hash};
 
 use {Collection, Mutable, Deque, MutableSeq};
 
@@ -707,10 +708,20 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<S: Writer, A: Hash<S>> Hash<S> for DList<A> {
+    fn hash(&self, state: &mut S) {
+        self.len().hash(state);
+        for elt in self.iter() {
+            elt.hash(state);
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use std::prelude::*;
     use std::rand;
+    use std::hash;
     use test::Bencher;
     use test;
 
@@ -1075,6 +1086,24 @@ fn test_eq() {
         assert!(n != m);
     }
 
+    #[test]
+    fn test_hash() {
+      let mut x = DList::new();
+      let mut y = DList::new();
+
+      assert!(hash::hash(&x) == hash::hash(&y));
+
+      x.push_back(1i);
+      x.push_back(2);
+      x.push_back(3);
+
+      y.push_front(3i);
+      y.push_front(2);
+      y.push_front(1);
+
+      assert!(hash::hash(&x) == hash::hash(&y));
+    }
+
     #[test]
     fn test_ord() {
         let n: DList<int> = list_from([]);
index 64062dc0ccbf8abc2e4f62adbaf5c7ca923727ab..5b1722b2769168d396a86de7f23a20cc3480c66d 100644 (file)
@@ -579,7 +579,7 @@ pub trait MutableVectorAllocating<'a, T> {
      *
      * * src - A mutable vector of `T`
      * * start - The index into `src` to start copying from
-     * * end - The index into `str` to stop copying from
+     * * end - The index into `src` to stop copying from
      */
     fn move_from(self, src: Vec<T>, start: uint, end: uint) -> uint;
 }
index e5c2d98519163926720ceccbbd5c78194e8d1ece..d9aea8b0a28a3143d3ec7b8087502f82f8933a9e 100644 (file)
@@ -688,7 +688,7 @@ pub unsafe fn shift_byte(&mut self) -> Option<u8> {
     /// assert_eq!(s.shift_char(), Some('o'));
     /// assert_eq!(s.shift_char(), None);
     /// ```
-    pub fn shift_char (&mut self) -> Option<char> {
+    pub fn shift_char(&mut self) -> Option<char> {
         let len = self.len();
         if len == 0 {
             return None
index 82745663e0cad3bd8711493bc88af8065e0e7ae7..d4cf10b384f39aba8abeb08c6864cfeb4c76c4be 100644 (file)
@@ -117,23 +117,23 @@ fn neg_infinity() -> f32 { NEG_INFINITY }
     #[inline]
     fn neg_zero() -> f32 { -0.0 }
 
-    /// Returns `true` if the number is NaN
+    /// Returns `true` if the number is NaN.
     #[inline]
     fn is_nan(self) -> bool { self != self }
 
-    /// Returns `true` if the number is infinite
+    /// Returns `true` if the number is infinite.
     #[inline]
     fn is_infinite(self) -> bool {
         self == Float::infinity() || self == Float::neg_infinity()
     }
 
-    /// Returns `true` if the number is neither infinite or NaN
+    /// Returns `true` if the number is neither infinite or NaN.
     #[inline]
     fn is_finite(self) -> bool {
         !(self.is_nan() || self.is_infinite())
     }
 
-    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN
+    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
     #[inline]
     fn is_normal(self) -> bool {
         self.classify() == FPNormal
@@ -195,25 +195,25 @@ fn integer_decode(self) -> (u64, i16, i8) {
         (mantissa as u64, exponent, sign)
     }
 
-    /// Round half-way cases toward `NEG_INFINITY`
+    /// Rounds towards minus infinity.
     #[inline]
     fn floor(self) -> f32 {
         unsafe { intrinsics::floorf32(self) }
     }
 
-    /// Round half-way cases toward `INFINITY`
+    /// Rounds towards plus infinity.
     #[inline]
     fn ceil(self) -> f32 {
         unsafe { intrinsics::ceilf32(self) }
     }
 
-    /// Round half-way cases away from `0.0`
+    /// Rounds to nearest integer. Rounds half-way cases away from zero.
     #[inline]
     fn round(self) -> f32 {
         unsafe { intrinsics::roundf32(self) }
     }
 
-    /// The integer part of the number (rounds towards `0.0`)
+    /// Returns the integer part of the number (rounds towards zero).
     #[inline]
     fn trunc(self) -> f32 {
         unsafe { intrinsics::truncf32(self) }
@@ -236,7 +236,7 @@ fn mul_add(self, a: f32, b: f32) -> f32 {
         unsafe { intrinsics::fmaf32(self, a, b) }
     }
 
-    /// The reciprocal (multiplicative inverse) of the number
+    /// Returns the reciprocal (multiplicative inverse) of the number.
     #[inline]
     fn recip(self) -> f32 { 1.0 / self }
 
@@ -325,45 +325,45 @@ fn ln_2() -> f32 { consts::LN_2 }
     #[inline]
     fn ln_10() -> f32 { consts::LN_10 }
 
-    /// Returns the exponential of the number
+    /// Returns the exponential of the number.
     #[inline]
     fn exp(self) -> f32 {
         unsafe { intrinsics::expf32(self) }
     }
 
-    /// Returns 2 raised to the power of the number
+    /// Returns 2 raised to the power of the number.
     #[inline]
     fn exp2(self) -> f32 {
         unsafe { intrinsics::exp2f32(self) }
     }
 
-    /// Returns the natural logarithm of the number
+    /// Returns the natural logarithm of the number.
     #[inline]
     fn ln(self) -> f32 {
         unsafe { intrinsics::logf32(self) }
     }
 
-    /// Returns the logarithm of the number with respect to an arbitrary base
+    /// Returns the logarithm of the number with respect to an arbitrary base.
     #[inline]
     fn log(self, base: f32) -> f32 { self.ln() / base.ln() }
 
-    /// Returns the base 2 logarithm of the number
+    /// Returns the base 2 logarithm of the number.
     #[inline]
     fn log2(self) -> f32 {
         unsafe { intrinsics::log2f32(self) }
     }
 
-    /// Returns the base 10 logarithm of the number
+    /// Returns the base 10 logarithm of the number.
     #[inline]
     fn log10(self) -> f32 {
         unsafe { intrinsics::log10f32(self) }
     }
 
-    /// Converts to degrees, assuming the number is in radians
+    /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }
 
-    /// Converts to radians, assuming the number is in degrees
+    /// Converts to radians, assuming the number is in degrees.
     #[inline]
     fn to_radians(self) -> f32 {
         let value: f32 = Float::pi();
index a3a82aeec5ec78f1cb8cbf453a8435ee874f15fc..a3ae8e7c79ea355309dc9189cf13c822966b3b21 100644 (file)
@@ -123,23 +123,23 @@ fn neg_infinity() -> f64 { NEG_INFINITY }
     #[inline]
     fn neg_zero() -> f64 { -0.0 }
 
-    /// Returns `true` if the number is NaN
+    /// Returns `true` if the number is NaN.
     #[inline]
     fn is_nan(self) -> bool { self != self }
 
-    /// Returns `true` if the number is infinite
+    /// Returns `true` if the number is infinite.
     #[inline]
     fn is_infinite(self) -> bool {
         self == Float::infinity() || self == Float::neg_infinity()
     }
 
-    /// Returns `true` if the number is neither infinite or NaN
+    /// Returns `true` if the number is neither infinite or NaN.
     #[inline]
     fn is_finite(self) -> bool {
         !(self.is_nan() || self.is_infinite())
     }
 
-    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN
+    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
     #[inline]
     fn is_normal(self) -> bool {
         self.classify() == FPNormal
@@ -201,25 +201,25 @@ fn integer_decode(self) -> (u64, i16, i8) {
         (mantissa, exponent, sign)
     }
 
-    /// Round half-way cases toward `NEG_INFINITY`
+    /// Rounds towards minus infinity.
     #[inline]
     fn floor(self) -> f64 {
         unsafe { intrinsics::floorf64(self) }
     }
 
-    /// Round half-way cases toward `INFINITY`
+    /// Rounds towards plus infinity.
     #[inline]
     fn ceil(self) -> f64 {
         unsafe { intrinsics::ceilf64(self) }
     }
 
-    /// Round half-way cases away from `0.0`
+    /// Rounds to nearest integer. Rounds half-way cases away from zero.
     #[inline]
     fn round(self) -> f64 {
         unsafe { intrinsics::roundf64(self) }
     }
 
-    /// The integer part of the number (rounds towards `0.0`)
+    /// Returns the integer part of the number (rounds towards zero).
     #[inline]
     fn trunc(self) -> f64 {
         unsafe { intrinsics::truncf64(self) }
@@ -242,7 +242,7 @@ fn mul_add(self, a: f64, b: f64) -> f64 {
         unsafe { intrinsics::fmaf64(self, a, b) }
     }
 
-    /// The reciprocal (multiplicative inverse) of the number
+    /// Returns the reciprocal (multiplicative inverse) of the number.
     #[inline]
     fn recip(self) -> f64 { 1.0 / self }
 
@@ -332,46 +332,45 @@ fn ln_2() -> f64 { consts::LN_2 }
     #[inline]
     fn ln_10() -> f64 { consts::LN_10 }
 
-    /// Returns the exponential of the number
+    /// Returns the exponential of the number.
     #[inline]
     fn exp(self) -> f64 {
         unsafe { intrinsics::expf64(self) }
     }
 
-    /// Returns 2 raised to the power of the number
+    /// Returns 2 raised to the power of the number.
     #[inline]
     fn exp2(self) -> f64 {
         unsafe { intrinsics::exp2f64(self) }
     }
 
-    /// Returns the natural logarithm of the number
+    /// Returns the natural logarithm of the number.
     #[inline]
     fn ln(self) -> f64 {
         unsafe { intrinsics::logf64(self) }
     }
 
-    /// Returns the logarithm of the number with respect to an arbitrary base
+    /// Returns the logarithm of the number with respect to an arbitrary base.
     #[inline]
     fn log(self, base: f64) -> f64 { self.ln() / base.ln() }
 
-    /// Returns the base 2 logarithm of the number
+    /// Returns the base 2 logarithm of the number.
     #[inline]
     fn log2(self) -> f64 {
         unsafe { intrinsics::log2f64(self) }
     }
 
-    /// Returns the base 10 logarithm of the number
+    /// Returns the base 10 logarithm of the number.
     #[inline]
     fn log10(self) -> f64 {
         unsafe { intrinsics::log10f64(self) }
     }
 
-
-    /// Converts to degrees, assuming the number is in radians
+    /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f64 { self * (180.0f64 / Float::pi()) }
 
-    /// Converts to radians, assuming the number is in degrees
+    /// Converts to radians, assuming the number is in degrees.
     #[inline]
     fn to_radians(self) -> f64 {
         let value: f64 = Float::pi();
index 62547b6669f7acfec1ca168b356eca821b1962e2..3350d8f548a86cee5dc5e0f48cb1b50d9b4867ea 100644 (file)
@@ -352,8 +352,13 @@ fn count(&mut self) -> Count<'a> {
             None => {
                 let tmp = self.cur.clone();
                 match self.word() {
-                    word if word.len() > 0 && self.consume('$') => {
-                        CountIsName(word)
+                    word if word.len() > 0 => {
+                        if self.consume('$') {
+                            CountIsName(word)
+                        } else {
+                            self.cur = tmp;
+                            CountImplied
+                        }
                     }
                     _ => {
                         self.cur = tmp;
index 96b9a6a13923cf94e14baec68a516181fffaa799..922bf768854ea3d6c184015ea0feecc911e8353a 100644 (file)
@@ -529,7 +529,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 /// Parse command line arguments according to the provided options.
 ///
-/// On success returns `Ok(Opt)`. Use methods such as `opt_present`
+/// On success returns `Ok(Matches)`. Use methods such as `opt_present`
 /// `opt_str`, etc. to interrogate results.  Returns `Err(Fail_)` on
 /// failure: use the `Show` implementation of `Fail_` to display
 /// information about it.
index 38bb6e355a77151857f370433b2518308d202f06..b9144047df5c0b7e3017f3fdeb27bedd594a82d4 100644 (file)
@@ -219,7 +219,7 @@ pub fn bootstrap(mut self: Box<Scheduler>) {
         let message = stask.sched.get_mut_ref().message_queue.pop();
         rtassert!(match message { msgq::Empty => true, _ => false });
 
-        stask.task.get_mut_ref().destroyed = true;
+        stask.task.take().unwrap().drop();
     }
 
     // This does not return a scheduler, as the scheduler is placed
index 633bd3c041a3d586f2d35ee3e440587ef53bc17e..af53766617cfe1159d92692413cdbbfcde6b5996 100644 (file)
@@ -25,10 +25,14 @@ pub struct Stack {
 // anyway), but some platforms don't support it at all. For example, it appears
 // that there's a bug in freebsd that MAP_STACK implies MAP_FIXED (so it always
 // fails): http://lists.freebsd.org/pipermail/freebsd-bugs/2011-July/044840.html
-#[cfg(not(windows), not(target_os = "freebsd"))]
+//
+// DragonFly BSD also seems to suffer from the same problem. When MAP_STACK is
+// used, it returns the same `ptr` multiple times.
+#[cfg(not(windows), not(target_os = "freebsd"), not(target_os = "dragonfly"))]
 static STACK_FLAGS: libc::c_int = libc::MAP_STACK | libc::MAP_PRIVATE |
                                   libc::MAP_ANON;
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 static STACK_FLAGS: libc::c_int = libc::MAP_PRIVATE | libc::MAP_ANON;
 #[cfg(windows)]
 static STACK_FLAGS: libc::c_int = 0;
index 3d3b413384050f37e6cd6057c5b43e53118db332..12d7b75569782f18ff52408d5b880e31e45aee2c 100644 (file)
@@ -442,15 +442,30 @@ fn spawn_sibling(mut self: Box<GreenTask>,
                      f: proc():Send) {
         self.put_task(cur_task);
 
+        // First, set up a bomb which when it goes off will restore the local
+        // task unless its disarmed. This will allow us to gracefully fail from
+        // inside of `configure` which allocates a new task.
+        struct Bomb { inner: Option<Box<GreenTask>> }
+        impl Drop for Bomb {
+            fn drop(&mut self) {
+                let _ = self.inner.take().map(|task| task.put());
+            }
+        }
+        let mut bomb = Bomb { inner: Some(self) };
+
         // Spawns a task into the current scheduler. We allocate the new task's
         // stack from the scheduler's stack pool, and then configure it
         // accordingly to `opts`. Afterwards we bootstrap it immediately by
         // switching to it.
         //
         // Upon returning, our task is back in TLS and we're good to return.
-        let mut sched = self.sched.take_unwrap();
-        let sibling = GreenTask::configure(&mut sched.stack_pool, opts, f);
-        sched.run_task(self, sibling)
+        let sibling = {
+            let sched = bomb.inner.get_mut_ref().sched.get_mut_ref();
+            GreenTask::configure(&mut sched.stack_pool, opts, f)
+        };
+        let mut me = bomb.inner.take().unwrap();
+        let sched = me.sched.take().unwrap();
+        sched.run_task(me, sibling)
     }
 
     // Local I/O is provided by the scheduler's event loop
index fc4144a2868638c2f7598aaf0aabb6ba4347bed5..1bc64ffcc92ae8f05a26f3e72ae30607d0b56b38 100644 (file)
 #[cfg(windows)] pub use funcs::extra::kernel32::{MoveFileExW, VirtualProtect};
 #[cfg(windows)] pub use funcs::extra::msvcrt::{get_osfhandle, open_osfhandle};
 
-#[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "linux")] #[cfg(target_os = "android")]
+#[cfg(target_os = "freebsd")] #[cfg(target_os = "dragonfly")]
 pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC};
 
 #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
 pub use consts::os::extra::{MAP_STACK};
 
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 pub use consts::os::bsd44::{TCP_KEEPIDLE};
 
 #[cfg(target_os = "macos")]
@@ -937,6 +939,205 @@ pub mod extra {
         }
     }
 
+    #[cfg(target_os = "dragonfly")]
+    pub mod os {
+        pub mod common {
+            pub mod posix01 {
+                use types::common::c95::{c_void};
+                use types::os::arch::c95::{c_char, c_int, size_t,
+                                                 time_t, suseconds_t, c_long};
+                use types::os::arch::c99::{uintptr_t};
+
+                pub type pthread_t = uintptr_t;
+
+                pub struct glob_t {
+                    pub gl_pathc:  size_t,
+                    pub __unused1: size_t,
+                    pub gl_offs:   size_t,
+                    pub __unused2: c_int,
+                    pub gl_pathv:  *mut *mut c_char,
+
+                    pub __unused3: *mut c_void,
+
+                    pub __unused4: *mut c_void,
+                    pub __unused5: *mut c_void,
+                    pub __unused6: *mut c_void,
+                    pub __unused7: *mut c_void,
+                    pub __unused8: *mut c_void,
+                }
+
+                pub struct timeval {
+                    pub tv_sec: time_t,
+                    pub tv_usec: suseconds_t,
+                }
+
+                pub struct timespec {
+                    pub tv_sec: time_t,
+                    pub tv_nsec: c_long,
+                }
+
+                pub enum timezone {}
+
+                pub type sighandler_t = size_t;
+            }
+            pub mod bsd44 {
+                use types::os::arch::c95::{c_char, c_int, c_uint};
+
+                pub type socklen_t = u32;
+                pub type sa_family_t = u8;
+                pub type in_port_t = u16;
+                pub type in_addr_t = u32;
+                pub struct sockaddr {
+                    pub sa_len: u8,
+                    pub sa_family: sa_family_t,
+                    pub sa_data: [u8, ..14],
+                }
+                pub struct sockaddr_storage {
+                    pub ss_len: u8,
+                    pub ss_family: sa_family_t,
+                    pub __ss_pad1: [u8, ..6],
+                    pub __ss_align: i64,
+                    pub __ss_pad2: [u8, ..112],
+                }
+                pub struct sockaddr_in {
+                    pub sin_len: u8,
+                    pub sin_family: sa_family_t,
+                    pub sin_port: in_port_t,
+                    pub sin_addr: in_addr,
+                    pub sin_zero: [u8, ..8],
+                }
+                pub struct in_addr {
+                    pub s_addr: in_addr_t,
+                }
+                pub struct sockaddr_in6 {
+                    pub sin6_len: u8,
+                    pub sin6_family: sa_family_t,
+                    pub sin6_port: in_port_t,
+                    pub sin6_flowinfo: u32,
+                    pub sin6_addr: in6_addr,
+                    pub sin6_scope_id: u32,
+                }
+                pub struct in6_addr {
+                    pub s6_addr: [u16, ..8]
+                }
+                pub struct ip_mreq {
+                    pub imr_multiaddr: in_addr,
+                    pub imr_interface: in_addr,
+                }
+                pub struct ip6_mreq {
+                    pub ipv6mr_multiaddr: in6_addr,
+                    pub ipv6mr_interface: c_uint,
+                }
+                pub struct addrinfo {
+                    pub ai_flags: c_int,
+                    pub ai_family: c_int,
+                    pub ai_socktype: c_int,
+                    pub ai_protocol: c_int,
+                    pub ai_addrlen: socklen_t,
+                    pub ai_canonname: *mut c_char,
+                    pub ai_addr: *mut sockaddr,
+                    pub ai_next: *mut addrinfo,
+                }
+                pub struct sockaddr_un {
+                    pub sun_len: u8,
+                    pub sun_family: sa_family_t,
+                    pub sun_path: [c_char, ..104]
+                }
+            }
+        }
+
+        #[cfg(target_arch = "x86_64")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i64;
+                pub type c_ulong = u64;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u64;
+                pub type ptrdiff_t = i64;
+                pub type clock_t = i32;
+                pub type time_t = i64;
+                pub type suseconds_t = i64;
+                pub type wchar_t = i32;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i64;
+                pub type dev_t = u32;
+                pub type ino_t = u32;
+                pub type pid_t = i32;
+                pub type uid_t = u32;
+                pub type gid_t = u32;
+                pub type useconds_t = u32;
+                pub type mode_t = u16;
+                pub type ssize_t = i64;
+            }
+            pub mod posix01 {
+                use types::common::c95::{c_void};
+                use types::common::c99::{uint16_t, uint32_t, int32_t, uint64_t, int64_t};
+                use types::os::arch::c95::{c_long, time_t};
+                use types::os::arch::posix88::{dev_t, gid_t};
+                use types::os::arch::posix88::{mode_t, off_t};
+                use types::os::arch::posix88::{uid_t};
+
+                pub type nlink_t = u16;
+                pub type blksize_t = uint32_t;
+                pub type ino_t = uint64_t;
+                pub type blkcnt_t = i64;
+                pub type fflags_t = u32;
+
+                pub struct stat {
+                    pub st_ino: ino_t,
+                    pub st_nlink: nlink_t,
+                    pub st_dev: dev_t,
+                    pub st_mode: mode_t,
+                    pub st_padding1: uint16_t,
+                    pub st_uid: uid_t,
+                    pub st_gid: gid_t,
+                    pub st_rdev: dev_t,
+                    pub st_atime: time_t,
+                    pub st_atime_nsec: c_long,
+                    pub st_mtime: time_t,
+                    pub st_mtime_nsec: c_long,
+                    pub st_ctime: time_t,
+                    pub st_ctime_nsec: c_long,
+                    pub st_size: off_t,
+                    pub st_blocks: blkcnt_t,
+                    pub st_blksize: blksize_t,
+                    pub st_flags: fflags_t,
+                    pub st_gen: uint32_t,
+                    pub st_lspare: int32_t,
+                    pub st_qspare1: int64_t,
+                    pub st_qspare2: int64_t,
+                }
+                pub struct utimbuf {
+                    pub actime: time_t,
+                    pub modtime: time_t,
+                }
+
+                pub type pthread_attr_t = *mut c_void;
+            }
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
+            pub mod extra {
+            }
+        }
+    }
+
     #[cfg(target_os = "win32")]
     pub mod os {
         pub mod common {
@@ -2736,6 +2937,7 @@ pub mod sysconf {
     }
 
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub mod os {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
@@ -2989,12 +3191,15 @@ pub mod posix01 {
             #[cfg(target_arch = "arm")]
             pub static PTHREAD_STACK_MIN: size_t = 4096;
 
-            #[cfg(target_arch = "mips")]
-            #[cfg(target_arch = "mipsel")]
-            #[cfg(target_arch = "x86")]
-            #[cfg(target_arch = "x86_64")]
+            #[cfg(target_os = "freebsd", target_arch = "mips")]
+            #[cfg(target_os = "freebsd", target_arch = "mipsel")]
+            #[cfg(target_os = "freebsd", target_arch = "x86")]
+            #[cfg(target_os = "freebsd", target_arch = "x86_64")]
             pub static PTHREAD_STACK_MIN: size_t = 2048;
 
+            #[cfg(target_os = "dragonfly")]
+            pub static PTHREAD_STACK_MIN: size_t = 1024;
+
             pub static CLOCK_REALTIME: c_int = 0;
             pub static CLOCK_MONOTONIC: c_int = 4;
         }
@@ -3056,7 +3261,10 @@ pub mod extra {
             pub static O_SYNC : c_int = 128;
             pub static CTL_KERN: c_int = 1;
             pub static KERN_PROC: c_int = 14;
+            #[cfg(target_os = "freebsd")]
             pub static KERN_PROC_PATHNAME: c_int = 12;
+            #[cfg(target_os = "dragonfly")]
+            pub static KERN_PROC_PATHNAME: c_int = 9;
 
             pub static MAP_COPY : c_int = 0x0002;
             pub static MAP_RENAME : c_int = 0x0020;
@@ -3809,6 +4017,7 @@ pub mod mman {
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub mod posix88 {
         pub mod stat_ {
             use types::os::arch::c95::{c_char, c_int};
@@ -3821,6 +4030,7 @@ pub mod stat_ {
 
                 #[cfg(target_os = "linux")]
                 #[cfg(target_os = "freebsd")]
+                #[cfg(target_os = "dragonfly")]
                 #[cfg(target_os = "android")]
                 #[cfg(target_os = "ios")]
                 pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
@@ -3834,6 +4044,7 @@ pub mod stat_ {
 
                 #[cfg(target_os = "linux")]
                 #[cfg(target_os = "freebsd")]
+                #[cfg(target_os = "dragonfly")]
                 #[cfg(target_os = "android")]
                 #[cfg(target_os = "ios")]
                 pub fn stat(path: *const c_char, buf: *mut stat) -> c_int;
@@ -4016,6 +4227,7 @@ pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t)
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub mod posix01 {
         pub mod stat_ {
             use types::os::arch::c95::{c_char, c_int};
@@ -4024,6 +4236,7 @@ pub mod stat_ {
             extern {
                 #[cfg(target_os = "linux")]
                 #[cfg(target_os = "freebsd")]
+                #[cfg(target_os = "dragonfly")]
                 #[cfg(target_os = "android")]
                 #[cfg(target_os = "ios")]
                 pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int;
@@ -4129,6 +4342,7 @@ pub mod mman {
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub mod posix08 {
         pub mod unistd {
         }
@@ -4212,6 +4426,7 @@ pub fn sendto(socket: SOCKET, buf: *const c_void, len: c_int,
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub mod bsd44 {
         use types::common::c95::{c_void};
         use types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, size_t};
@@ -4275,6 +4490,7 @@ pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32)
     }
 
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub mod extra {
     }
 
index 2062bb4c7b1b67d95261c5f023ec131309837f5a..a8def3e289de235929e20f3fd8eddd68f8c2eab5 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::ascii::StrAsciiExt;
+use std::ascii::AsciiExt;
 use std::cmp;
 
 #[deriving(Show, Clone)]
index 9fbf3659d3f6ba900a0883655045394558343304..af4d309dfe250d2853ed2d48909b2874449699b2 100644 (file)
@@ -22,6 +22,7 @@
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 pub static FIONBIO: libc::c_ulong = 0x8004667e;
 #[cfg(target_os = "linux", target_arch = "x86")]
 #[cfg(target_os = "linux", target_arch = "x86_64")]
@@ -35,6 +36,7 @@
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 pub static FIOCLEX: libc::c_ulong = 0x20006601;
 #[cfg(target_os = "linux", target_arch = "x86")]
 #[cfg(target_os = "linux", target_arch = "x86_64")]
@@ -48,6 +50,7 @@
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 pub static MSG_DONTWAIT: libc::c_int = 0x80;
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "android")]
@@ -99,6 +102,7 @@ pub fn fd_set(set: &mut fd_set, fd: i32) {
 
 #[cfg(target_os = "android")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 #[cfg(target_os = "linux")]
 mod select {
     use std::uint;
@@ -106,6 +110,7 @@ mod select {
     pub static FD_SETSIZE: uint = 1024;
 
     pub struct fd_set {
+        // FIXME: shouldn't this be a c_ulong?
         fds_bits: [uint, ..(FD_SETSIZE / uint::BITS)]
     }
 
@@ -202,6 +207,7 @@ pub struct sigset_t {
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 mod signal {
     use libc;
 
@@ -218,6 +224,7 @@ mod signal {
     #[cfg(target_os = "ios")]
     pub type sigset_t = u32;
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub struct sigset_t {
         bits: [u32, ..4],
     }
@@ -243,6 +250,7 @@ pub struct sigaction {
     }
 
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     pub struct sigaction {
         pub sa_handler: extern fn(libc::c_int),
         pub sa_flags: libc::c_int,
index ecdf4ad2c45f49b24af8653bc2d713bfed9dd1d3..db5421481ee42eca7fbb8520a988ce87d4e6f347 100644 (file)
@@ -52,6 +52,7 @@
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "linux")]
 #[path = "timer_unix.rs"]
index c3eb5e91e90f07c5f6fd09a7f87e00c9a344abf6..7a90ede8ca863283f79dd1f75666b4465cd2c76a 100644 (file)
@@ -326,11 +326,13 @@ fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
                    seconds as libc::c_int)
     }
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
         setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
                    seconds as libc::c_int)
     }
-    #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "freebsd"))]
+    #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "freebsd"),
+      not(target_os = "dragonfly"))]
     fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> {
         Ok(())
     }
index e3e6ae425266e586265c3e2866390bd8c83c4420..c89a40d65135144f880d0904619392942793a434 100644 (file)
@@ -847,6 +847,7 @@ pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
         pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 }
index 35367ff2efab3675bbb0f376dfd893c203ecacce..c72d6c24a7c16ffa5b6cd661c9b8d2698322323c 100644 (file)
@@ -71,7 +71,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
     // Note that this increment must happen *before* the spawn in order to
     // guarantee that if this task exits it will always end up waiting for the
     // spawned task to exit.
-    bookkeeping::increment();
+    let token = bookkeeping::increment();
 
     // Spawning a new OS thread guarantees that __morestack will never get
     // triggered, but we must manually set up the actual stack bounds once this
@@ -93,7 +93,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
         let mut task = task;
         task.put_runtime(ops);
         drop(task.run(|| { f.take_unwrap()() }).destroy());
-        bookkeeping::decrement();
+        drop(token);
     })
 }
 
index acba750aaf4ac0d745f2c0b8014188050f1932b5..4dd3817e475ed7ade94875bfb85b1773bc1736f5 100644 (file)
@@ -514,9 +514,14 @@ fn gcd(&self, other: &BigUint) -> BigUint {
     #[inline]
     fn lcm(&self, other: &BigUint) -> BigUint { ((*self * *other) / self.gcd(other)) }
 
-    /// Returns `true` if the number can be divided by `other` without leaving a remainder.
+    /// Deprecated, use `is_multiple_of` instead.
+    #[deprecated = "function renamed to `is_multiple_of`"]
     #[inline]
-    fn divides(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
+    fn divides(&self, other: &BigUint) -> bool { return self.is_multiple_of(other); }
+
+    /// Returns `true` if the number is a multiple of `other`.
+    #[inline]
+    fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
 
     /// Returns `true` if the number is divisible by `2`.
     #[inline]
@@ -1112,9 +1117,14 @@ fn lcm(&self, other: &BigInt) -> BigInt {
         BigInt::from_biguint(Plus, self.data.lcm(&other.data))
     }
 
-    /// Returns `true` if the number can be divided by `other` without leaving a remainder.
+    /// Deprecated, use `is_multiple_of` instead.
+    #[deprecated = "function renamed to `is_multiple_of`"]
+    #[inline]
+    fn divides(&self, other: &BigInt) -> bool { return self.is_multiple_of(other); }
+
+    /// Returns `true` if the number is a multiple of `other`.
     #[inline]
-    fn divides(&self, other: &BigInt) -> bool { self.data.divides(&other.data) }
+    fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) }
 
     /// Returns `true` if the number is divisible by `2`.
     #[inline]
index bcaebbd136809e36368fc6fa95b8280b89cecf42..b06e2b448d46387ca39ba467d0d32d9f19552837 100644 (file)
@@ -77,16 +77,20 @@ pub trait Integer: Num + PartialOrd
     /// ~~~
     fn lcm(&self, other: &Self) -> Self;
 
-    /// Returns `true` if `other` divides evenly into `self`.
+    /// Deprecated, use `is_multiple_of` instead.
+    #[deprecated = "function renamed to `is_multiple_of`"]
+    fn divides(&self, other: &Self) -> bool;
+
+    /// Returns `true` if `other` is a multiple of `self`.
     ///
     /// # Examples
     ///
     /// ~~~
     /// # use num::Integer;
-    /// assert_eq!(9i.divides(&3), true);
-    /// assert_eq!(3i.divides(&9), false);
+    /// assert_eq!(9i.is_multiple_of(&3), true);
+    /// assert_eq!(3i.is_multiple_of(&9), false);
     /// ~~~
-    fn divides(&self, other: &Self) -> bool;
+    fn is_multiple_of(&self, other: &Self) -> bool;
 
     /// Returns `true` if the number is even.
     ///
@@ -231,10 +235,14 @@ fn lcm(&self, other: &$T) -> $T {
                 ((*self * *other) / self.gcd(other)).abs()
             }
 
-            /// Returns `true` if the number can be divided by `other` without
-            /// leaving a remainder
+            /// Deprecated, use `is_multiple_of` instead.
+            #[deprecated = "function renamed to `is_multiple_of`"]
+            #[inline]
+            fn divides(&self, other: &$T) -> bool { return self.is_multiple_of(other); }
+
+            /// Returns `true` if the number is a multiple of `other`.
             #[inline]
-            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+            fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
 
             /// Returns `true` if the number is divisible by `2`
             #[inline]
@@ -393,21 +401,26 @@ fn gcd(&self, other: &$T) -> $T {
                 n
             }
 
-            /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+            /// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
             #[inline]
             fn lcm(&self, other: &$T) -> $T {
                 (*self * *other) / self.gcd(other)
             }
 
-            /// Returns `true` if the number can be divided by `other` without leaving a remainder
+            /// Deprecated, use `is_multiple_of` instead.
+            #[deprecated = "function renamed to `is_multiple_of`"]
             #[inline]
-            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+            fn divides(&self, other: &$T) -> bool { return self.is_multiple_of(other); }
 
-            /// Returns `true` if the number is divisible by `2`
+            /// Returns `true` if the number is a multiple of `other`.
+            #[inline]
+            fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
+
+            /// Returns `true` if the number is divisible by `2`.
             #[inline]
             fn is_even(&self) -> bool { self & 1 == 0 }
 
-            /// Returns `true` if the number is not divisible by `2`
+            /// Returns `true` if the number is not divisible by `2`.
             #[inline]
             fn is_odd(&self) -> bool { !self.is_even() }
         }
@@ -449,10 +462,10 @@ fn test_lcm() {
             }
 
             #[test]
-            fn test_divides() {
-                assert!((6 as $T).divides(&(6 as $T)));
-                assert!((6 as $T).divides(&(3 as $T)));
-                assert!((6 as $T).divides(&(1 as $T)));
+            fn test_is_multiple_of() {
+                assert!((6 as $T).is_multiple_of(&(6 as $T)));
+                assert!((6 as $T).is_multiple_of(&(3 as $T)));
+                assert!((6 as $T).is_multiple_of(&(1 as $T)));
             }
 
             #[test]
index a279ede6fa5347d68b85d7251fb3ad20a4b43752..e0f6b4fb9af66a12ccb06e6f4282d12f6ed65890 100644 (file)
@@ -38,13 +38,13 @@ pub struct Ratio<T> {
 
 impl<T: Clone + Integer + PartialOrd>
     Ratio<T> {
-    /// Create a ratio representing the integer `t`.
+    /// Creates a ratio representing the integer `t`.
     #[inline]
     pub fn from_integer(t: T) -> Ratio<T> {
         Ratio::new_raw(t, One::one())
     }
 
-    /// Create a ratio without checking for `denom == 0` or reducing.
+    /// Creates a ratio without checking for `denom == 0` or reducing.
     #[inline]
     pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
         Ratio { numer: numer, denom: denom }
@@ -61,7 +61,7 @@ pub fn new(numer: T, denom: T) -> Ratio<T> {
         ret
     }
 
-    /// Convert to an integer.
+    /// Converts to an integer.
     #[inline]
     pub fn to_integer(&self) -> T {
         self.trunc().numer
@@ -79,7 +79,7 @@ pub fn denom<'a>(&'a self) -> &'a T {
         &self.denom
     }
 
-    /// Return true if the rational number is an integer (denominator is 1).
+    /// Returns true if the rational number is an integer (denominator is 1).
     #[inline]
     pub fn is_integer(&self) -> bool {
         self.denom == One::one()
@@ -103,19 +103,21 @@ fn reduce(&mut self) {
         }
     }
 
-    /// Return a `reduce`d copy of self.
+    /// Returns a `reduce`d copy of self.
     pub fn reduced(&self) -> Ratio<T> {
         let mut ret = self.clone();
         ret.reduce();
         ret
     }
 
-    /// Return the reciprocal
+    /// Returns the reciprocal.
     #[inline]
     pub fn recip(&self) -> Ratio<T> {
         Ratio::new_raw(self.denom.clone(), self.numer.clone())
     }
 
+    /// Rounds towards minus infinity.
+    #[inline]
     pub fn floor(&self) -> Ratio<T> {
         if *self < Zero::zero() {
             Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
@@ -124,6 +126,8 @@ pub fn floor(&self) -> Ratio<T> {
         }
     }
 
+    /// Rounds towards plus infinity.
+    #[inline]
     pub fn ceil(&self) -> Ratio<T> {
         if *self < Zero::zero() {
             Ratio::from_integer(self.numer / self.denom)
@@ -132,8 +136,12 @@ pub fn ceil(&self) -> Ratio<T> {
         }
     }
 
+    /// Rounds to the nearest integer. Rounds half-way cases away from zero.
+    ///
+    /// Note: This function is currently broken and always rounds away from zero.
     #[inline]
     pub fn round(&self) -> Ratio<T> {
+        // FIXME(#15826)
         if *self < Zero::zero() {
             Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
         } else {
@@ -141,18 +149,21 @@ pub fn round(&self) -> Ratio<T> {
         }
     }
 
+    /// Rounds towards zero.
     #[inline]
     pub fn trunc(&self) -> Ratio<T> {
         Ratio::from_integer(self.numer / self.denom)
     }
 
+    ///Returns the fractional part of a number.
+    #[inline]
     pub fn fract(&self) -> Ratio<T> {
         Ratio::new_raw(self.numer % self.denom, self.denom.clone())
     }
 }
 
 impl Ratio<BigInt> {
-    /// Converts a float into a rational number
+    /// Converts a float into a rational number.
     pub fn from_float<T: Float>(f: T) -> Option<BigRational> {
         if !f.is_finite() {
             return None;
@@ -328,7 +339,7 @@ fn to_str_radix(&self, radix: uint) -> String {
 
 impl<T: FromStr + Clone + Integer + PartialOrd>
     FromStr for Ratio<T> {
-    /// Parses `numer/denom` or just `numer`
+    /// Parses `numer/denom` or just `numer`.
     fn from_str(s: &str) -> Option<Ratio<T>> {
         let mut split = s.splitn('/', 1);
 
index c7dca1b93efbda26afbd9af27a4a28d446d5cba1..0cf884eccbcb322676a0f4d2161a4bb7bf17000e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::archive::{Archive, ArchiveConfig, METADATA_FILENAME};
+use super::archive::{Archive, ArchiveBuilder, ArchiveConfig, METADATA_FILENAME};
 use super::rpath;
 use super::rpath::RPathConfig;
 use super::svh::Svh;
@@ -927,6 +927,7 @@ pub fn filename_for_input(sess: &Session,
                 abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
                 abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
                 abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
+                abi::OsDragonfly => (loader::DRAGONFLY_DLL_PREFIX, loader::DRAGONFLY_DLL_SUFFIX),
                 abi::OsiOS => unreachable!(),
             };
             out_filename.with_filename(format!("{}{}{}",
@@ -944,6 +945,7 @@ pub fn filename_for_input(sess: &Session,
                 abi::OsLinux |
                 abi::OsAndroid |
                 abi::OsFreebsd |
+                abi::OsDragonfly |
                 abi::OsiOS => out_filename.clone(),
             }
         }
@@ -983,7 +985,7 @@ fn link_binary_output(sess: &Session,
 
     match crate_type {
         config::CrateTypeRlib => {
-            link_rlib(sess, Some(trans), &obj_filename, &out_filename);
+            link_rlib(sess, Some(trans), &obj_filename, &out_filename).build();
         }
         config::CrateTypeStaticlib => {
             link_staticlib(sess, &obj_filename, &out_filename);
@@ -1019,7 +1021,7 @@ fn archive_search_paths(sess: &Session) -> Vec<Path> {
 fn link_rlib<'a>(sess: &'a Session,
                  trans: Option<&CrateTranslation>, // None == no metadata/bytecode
                  obj_filename: &Path,
-                 out_filename: &Path) -> Archive<'a> {
+                 out_filename: &Path) -> ArchiveBuilder<'a> {
     let handler = &sess.diagnostic().handler;
     let config = ArchiveConfig {
         handler: handler,
@@ -1028,17 +1030,30 @@ fn link_rlib<'a>(sess: &'a Session,
         os: sess.targ_cfg.os,
         maybe_ar_prog: sess.opts.cg.ar.clone()
     };
-    let mut a = Archive::create(config, obj_filename);
+    let mut ab = ArchiveBuilder::create(config);
+    ab.add_file(obj_filename).unwrap();
 
     for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
         match kind {
             cstore::NativeStatic => {
-                a.add_native_library(l.as_slice()).unwrap();
+                ab.add_native_library(l.as_slice()).unwrap();
             }
             cstore::NativeFramework | cstore::NativeUnknown => {}
         }
     }
 
+    // After adding all files to the archive, we need to update the
+    // symbol table of the archive.
+    ab.update_symbols();
+
+    let mut ab = match sess.targ_cfg.os {
+        // For OSX/iOS, we must be careful to update symbols only when adding
+        // object files.  We're about to start adding non-object files, so run
+        // `ar` now to process the object files.
+        abi::OsMacos | abi::OsiOS => ab.build().extend(),
+        _ => ab,
+    };
+
     // Note that it is important that we add all of our non-object "magical
     // files" *after* all of the object files in the archive. The reason for
     // this is as follows:
@@ -1078,7 +1093,7 @@ fn link_rlib<'a>(sess: &'a Session,
                     sess.abort_if_errors();
                 }
             }
-            a.add_file(&metadata, false);
+            ab.add_file(&metadata).unwrap();
             remove(sess, &metadata);
 
             // For LTO purposes, the bytecode of this library is also inserted
@@ -1105,25 +1120,18 @@ fn link_rlib<'a>(sess: &'a Session,
                     sess.abort_if_errors()
                 }
             }
-            a.add_file(&bc_deflated, false);
+            ab.add_file(&bc_deflated).unwrap();
             remove(sess, &bc_deflated);
             if !sess.opts.cg.save_temps &&
                !sess.opts.output_types.contains(&OutputTypeBitcode) {
                 remove(sess, &bc);
             }
-
-            // After adding all files to the archive, we need to update the
-            // symbol table of the archive. This currently dies on OSX (see
-            // #11162), and isn't necessary there anyway
-            match sess.targ_cfg.os {
-                abi::OsMacos | abi::OsiOS => {}
-                _ => { a.update_symbols(); }
-            }
         }
 
         None => {}
     }
-    return a;
+
+    ab
 }
 
 // Create a static archive
@@ -1139,9 +1147,13 @@ fn link_rlib<'a>(sess: &'a Session,
 // link in the metadata object file (and also don't prepare the archive with a
 // metadata file).
 fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
-    let mut a = link_rlib(sess, None, obj_filename, out_filename);
-    a.add_native_library("morestack").unwrap();
-    a.add_native_library("compiler-rt").unwrap();
+    let ab = link_rlib(sess, None, obj_filename, out_filename);
+    let mut ab = match sess.targ_cfg.os {
+        abi::OsMacos | abi::OsiOS => ab.build().extend(),
+        _ => ab,
+    };
+    ab.add_native_library("morestack").unwrap();
+    ab.add_native_library("compiler-rt").unwrap();
 
     let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
     let mut all_native_libs = vec![];
@@ -1155,12 +1167,15 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
                 continue
             }
         };
-        a.add_rlib(&p, name.as_slice(), sess.lto()).unwrap();
+        ab.add_rlib(&p, name.as_slice(), sess.lto()).unwrap();
 
         let native_libs = csearch::get_native_libraries(&sess.cstore, cnum);
         all_native_libs.extend(native_libs.move_iter());
     }
 
+    ab.update_symbols();
+    let _ = ab.build();
+
     if !all_native_libs.is_empty() {
         sess.warn("link against the following native artifacts when linking against \
                   this static library");
@@ -1230,7 +1245,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
     // the symbols
     if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS)
         && (sess.opts.debuginfo != NoDebugInfo) {
-            match Command::new("dsymutil").arg(out_filename).status() {
+            match Command::new("dsymutil").arg(out_filename).output() {
                 Ok(..) => {}
                 Err(e) => {
                     sess.err(format!("failed to run dsymutil: {}", e).as_slice());
@@ -1311,7 +1326,7 @@ fn link_args(cmd: &mut Command,
         cmd.arg("-Wl,--gc-sections");
     }
 
-    if sess.targ_cfg.os == abi::OsLinux {
+    if sess.targ_cfg.os == abi::OsLinux || sess.targ_cfg.os == abi::OsDragonfly {
         // GNU-style linkers will use this to omit linking to libraries which
         // don't actually fulfill any relocations, but only for libraries which
         // follow this flag. Thus, use it before specifying libraries to link to.
@@ -1436,6 +1451,12 @@ fn link_args(cmd: &mut Command,
                   "-L/usr/local/lib/gcc46",
                   "-L/usr/local/lib/gcc44"]);
     }
+    else if sess.targ_cfg.os == abi::OsDragonfly {
+        cmd.args(["-L/usr/local/lib",
+                  "-L/usr/lib/gcc47",
+                  "-L/usr/lib/gcc44"]);
+    }
+
 
     // FIXME (#2397): At some point we want to rpath our guesses as to
     // where extern libraries might live, based on the
index 8b4fcb10907b22eafd71c8612b4a2776936c9b68..f4309d9e51b56f7ae14c84349c09fb896aa0fd94 100644 (file)
@@ -390,12 +390,13 @@ pub fn default_lib_output() -> CrateType {
 
 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let tos = match sess.targ_cfg.os {
-        abi::OsWin32 =>   InternedString::new("win32"),
-        abi::OsMacos =>   InternedString::new("macos"),
-        abi::OsLinux =>   InternedString::new("linux"),
-        abi::OsAndroid => InternedString::new("android"),
-        abi::OsFreebsd => InternedString::new("freebsd"),
-        abi::OsiOS =>     InternedString::new("ios"),
+        abi::OsWin32 =>     InternedString::new("win32"),
+        abi::OsMacos =>     InternedString::new("macos"),
+        abi::OsLinux =>     InternedString::new("linux"),
+        abi::OsAndroid =>   InternedString::new("android"),
+        abi::OsFreebsd =>   InternedString::new("freebsd"),
+        abi::OsDragonfly => InternedString::new("dragonfly"),
+        abi::OsiOS =>       InternedString::new("ios"),
     };
 
     // ARM is bi-endian, however using NDK seems to default
@@ -451,13 +452,14 @@ pub fn get_os(triple: &str) -> Option<abi::Os> {
     None
 }
 static os_names : &'static [(&'static str, abi::Os)] = &[
-    ("mingw32", abi::OsWin32),
-    ("win32",   abi::OsWin32),
-    ("darwin",  abi::OsMacos),
-    ("android", abi::OsAndroid),
-    ("linux",   abi::OsLinux),
-    ("freebsd", abi::OsFreebsd),
-    ("ios",     abi::OsiOS)];
+    ("mingw32",   abi::OsWin32),
+    ("win32",     abi::OsWin32),
+    ("darwin",    abi::OsMacos),
+    ("android",   abi::OsAndroid),
+    ("linux",     abi::OsLinux),
+    ("freebsd",   abi::OsFreebsd),
+    ("dragonfly", abi::OsDragonfly),
+    ("ios",       abi::OsiOS)];
 
 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
     for &(arch, abi) in architecture_abis.iter() {
index 9f15c9a9b3fa0dd1d6d3c9a9fe82d2d0d2a75627..99855c7345cb4e5269a35959944a4edc71e66389 100644 (file)
@@ -69,6 +69,8 @@
     ("rustc_diagnostic_macros", Active),
     ("unboxed_closures", Active),
 
+    // if you change this list without updating src/doc/rust.md, cmr will be sad
+
     // A temporary feature gate used to enable parser extensions needed
     // to bootstrap fix for #5723.
     ("issue_5723_bootstrap", Active),
index 2a7f7e8c54dd1f66bfb07e10df12e630a06b1bad..82040f141593e7575a1ed9224a5f5757e8835903 100644 (file)
@@ -48,6 +48,9 @@
 #[phase(plugin, link)] extern crate log;
 #[phase(plugin, link)] extern crate syntax;
 
+#[cfg(test)]
+extern crate test;
+
 mod diagnostics;
 
 pub mod back {
@@ -129,6 +132,7 @@ pub mod util {
 
     pub mod common;
     pub mod ppaux;
+    pub mod io;
     pub mod nodemap;
 }
 
index 3f4f51236997191403f8add494035fcf0a408d68..1667f2b6d5f0a7ec9cc17f1cc5e6f3ec27bc4661 100644 (file)
@@ -358,9 +358,9 @@ fn check_ty(cx: &Context, ty: &ast::Ty) {
                         def::DefTy(def_id) => {
                             if !adt::is_ffi_safe(cx.tcx, def_id) {
                                 cx.span_lint(CTYPES, ty.span,
-                                             "found enum type without foreign-function-safe \
-                                              representation annotation in foreign module");
-                                // hmm... this message could be more helpful
+                                             "found enum type without foreign-function-safe
+                                             representation annotation in foreign module, consider \
+                                             adding a #[repr(...)] attribute to the enumeration");
                             }
                         }
                         _ => ()
index 8896a068baa76b992f80bf708cd8d4ab59371f05..9224647bc798b19eeb187f3e51a9c0537a564a5b 100644 (file)
@@ -31,7 +31,7 @@
 #![macro_escape]
 
 use std::hash;
-use std::ascii::StrAsciiExt;
+use std::ascii::AsciiExt;
 use syntax::codemap::Span;
 use syntax::visit::FnKind;
 use syntax::ast;
index 6665e913e192fbd0b0ca71bedec63499c9c22bcf..dbda4f58d960f91fc721e205ccdc5431acf6dc87 100644 (file)
@@ -26,6 +26,7 @@
 use middle::typeck;
 use middle::stability;
 use middle;
+use util::io::SeekableMemWriter;
 use util::nodemap::{NodeMap, NodeSet};
 
 use serialize::Encodable;
@@ -33,7 +34,6 @@
 use std::gc::Gc;
 use std::hash::Hash;
 use std::hash;
-use std::io::MemWriter;
 use std::mem;
 use std::collections::HashMap;
 use syntax::abi;
@@ -61,7 +61,7 @@ pub enum InlinedItemRef<'a> {
     IIForeignRef(&'a ast::ForeignItem)
 }
 
-pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
 
 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
                                   ebml_w: &mut Encoder,
@@ -1407,7 +1407,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
 // Path and definition ID indexing
 
 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
-                         write_fn: |&mut MemWriter, &T|) {
+                         write_fn: |&mut SeekableMemWriter, &T|) {
     let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
     for elt in index.move_iter() {
         let h = hash::hash(&elt.val) as uint;
@@ -1424,7 +1424,7 @@ fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
             ebml_w.start_tag(tag_index_buckets_bucket_elt);
             assert!(elt.pos < 0xffff_ffff);
             {
-                let wr: &mut MemWriter = ebml_w.writer;
+                let wr: &mut SeekableMemWriter = ebml_w.writer;
                 wr.write_be_u32(elt.pos as u32);
             }
             write_fn(ebml_w.writer, &elt.val);
@@ -1436,15 +1436,15 @@ fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
     ebml_w.start_tag(tag_index_table);
     for pos in bucket_locs.iter() {
         assert!(*pos < 0xffff_ffff);
-        let wr: &mut MemWriter = ebml_w.writer;
+        let wr: &mut SeekableMemWriter = ebml_w.writer;
         wr.write_be_u32(*pos as u32);
     }
     ebml_w.end_tag();
     ebml_w.end_tag();
 }
 
-fn write_i64(writer: &mut MemWriter, &n: &i64) {
-    let wr: &mut MemWriter = writer;
+fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
+    let wr: &mut SeekableMemWriter = writer;
     assert!(n < 0x7fff_ffff);
     wr.write_be_u32(n as u32);
 }
@@ -1545,14 +1545,14 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
 
                 ebml_w.start_tag(tag_lang_items_item_id);
                 {
-                    let wr: &mut MemWriter = ebml_w.writer;
+                    let wr: &mut SeekableMemWriter = ebml_w.writer;
                     wr.write_be_u32(i as u32);
                 }
                 ebml_w.end_tag();   // tag_lang_items_item_id
 
                 ebml_w.start_tag(tag_lang_items_item_node_id);
                 {
-                    let wr: &mut MemWriter = ebml_w.writer;
+                    let wr: &mut SeekableMemWriter = ebml_w.writer;
                     wr.write_be_u32(id.node as u32);
                 }
                 ebml_w.end_tag();   // tag_lang_items_item_node_id
@@ -1824,12 +1824,12 @@ fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
       0, 0, 0, 1 ];
 
 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
-    let mut wr = MemWriter::new();
+    let mut wr = SeekableMemWriter::new();
     encode_metadata_inner(&mut wr, parms, krate);
     wr.unwrap().move_iter().collect()
 }
 
-fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
+fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate: &Crate) {
     struct Stats {
         attr_bytes: u64,
         dep_bytes: u64,
@@ -1982,7 +1982,7 @@ struct Stats {
 
 // Get the encoded string for a type
 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
-    let mut wr = MemWriter::new();
+    let mut wr = SeekableMemWriter::new();
     tyencode::enc_ty(&mut wr, &tyencode::ctxt {
         diag: tcx.sess.diagnostic(),
         ds: def_to_string,
index 1811c4f8612f01560e8678b2451e7f5c4a33d825..4b9dd1003ec604ec6827ca67abbccd1b527d2be8 100644 (file)
 pub static FREEBSD_DLL_PREFIX: &'static str = "lib";
 pub static FREEBSD_DLL_SUFFIX: &'static str = ".so";
 
+pub static DRAGONFLY_DLL_PREFIX: &'static str = "lib";
+pub static DRAGONFLY_DLL_SUFFIX: &'static str = ".so";
+
 pub static ANDROID_DLL_PREFIX: &'static str = "lib";
 pub static ANDROID_DLL_SUFFIX: &'static str = ".so";
 
@@ -617,6 +620,7 @@ fn dylibname(&self) -> Option<(&'static str, &'static str)> {
             abi::OsLinux => Some((LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX)),
             abi::OsAndroid => Some((ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX)),
             abi::OsFreebsd => Some((FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX)),
+            abi::OsDragonfly => Some((DRAGONFLY_DLL_PREFIX, DRAGONFLY_DLL_SUFFIX)),
             abi::OsiOS => None,
         }
     }
@@ -823,7 +827,8 @@ pub fn meta_section_name(os: abi::Os) -> Option<&'static str> {
         abi::OsWin32 => Some(".note.rustc"),
         abi::OsLinux => Some(".note.rustc"),
         abi::OsAndroid => Some(".note.rustc"),
-        abi::OsFreebsd => Some(".note.rustc")
+        abi::OsFreebsd => Some(".note.rustc"),
+        abi::OsDragonfly => Some(".note.rustc"),
     }
 }
 
@@ -834,7 +839,8 @@ pub fn read_meta_section_name(os: abi::Os) -> &'static str {
         abi::OsWin32 => ".note.rustc",
         abi::OsLinux => ".note.rustc",
         abi::OsAndroid => ".note.rustc",
-        abi::OsFreebsd => ".note.rustc"
+        abi::OsFreebsd => ".note.rustc",
+        abi::OsDragonfly => ".note.rustc"
     }
 }
 
index 15e4e85ddb7114323b884f90f3c4bf057642330a..f301dc3760db60200a76df86f24de4b34f83cbef 100644 (file)
@@ -15,7 +15,6 @@
 
 use std::cell::RefCell;
 use std::collections::HashMap;
-use std::io::MemWriter;
 
 use middle::subst;
 use middle::subst::VecPerParamSpace;
@@ -28,6 +27,8 @@
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token;
 
+use util::io::SeekableMemWriter;
+
 macro_rules! mywrite( ($($arg:tt)*) => ({ write!($($arg)*); }) )
 
 pub struct ctxt<'a> {
@@ -48,7 +49,7 @@ pub struct ty_abbrev {
 
 pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
 
-pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
+pub fn enc_ty(w: &mut SeekableMemWriter, cx: &ctxt, t: ty::t) {
     match cx.abbrevs.borrow_mut().find(&t) {
         Some(a) => { w.write(a.s.as_bytes()); return; }
         None => {}
@@ -72,19 +73,19 @@ fn estimate_sz(u: u64) -> u64 {
     }
 }
 
-fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
+fn enc_mutability(w: &mut SeekableMemWriter, mt: ast::Mutability) {
     match mt {
         MutImmutable => (),
         MutMutable => mywrite!(w, "m"),
     }
 }
 
-fn enc_mt(w: &mut MemWriter, cx: &ctxt, mt: ty::mt) {
+fn enc_mt(w: &mut SeekableMemWriter, cx: &ctxt, mt: ty::mt) {
     enc_mutability(w, mt.mutbl);
     enc_ty(w, cx, mt.ty);
 }
 
-fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
+fn enc_opt<T>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: |&mut SeekableMemWriter, T|) {
     match t {
         None => mywrite!(w, "n"),
         Some(v) => {
@@ -94,10 +95,10 @@ fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
     }
 }
 
-fn enc_vec_per_param_space<T>(w: &mut MemWriter,
+fn enc_vec_per_param_space<T>(w: &mut SeekableMemWriter,
                               cx: &ctxt,
                               v: &VecPerParamSpace<T>,
-                              op: |&mut MemWriter, &ctxt, &T|) {
+                              op: |&mut SeekableMemWriter, &ctxt, &T|) {
     for &space in subst::ParamSpace::all().iter() {
         mywrite!(w, "[");
         for t in v.get_slice(space).iter() {
@@ -107,13 +108,13 @@ fn enc_vec_per_param_space<T>(w: &mut MemWriter,
     }
 }
 
-pub fn enc_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::Substs) {
+pub fn enc_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Substs) {
     enc_region_substs(w, cx, &substs.regions);
     enc_vec_per_param_space(w, cx, &substs.types,
                             |w, cx, &ty| enc_ty(w, cx, ty));
 }
 
-fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
+fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
     match *substs {
         subst::ErasedRegions => {
             mywrite!(w, "e");
@@ -126,7 +127,7 @@ fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts)
     }
 }
 
-fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
+fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
     match r {
         ty::ReLateBound(id, br) => {
             mywrite!(w, "b[{}|", id);
@@ -161,7 +162,7 @@ fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
     }
 }
 
-fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
+fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
     match br {
         ty::BrAnon(idx) => {
             mywrite!(w, "a{}|", idx);
@@ -177,12 +178,12 @@ fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
     }
 }
 
-pub fn enc_trait_ref(w: &mut MemWriter, cx: &ctxt, s: &ty::TraitRef) {
+pub fn enc_trait_ref(w: &mut SeekableMemWriter, cx: &ctxt, s: &ty::TraitRef) {
     mywrite!(w, "{}|", (cx.ds)(s.def_id));
     enc_substs(w, cx, &s.substs);
 }
 
-pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
+pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore) {
     match s {
         ty::UniqTraitStore => mywrite!(w, "~"),
         ty::RegionTraitStore(re, m) => {
@@ -193,7 +194,7 @@ pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
     }
 }
 
-fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
+fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
     match *st {
         ty::ty_nil => mywrite!(w, "n"),
         ty::ty_bot => mywrite!(w, "z"),
@@ -293,33 +294,33 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
     }
 }
 
-fn enc_fn_style(w: &mut MemWriter, p: FnStyle) {
+fn enc_fn_style(w: &mut SeekableMemWriter, p: FnStyle) {
     match p {
         NormalFn => mywrite!(w, "n"),
         UnsafeFn => mywrite!(w, "u"),
     }
 }
 
-fn enc_abi(w: &mut MemWriter, abi: Abi) {
+fn enc_abi(w: &mut SeekableMemWriter, abi: Abi) {
     mywrite!(w, "[");
     mywrite!(w, "{}", abi.name());
     mywrite!(w, "]")
 }
 
-fn enc_onceness(w: &mut MemWriter, o: Onceness) {
+fn enc_onceness(w: &mut SeekableMemWriter, o: Onceness) {
     match o {
         Once => mywrite!(w, "o"),
         Many => mywrite!(w, "m")
     }
 }
 
-pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
+pub fn enc_bare_fn_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
     enc_fn_style(w, ft.fn_style);
     enc_abi(w, ft.abi);
     enc_fn_sig(w, cx, &ft.sig);
 }
 
-pub fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
+pub fn enc_closure_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
     enc_fn_style(w, ft.fn_style);
     enc_onceness(w, ft.onceness);
     enc_trait_store(w, cx, ft.store);
@@ -330,7 +331,7 @@ pub fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
     enc_abi(w, ft.abi);
 }
 
-fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
+fn enc_fn_sig(w: &mut SeekableMemWriter, cx: &ctxt, fsig: &ty::FnSig) {
     mywrite!(w, "[{}|", fsig.binder_id);
     for ty in fsig.inputs.iter() {
         enc_ty(w, cx, *ty);
@@ -344,7 +345,7 @@ fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
     enc_ty(w, cx, fsig.output);
 }
 
-fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
+fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
     for bound in bs.builtin_bounds.iter() {
         match bound {
             ty::BoundSend => mywrite!(w, "S"),
@@ -363,7 +364,7 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
     mywrite!(w, ".");
 }
 
-pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
+pub fn enc_type_param_def(w: &mut SeekableMemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
     mywrite!(w, "{}:{}|{}|{}|",
              token::get_ident(v.ident), (cx.ds)(v.def_id),
              v.space.to_uint(), v.index);
index 722715405bce4ec08c06e69f070ac309f712f1ba..9a587dd77418259b7000b976386c77c0cbdfdd23 100644 (file)
@@ -28,6 +28,7 @@
 use middle::subst::VecPerParamSpace;
 use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
 use middle::{ty, typeck};
+use util::io::SeekableMemWriter;
 use util::ppaux::ty_to_string;
 
 use syntax::{ast, ast_map, ast_util, codemap, fold};
@@ -39,7 +40,6 @@
 
 use libc;
 use std::io::Seek;
-use std::io::MemWriter;
 use std::mem;
 use std::gc::GC;
 
@@ -73,7 +73,7 @@ trait tr_intern {
     fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
 }
 
-pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
+pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
 
 // ______________________________________________________________________
 // Top-level methods.
@@ -1573,10 +1573,8 @@ fn mk_ctxt() -> parse::ParseSess {
 
 #[cfg(test)]
 fn roundtrip(in_item: Option<Gc<ast::Item>>) {
-    use std::io::MemWriter;
-
     let in_item = in_item.unwrap();
-    let mut wr = MemWriter::new();
+    let mut wr = SeekableMemWriter::new();
     {
         let mut ebml_w = writer::Encoder::new(&mut wr);
         encode_item_ast(&mut ebml_w, in_item);
index 4f6885f05ed16c87176f204397e514337ca3b484..9cd46067c107b3b5a7eafa140a7a75e16f26f03e 100644 (file)
@@ -333,32 +333,37 @@ fn expr(&mut self, expr: Gc<ast::Expr>, pred: CFGIndex) -> CFGIndex {
                 //    [discr]
                 //       |
                 //       v 2
-                //    [guard1]
+                //    [cond1]
                 //      /  \
                 //     |    \
-                //     v 3  |
-                //  [pat1]  |
-                //     |
-                //     v 4  |
-                // [body1]  v
-                //     |  [guard2]
-                //     |    /   \
-                //     | [body2] \
-                //     |    |   ...
-                //     |    |    |
-                //     v 5  v    v
-                //   [....expr....]
+                //     v 3   \
+                //  [pat1]    \
+                //     |       |
+                //     v 4     |
+                //  [guard1]   |
+                //     |       |
+                //     |       |
+                //     v 5     v
+                //  [body1]  [cond2]
+                //     |      /  \
+                //     |    ...  ...
+                //     |     |    |
+                //     v 6   v    v
+                //  [.....expr.....]
                 //
                 let discr_exit = self.expr(discr.clone(), pred);         // 1
 
                 let expr_exit = self.add_node(expr.id, []);
-                let mut guard_exit = discr_exit;
+                let mut cond_exit = discr_exit;
                 for arm in arms.iter() {
-                    guard_exit = self.opt_expr(arm.guard, guard_exit);   // 2
+                    cond_exit = self.add_dummy_node([cond_exit]);        // 2
                     let pats_exit = self.pats_any(arm.pats.as_slice(),
-                                                  guard_exit);           // 3
-                    let body_exit = self.expr(arm.body.clone(), pats_exit); // 4
-                    self.add_contained_edge(body_exit, expr_exit);       // 5
+                                                  cond_exit);            // 3
+                    let guard_exit = self.opt_expr(arm.guard,
+                                                   pats_exit);           // 4
+                    let body_exit = self.expr(arm.body.clone(),
+                                              guard_exit);               // 5
+                    self.add_contained_edge(body_exit, expr_exit);       // 6
                 }
                 expr_exit
             }
index e458b82f03634359ef1f561fd1ff5f5c58d83dbb..4d10676a5892ee8187e1eaacddb49c803dc77455 100644 (file)
 use middle::const_eval::{compare_const_vals, const_bool, const_float, const_nil, const_val};
 use middle::const_eval::{const_expr_to_pat, eval_const_expr, lookup_const_by_id};
 use middle::def::*;
+use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
+use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
+use middle::expr_use_visitor::{WriteAndRead};
+use middle::mem_categorization::cmt;
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
@@ -143,7 +147,16 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
                                                 arm.pats.as_slice());
             }
 
-            // Second, check for unreachable arms.
+            // Second, if there is a guard on each arm, make sure it isn't
+            // assigning or borrowing anything mutably.
+            for arm in arms.iter() {
+                match arm.guard {
+                    Some(guard) => check_for_mutation_in_guard(cx, &*guard),
+                    None => {}
+                }
+            }
+
+            // Third, check for unreachable arms.
             check_arms(cx, arms.as_slice());
 
             // Finally, check if the whole match expression is exhaustive.
@@ -903,3 +916,53 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
         });
     }
 }
+
+/// Ensures that a pattern guard doesn't borrow by mutable reference or
+/// assign.
+fn check_for_mutation_in_guard<'a>(cx: &'a MatchCheckCtxt<'a>, guard: &Expr) {
+    let mut checker = MutationChecker {
+        cx: cx,
+    };
+    let mut visitor = ExprUseVisitor::new(&mut checker, checker.cx.tcx);
+    visitor.walk_expr(guard);
+}
+
+struct MutationChecker<'a> {
+    cx: &'a MatchCheckCtxt<'a>,
+}
+
+impl<'a> Delegate for MutationChecker<'a> {
+    fn consume(&mut self, _: NodeId, _: Span, _: cmt, _: ConsumeMode) {}
+    fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {}
+    fn borrow(&mut self,
+              _: NodeId,
+              span: Span,
+              _: cmt,
+              _: Region,
+              kind: BorrowKind,
+              _: LoanCause) {
+        match kind {
+            MutBorrow => {
+                self.cx
+                    .tcx
+                    .sess
+                    .span_err(span,
+                              "cannot mutably borrow in a pattern guard")
+            }
+            ImmBorrow | UniqueImmBorrow => {}
+        }
+    }
+    fn decl_without_init(&mut self, _: NodeId, _: Span) {}
+    fn mutate(&mut self, _: NodeId, span: Span, _: cmt, mode: MutateMode) {
+        match mode {
+            JustWrite | WriteAndRead => {
+                self.cx
+                    .tcx
+                    .sess
+                    .span_err(span, "cannot assign in a pattern guard")
+            }
+            Init => {}
+        }
+    }
+}
+
index 7995317d49fd160c160a3fb245f82c7d7a7cc4c5..605811555a16819b70d69d99a42b614b4c6a0560 100644 (file)
@@ -292,7 +292,7 @@ fn select_from_expr(&mut self, expr: &ast::Expr) {
         self.walk_expr(expr)
     }
 
-    fn walk_expr(&mut self, expr: &ast::Expr) {
+    pub fn walk_expr(&mut self, expr: &ast::Expr) {
         debug!("walk_expr(expr={})", expr.repr(self.tcx()));
 
         self.walk_adjustment(expr);
index 5433923441a7b912b1c4a30d5cb09bf0a267afe0..ea301784c930e0966412a5ae13b8c2bad6d1ac16 100644 (file)
@@ -1235,7 +1235,8 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
                        output_type: ty::t,
                        param_substs: &'a param_substs,
                        sp: Option<Span>,
-                       block_arena: &'a TypedArena<Block<'a>>)
+                       block_arena: &'a TypedArena<Block<'a>>,
+                       handle_items: HandleItemsFlag)
                        -> FunctionContext<'a> {
     param_substs.validate();
 
@@ -1268,7 +1269,8 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
           block_arena: block_arena,
           ccx: ccx,
           debug_context: debug_context,
-          scopes: RefCell::new(Vec::new())
+          scopes: RefCell::new(Vec::new()),
+          handle_items: handle_items,
     };
 
     if has_env {
@@ -1579,7 +1581,8 @@ pub fn trans_closure(ccx: &CrateContext,
                      abi: Abi,
                      has_env: bool,
                      is_unboxed_closure: IsUnboxedClosureFlag,
-                     maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>) {
+                     maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>,
+                     handle_items: HandleItemsFlag) {
     ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
 
     let _icx = push_ctxt("trans_closure");
@@ -1596,7 +1599,8 @@ pub fn trans_closure(ccx: &CrateContext,
                           output_type,
                           param_substs,
                           Some(body.span),
-                          &arena);
+                          &arena,
+                          handle_items);
     let mut bcx = init_function(&fcx, false, output_type);
 
     // cleanup scope for the incoming arguments
@@ -1698,7 +1702,8 @@ pub fn trans_fn(ccx: &CrateContext,
                 llfndecl: ValueRef,
                 param_substs: &param_substs,
                 id: ast::NodeId,
-                attrs: &[ast::Attribute]) {
+                attrs: &[ast::Attribute],
+                handle_items: HandleItemsFlag) {
     let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_string(id).to_string());
     debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
     let _icx = push_ctxt("trans_fn");
@@ -1718,7 +1723,8 @@ pub fn trans_fn(ccx: &CrateContext,
                   abi,
                   false,
                   NotUnboxedClosure,
-                  |bcx| bcx);
+                  |bcx| bcx,
+                  handle_items);
 }
 
 pub fn trans_enum_variant(ccx: &CrateContext,
@@ -1824,7 +1830,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
-                          param_substs, None, &arena);
+                          param_substs, None, &arena, TranslateItems);
     let bcx = init_function(&fcx, false, result_ty);
 
     let arg_tys = ty::ty_fn_args(ctor_ty);
@@ -1925,7 +1931,8 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                      llfn,
                      &param_substs::empty(),
                      item.id,
-                     item.attrs.as_slice());
+                     item.attrs.as_slice(),
+                     TranslateItems);
         } else {
             // Be sure to travel more than just one layer deep to catch nested
             // items in blocks and such.
index e2ad8b4fd4680a6891587f6b76d42b3a23181707..f186af48321c3d8dd64db0769811eb5e7ca8bfa9 100644 (file)
@@ -339,7 +339,8 @@ pub fn trans_unboxing_shim(bcx: &Block,
                           return_type,
                           &empty_param_substs,
                           None,
-                          &block_arena);
+                          &block_arena,
+                          TranslateItems);
     let mut bcx = init_function(&fcx, false, return_type);
 
     // Create the substituted versions of the self type.
@@ -775,6 +776,8 @@ pub fn trans_call_inner<'a>(
     // We trans them in place in `trans_intrinsic_call`
     assert!(abi != synabi::RustIntrinsic);
 
+    let is_rust_fn = abi == synabi::Rust || abi == synabi::RustCall;
+
     // Generate a location to store the result. If the user does
     // not care about the result, just make a stack slot.
     let opt_llretslot = match dest {
@@ -783,7 +786,9 @@ pub fn trans_call_inner<'a>(
             None
         }
         Some(expr::SaveIn(dst)) => Some(dst),
-        Some(expr::Ignore) => {
+        Some(expr::Ignore) if !is_rust_fn ||
+                type_of::return_uses_outptr(ccx, ret_ty) ||
+                ty::type_needs_drop(bcx.tcx(), ret_ty) => {
             if !type_is_zero_size(ccx, ret_ty) {
                 Some(alloc_ty(bcx, ret_ty, "__llret"))
             } else {
@@ -791,6 +796,7 @@ pub fn trans_call_inner<'a>(
                 Some(C_undef(llty.ptr_to()))
             }
         }
+        Some(expr::Ignore) => None
     };
 
     let mut llresult = unsafe {
@@ -803,7 +809,7 @@ pub fn trans_call_inner<'a>(
     // and done, either the return value of the function will have been
     // written in opt_llretslot (if it is Some) or `llresult` will be
     // set appropriately (otherwise).
-    if abi == synabi::Rust || abi == synabi::RustCall {
+    if is_rust_fn {
         let mut llargs = Vec::new();
 
         // Push the out-pointer if we use an out-pointer for this
@@ -878,15 +884,13 @@ pub fn trans_call_inner<'a>(
 
     // If the caller doesn't care about the result of this fn call,
     // drop the temporary slot we made.
-    match dest {
-        None => {
-            assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
-        }
-        Some(expr::Ignore) => {
+    match (dest, opt_llretslot) {
+        (Some(expr::Ignore), Some(llretslot)) => {
             // drop the value if it is not being saved.
-            bcx = glue::drop_ty(bcx, opt_llretslot.unwrap(), ret_ty);
+            bcx = glue::drop_ty(bcx, llretslot, ret_ty);
+            call_lifetime_end(bcx, llretslot);
         }
-        Some(expr::SaveIn(_)) => { }
+        _ => {}
     }
 
     if ty::type_is_bot(ret_ty) {
index a65d208d4d2872c674e0dd5f6622f33af3d08f98..98b2ebb70f3cb211c732c68810d8cadb454bd914 100644 (file)
@@ -394,7 +394,8 @@ pub fn trans_expr_fn<'a>(
                   ty::ty_fn_abi(fty),
                   true,
                   NotUnboxedClosure,
-                  |bcx| load_environment(bcx, cdata_ty, &freevars, store));
+                  |bcx| load_environment(bcx, cdata_ty, &freevars, store),
+                  bcx.fcx.handle_items);
     fill_fn_pair(bcx, dest_addr, llfn, llbox);
     bcx
 }
@@ -486,7 +487,8 @@ pub fn trans_unboxed_closure<'a>(
                   ty::ty_fn_abi(function_type),
                   true,
                   IsUnboxedClosure,
-                  |bcx| load_unboxed_closure_environment(bcx, freevars_ptr));
+                  |bcx| load_unboxed_closure_environment(bcx, freevars_ptr),
+                  bcx.fcx.handle_items);
 
     // Don't hoist this to the top of the function. It's perfectly legitimate
     // to have a zero-size unboxed closure (in which case dest will be
@@ -573,7 +575,7 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext,
     let arena = TypedArena::new();
     let empty_param_substs = param_substs::empty();
     let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output,
-                          &empty_param_substs, None, &arena);
+                          &empty_param_substs, None, &arena, TranslateItems);
     let bcx = init_function(&fcx, true, f.sig.output);
 
     let args = create_datums_for_fn_args(&fcx,
index 320e291e928653ec48a6147ba7fba4ffef2bd039..71ddc2e40459c241ff48727876e23d99e7ac98b0 100644 (file)
@@ -221,6 +221,12 @@ fn substp(&self, tcx: &ty::ctxt, substs: &param_substs) -> T {
 pub type RvalueDatum = datum::Datum<datum::Rvalue>;
 pub type LvalueDatum = datum::Datum<datum::Lvalue>;
 
+#[deriving(Clone, Eq, PartialEq)]
+pub enum HandleItemsFlag {
+    IgnoreItems,
+    TranslateItems,
+}
+
 // Function context.  Every LLVM function we create will have one of
 // these.
 pub struct FunctionContext<'a> {
@@ -289,6 +295,9 @@ pub struct FunctionContext<'a> {
 
     // Cleanup scopes.
     pub scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
+
+    // How to handle items encountered during translation of this function.
+    pub handle_items: HandleItemsFlag,
 }
 
 impl<'a> FunctionContext<'a> {
index f3457f3b0ae06ff49be2480027d8cb8914c00587..bb528790314da512fe2dae3a4234d58b3ad2a1a9 100644 (file)
@@ -121,10 +121,6 @@ pub struct CrateContext {
     /// Holds the LLVM values for closure IDs.
     pub unboxed_closure_vals: RefCell<DefIdMap<ValueRef>>,
 
-    /// Set when at least one function uses GC. Needed so that
-    /// decl_gc_metadata knows whether to link to the module metadata, which
-    /// is not emitted by LLVM's GC pass when no functions use GC.
-    pub uses_gc: bool,
     pub dbg_cx: Option<debuginfo::CrateDebugContext>,
 
     pub eh_personality: RefCell<Option<ValueRef>>,
@@ -230,7 +226,6 @@ pub fn new(name: &str,
                 opaque_vec_type: Type::from_ref(ptr::mut_null()),
                 builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
                 unboxed_closure_vals: RefCell::new(DefIdMap::new()),
-                uses_gc: false,
                 dbg_cx: dbg_cx,
                 eh_personality: RefCell::new(None),
                 intrinsics: RefCell::new(HashMap::new()),
index d8a8cc1c561a902178a4d486bcb16f29115db5f2..dd8fe5e9303a56145601274cdb087f4af69652d1 100644 (file)
@@ -68,7 +68,12 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>,
                         debuginfo::create_local_var_metadata(bcx, &**local);
                     }
                 }
-                ast::DeclItem(ref i) => trans_item(cx.fcx.ccx, &**i)
+                ast::DeclItem(ref i) => {
+                    match fcx.handle_items {
+                        TranslateItems => trans_item(cx.fcx.ccx, &**i),
+                        IgnoreItems => {}
+                    }
+                }
             }
         }
         ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
index f305ae90d46af69f9ed01dfe2a4de098257eccd3..cb46d62fca9e9f56b81fdff0e432981f16ab4cf0 100644 (file)
@@ -601,7 +601,8 @@ fn build_rust_fn(ccx: &CrateContext,
 
         let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
         base::set_llvm_fn_attrs(attrs, llfn);
-        base::trans_fn(ccx, decl, body, llfn, &param_substs::empty(), id, []);
+        base::trans_fn(ccx, decl, body, llfn, &param_substs::empty(), id, [],
+                       TranslateItems);
         llfn
     }
 
index 5c978d505cb768e61c402fb5c5555536e45d159f..40288a33930e5ebdb96131d92b2d24a9490bd1fd 100644 (file)
@@ -468,7 +468,7 @@ fn make_generic_glue(ccx: &CrateContext,
     let arena = TypedArena::new();
     let empty_param_substs = param_substs::empty();
     let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(),
-                          &empty_param_substs, None, &arena);
+                          &empty_param_substs, None, &arena, TranslateItems);
 
     let bcx = init_function(&fcx, false, ty::mk_nil());
 
index bf39f3a6aa385842d1d2a838aafe61dcbffa9648..877dd647c3b20bb32eb05fd46c96585e7984ca7d 100644 (file)
@@ -133,7 +133,7 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
           if unparameterized {
               let llfn = get_item_val(ccx, mth.id);
                 trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), llfn,
-                       &param_substs::empty(), mth.id, []);
+                       &param_substs::empty(), mth.id, [], TranslateItems);
           }
           local_def(mth.id)
         }
index 53f89c9d8b879ccc038ef2953dfa76e8655ce427..4e6250883ebf09809dc7083eaa2c750db380821d 100644 (file)
@@ -75,7 +75,8 @@ pub fn trans_impl(ccx: &CrateContext,
                      llfn,
                      &param_substs::empty(),
                      method.id,
-                     []);
+                     [],
+                     TranslateItems);
         } else {
             let mut v = TransItemVisitor{ ccx: ccx };
             visit::walk_method_helper(&mut v, &**method, ());
index dac3b6bd8eee47bfdff7b296240f667a4797d0b5..986d3328f2c3a7a97f8ab94660909cfd54cb9530 100644 (file)
@@ -149,7 +149,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
               } => {
                   let d = mk_lldecl();
                   set_llvm_fn_attrs(i.attrs.as_slice(), d);
-                  trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, []);
+                  trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, [],
+                           IgnoreItems);
                   d
               }
               _ => {
@@ -181,7 +182,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeMethod(mth) => {
             let d = mk_lldecl();
             set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-            trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, []);
+            trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, [],
+                     IgnoreItems);
             d
         }
         ast_map::NodeTraitMethod(method) => {
@@ -190,7 +192,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                     let d = mk_lldecl();
                     set_llvm_fn_attrs(mth.attrs.as_slice(), d);
                     trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
-                             &psubsts, mth.id, []);
+                             &psubsts, mth.id, [], IgnoreItems);
                     d
                 }
                 _ => {
index 7d8700b9426091e761d8388ec3e8f8552ac749cb..eb0d77da5519fbc389e4c4376adda48282ca13f3 100644 (file)
@@ -312,7 +312,7 @@ pub fn visit_ty(&mut self, t: ty::t) {
                 let empty_param_substs = param_substs::empty();
                 let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
                                       ty::mk_u64(), &empty_param_substs,
-                                      None, &arena);
+                                      None, &arena, TranslateItems);
                 let bcx = init_function(&fcx, false, ty::mk_u64());
 
                 // we know the return type of llfdecl is an int here, so
index d202e61abf332e1981014763a92bf524db184f7d..5e7426f3ae749ccddeba3f06a56c000c71409e5b 100644 (file)
@@ -877,6 +877,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 }
             }
             ast::TyFixedLengthVec(ty, e) => {
+                typeck::write_ty_to_tcx(tcx, e.id, ty::mk_uint());
                 match const_eval::eval_const_expr_partial(tcx, &*e) {
                     Ok(ref r) => {
                         match *r {
index 08a26eefa227364987d9c79acb747ce7e0e10bb0..bbb6e162ecb992e9ff7ebabbbe9976dc074f047d 100644 (file)
@@ -430,6 +430,18 @@ fn visit_block(&mut self, b: &ast::Block, _: ()) {
         self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
     }
 
+    // Since an expr occurs as part of the type fixed size arrays we
+    // need to record the type for that node
+    fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
+        match t.node {
+            ast::TyFixedLengthVec(ref ty, ref count_expr) => {
+                self.visit_ty(&**ty, ());
+                check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
+            }
+            _ => visit::walk_ty(self, t, ())
+        }
+    }
+
     // Don't descend into fns and items
     fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
                 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
@@ -3444,6 +3456,12 @@ fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
         }
       }
       ast::ExprCast(ref e, ref t) => {
+        match t.node {
+            ast::TyFixedLengthVec(_, ref count_expr) => {
+                check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
+            }
+            _ => {}
+        }
         check_cast(fcx, &**e, &**t, id, expr.span);
       }
       ast::ExprVec(ref args) => {
index c3e7d06f3f896dd28a458b41955237442946da0c..d94ac103ceb731ed37f18d15a5e80f5c5c68fcfb 100644 (file)
@@ -181,8 +181,14 @@ fn visit_local(&mut self, l: &ast::Local, _: ()) {
         visit::walk_local(self, l, ());
     }
 
-    fn visit_ty(&mut self, _t: &ast::Ty, _: ()) {
-        // ignore
+    fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
+        match t.node {
+            ast::TyFixedLengthVec(ref ty, ref count_expr) => {
+                self.visit_ty(&**ty, ());
+                write_ty_to_tcx(self.tcx(), count_expr.id, ty::mk_uint());
+            }
+            _ => visit::walk_ty(self, t, ())
+        }
     }
 }
 
diff --git a/src/librustc/util/io.rs b/src/librustc/util/io.rs
new file mode 100644 (file)
index 0000000..f153aca
--- /dev/null
@@ -0,0 +1,232 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::io::{IoError, IoResult, SeekStyle};
+use std::io;
+use std::slice;
+
+static BUF_CAPACITY: uint = 128;
+
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+    // compute offset as signed and clamp to prevent overflow
+    let pos = match seek {
+        io::SeekSet => 0,
+        io::SeekEnd => end,
+        io::SeekCur => cur,
+    } as i64;
+
+    if offset + pos < 0 {
+        Err(IoError {
+            kind: io::InvalidInput,
+            desc: "invalid seek to a negative offset",
+            detail: None
+        })
+    } else {
+        Ok((offset + pos) as u64)
+    }
+}
+
+/// Writes to an owned, growable byte vector that supports seeking.
+///
+/// # Example
+///
+/// ```rust
+/// # #![allow(unused_must_use)]
+/// use std::io::SeekableMemWriter;
+///
+/// let mut w = SeekableMemWriter::new();
+/// w.write([0, 1, 2]);
+///
+/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// ```
+pub struct SeekableMemWriter {
+    buf: Vec<u8>,
+    pos: uint,
+}
+
+impl SeekableMemWriter {
+    /// Create a new `SeekableMemWriter`.
+    #[inline]
+    pub fn new() -> SeekableMemWriter {
+        SeekableMemWriter::with_capacity(BUF_CAPACITY)
+    }
+    /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+    /// the internal buffer.
+    #[inline]
+    pub fn with_capacity(n: uint) -> SeekableMemWriter {
+        SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+    }
+
+    /// Acquires an immutable reference to the underlying buffer of this
+    /// `SeekableMemWriter`.
+    ///
+    /// No method is exposed for acquiring a mutable reference to the buffer
+    /// because it could corrupt the state of this `MemWriter`.
+    #[inline]
+    pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+    /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+    #[inline]
+    pub fn unwrap(self) -> Vec<u8> { self.buf }
+}
+
+impl Writer for SeekableMemWriter {
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+        if self.pos == self.buf.len() {
+            self.buf.push_all(buf)
+        } else {
+            // Make sure the internal buffer is as least as big as where we
+            // currently are
+            let difference = self.pos as i64 - self.buf.len() as i64;
+            if difference > 0 {
+                self.buf.grow(difference as uint, &0);
+            }
+
+            // Figure out what bytes will be used to overwrite what's currently
+            // there (left), and what will be appended on the end (right)
+            let cap = self.buf.len() - self.pos;
+            let (left, right) = if cap <= buf.len() {
+                (buf.slice_to(cap), buf.slice_from(cap))
+            } else {
+                (buf, &[])
+            };
+
+            // Do the necessary writes
+            if left.len() > 0 {
+                slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+            }
+            if right.len() > 0 {
+                self.buf.push_all(right);
+            }
+        }
+
+        // Bump us forward
+        self.pos += buf.len();
+        Ok(())
+    }
+}
+
+impl Seek for SeekableMemWriter {
+    #[inline]
+    fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+    #[inline]
+    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+        let new = try!(combine(style, self.pos, self.buf.len(), pos));
+        self.pos = new as uint;
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::SeekableMemWriter;
+    use std::io;
+    use test::Bencher;
+
+    #[test]
+    fn test_seekable_mem_writer() {
+        let mut writer = SeekableMemWriter::new();
+        assert_eq!(writer.tell(), Ok(0));
+        writer.write([0]).unwrap();
+        assert_eq!(writer.tell(), Ok(1));
+        writer.write([1, 2, 3]).unwrap();
+        writer.write([4, 5, 6, 7]).unwrap();
+        assert_eq!(writer.tell(), Ok(8));
+        assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]);
+
+        writer.seek(0, io::SeekSet).unwrap();
+        assert_eq!(writer.tell(), Ok(0));
+        writer.write([3, 4]).unwrap();
+        assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]);
+
+        writer.seek(1, io::SeekCur).unwrap();
+        writer.write([0, 1]).unwrap();
+        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]);
+
+        writer.seek(-1, io::SeekEnd).unwrap();
+        writer.write([1, 2]).unwrap();
+        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]);
+
+        writer.seek(1, io::SeekEnd).unwrap();
+        writer.write([1]).unwrap();
+        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
+    }
+
+    #[test]
+    fn seek_past_end() {
+        let mut r = SeekableMemWriter::new();
+        r.seek(10, io::SeekSet).unwrap();
+        assert!(r.write([3]).is_ok());
+    }
+
+    #[test]
+    fn seek_before_0() {
+        let mut r = SeekableMemWriter::new();
+        assert!(r.seek(-1, io::SeekSet).is_err());
+    }
+
+    fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) {
+        let src: Vec<u8> = Vec::from_elem(len, 5);
+
+        b.bytes = (times * len) as u64;
+        b.iter(|| {
+            let mut wr = SeekableMemWriter::new();
+            for _ in range(0, times) {
+                wr.write(src.as_slice()).unwrap();
+            }
+
+            let v = wr.unwrap();
+            assert_eq!(v.len(), times * len);
+            assert!(v.iter().all(|x| *x == 5));
+        });
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 1, 0)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 1, 10)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 1, 100)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 1, 1000)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 100, 0)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 100, 10)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 100, 100)
+    }
+
+    #[bench]
+    fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) {
+        do_bench_seekable_mem_writer(b, 100, 1000)
+    }
+}
index c4a9d9c80ef1284ccf197a8723cace79e52ba43b..e2cadf817d5ea1e220f73006b6f070e0b37e5624 100644 (file)
@@ -36,6 +36,17 @@ pub struct Archive<'a> {
     maybe_ar_prog: Option<String>
 }
 
+/// Helper for adding many files to an archive with a single invocation of
+/// `ar`.
+#[must_use = "must call build() to finish building the archive"]
+pub struct ArchiveBuilder<'a> {
+    archive: Archive<'a>,
+    work_dir: TempDir,
+    /// Filename of each member that should be added to the archive.
+    members: Vec<Path>,
+    should_update_symbols: bool,
+}
+
 fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
           args: &str, cwd: Option<&Path>,
           paths: &[&Path]) -> ProcessOutput {
@@ -85,10 +96,8 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
 }
 
 impl<'a> Archive<'a> {
-    /// Initializes a new static archive with the given object file
-    pub fn create<'b>(config: ArchiveConfig<'a>, initial_object: &'b Path) -> Archive<'a> {
+    fn new(config: ArchiveConfig<'a>) -> Archive<'a> {
         let ArchiveConfig { handler, dst, lib_search_paths, os, maybe_ar_prog } = config;
-        run_ar(handler, &maybe_ar_prog, "crus", None, [&dst, initial_object]);
         Archive {
             handler: handler,
             dst: dst,
@@ -100,17 +109,47 @@ pub fn create<'b>(config: ArchiveConfig<'a>, initial_object: &'b Path) -> Archiv
 
     /// Opens an existing static archive
     pub fn open(config: ArchiveConfig<'a>) -> Archive<'a> {
-        let ArchiveConfig { handler, dst, lib_search_paths, os, maybe_ar_prog } = config;
-        assert!(dst.exists());
-        Archive {
-            handler: handler,
-            dst: dst,
-            lib_search_paths: lib_search_paths,
-            os: os,
-            maybe_ar_prog: maybe_ar_prog
+        let archive = Archive::new(config);
+        assert!(archive.dst.exists());
+        archive
+    }
+
+    /// Removes a file from this archive
+    pub fn remove_file(&mut self, file: &str) {
+        run_ar(self.handler, &self.maybe_ar_prog, "d", None, [&self.dst, &Path::new(file)]);
+    }
+
+    /// Lists all files in an archive
+    pub fn files(&self) -> Vec<String> {
+        let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, [&self.dst]);
+        let output = str::from_utf8(output.output.as_slice()).unwrap();
+        // use lines_any because windows delimits output with `\r\n` instead of
+        // just `\n`
+        output.lines_any().map(|s| s.to_string()).collect()
+    }
+
+    /// Creates an `ArchiveBuilder` for adding files to this archive.
+    pub fn extend(self) -> ArchiveBuilder<'a> {
+        ArchiveBuilder::new(self)
+    }
+}
+
+impl<'a> ArchiveBuilder<'a> {
+    fn new(archive: Archive<'a>) -> ArchiveBuilder<'a> {
+        ArchiveBuilder {
+            archive: archive,
+            work_dir: TempDir::new("rsar").unwrap(),
+            members: vec![],
+            should_update_symbols: false,
         }
     }
 
+    /// Create a new static archive, ready for adding files.
+    pub fn create(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
+        let archive = Archive::new(config);
+        ArchiveBuilder::new(archive)
+    }
+
     /// Adds all of the contents of a native library to this archive. This will
     /// search in the relevant locations for a library named `name`.
     pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> {
@@ -135,48 +174,96 @@ pub fn add_rlib(&mut self, rlib: &Path, name: &str,
     }
 
     /// Adds an arbitrary file to this archive
-    pub fn add_file(&mut self, file: &Path, has_symbols: bool) {
-        let cmd = if has_symbols {"r"} else {"rS"};
-        run_ar(self.handler, &self.maybe_ar_prog, cmd, None, [&self.dst, file]);
-    }
-
-    /// Removes a file from this archive
-    pub fn remove_file(&mut self, file: &str) {
-        run_ar(self.handler, &self.maybe_ar_prog, "d", None, [&self.dst, &Path::new(file)]);
+    pub fn add_file(&mut self, file: &Path) -> io::IoResult<()> {
+        let filename = Path::new(file.filename().unwrap());
+        let new_file = self.work_dir.path().join(&filename);
+        try!(fs::copy(file, &new_file));
+        self.members.push(filename);
+        Ok(())
     }
 
-    /// Updates all symbols in the archive (runs 'ar s' over it)
+    /// Indicate that the next call to `build` should updates all symbols in
+    /// the archive (run 'ar s' over it).
     pub fn update_symbols(&mut self) {
-        run_ar(self.handler, &self.maybe_ar_prog, "s", None, [&self.dst]);
+        self.should_update_symbols = true;
     }
 
-    /// Lists all files in an archive
-    pub fn files(&self) -> Vec<String> {
-        let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, [&self.dst]);
-        let output = str::from_utf8(output.output.as_slice()).unwrap();
-        // use lines_any because windows delimits output with `\r\n` instead of
-        // just `\n`
-        output.lines_any().map(|s| s.to_string()).collect()
+    /// Combine the provided files, rlibs, and native libraries into a single
+    /// `Archive`.
+    pub fn build(self) -> Archive<'a> {
+        // Get an absolute path to the destination, so `ar` will work even
+        // though we run it from `self.work_dir`.
+        let abs_dst = os::getcwd().join(&self.archive.dst);
+        assert!(!abs_dst.is_relative());
+        let mut args = vec![&abs_dst];
+        let mut total_len = abs_dst.as_vec().len();
+
+        if self.members.is_empty() {
+            // OSX `ar` does not allow using `r` with no members, but it does
+            // allow running `ar s file.a` to update symbols only.
+            if self.should_update_symbols {
+                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+                       "s", Some(self.work_dir.path()), args.as_slice());
+            }
+            return self.archive;
+        }
+
+        // Don't allow the total size of `args` to grow beyond 32,000 bytes.
+        // Windows will raise an error if the argument string is longer than
+        // 32,768, and we leave a bit of extra space for the program name.
+        static ARG_LENGTH_LIMIT: uint = 32000;
+
+        for member_name in self.members.iter() {
+            let len = member_name.as_vec().len();
+
+            // `len + 1` to account for the space that's inserted before each
+            // argument.  (Windows passes command-line arguments as a single
+            // string, not an array of strings.)
+            if total_len + len + 1 > ARG_LENGTH_LIMIT {
+                // Add the archive members seen so far, without updating the
+                // symbol table (`S`).
+                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+                       "cruS", Some(self.work_dir.path()), args.as_slice());
+
+                args.clear();
+                args.push(&abs_dst);
+                total_len = abs_dst.as_vec().len();
+            }
+
+            args.push(member_name);
+            total_len += len + 1;
+        }
+
+        // Add the remaining archive members, and update the symbol table if
+        // necessary.
+        let flags = if self.should_update_symbols { "crus" } else { "cruS" };
+        run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+               flags, Some(self.work_dir.path()), args.as_slice());
+
+        self.archive
     }
 
     fn add_archive(&mut self, archive: &Path, name: &str,
                    skip: &[&str]) -> io::IoResult<()> {
         let loc = TempDir::new("rsar").unwrap();
 
-        // First, extract the contents of the archive to a temporary directory
+        // First, extract the contents of the archive to a temporary directory.
+        // We don't unpack directly into `self.work_dir` due to the possibility
+        // of filename collisions.
         let archive = os::make_absolute(archive);
-        run_ar(self.handler, &self.maybe_ar_prog, "x", Some(loc.path()), [&archive]);
+        run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+               "x", Some(loc.path()), [&archive]);
 
         // Next, we must rename all of the inputs to "guaranteed unique names".
-        // The reason for this is that archives are keyed off the name of the
-        // files, so if two files have the same name they will override one
-        // another in the archive (bad).
+        // We move each file into `self.work_dir` under its new unique name.
+        // The reason for this renaming is that archives are keyed off the name
+        // of the files, so if two files have the same name they will override
+        // one another in the archive (bad).
         //
         // We skip any files explicitly desired for skipping, and we also skip
         // all SYMDEF files as these are just magical placeholders which get
         // re-created when we make a new archive anyway.
         let files = try!(fs::readdir(loc.path()));
-        let mut inputs = Vec::new();
         for file in files.iter() {
             let filename = file.filename_str().unwrap();
             if skip.iter().any(|s| *s == filename) { continue }
@@ -192,21 +279,15 @@ fn add_archive(&mut self, archive: &Path, name: &str,
             } else {
                 filename
             };
-            let new_filename = file.with_filename(filename);
+            let new_filename = self.work_dir.path().join(filename.as_slice());
             try!(fs::rename(file, &new_filename));
-            inputs.push(new_filename);
+            self.members.push(Path::new(filename));
         }
-        if inputs.len() == 0 { return Ok(()) }
-
-        // Finally, add all the renamed files to this archive
-        let mut args = vec!(&self.dst);
-        args.extend(inputs.iter());
-        run_ar(self.handler, &self.maybe_ar_prog, "r", None, args.as_slice());
         Ok(())
     }
 
     fn find_library(&self, name: &str) -> Path {
-        let (osprefix, osext) = match self.os {
+        let (osprefix, osext) = match self.archive.os {
             abi::OsWin32 => ("", "lib"), _ => ("lib", "a"),
         };
         // On Windows, static libraries sometimes show up as libfoo.a and other
@@ -214,7 +295,7 @@ fn find_library(&self, name: &str) -> Path {
         let oslibname = format!("{}{}.{}", osprefix, name, osext);
         let unixlibname = format!("lib{}.a", name);
 
-        for path in self.lib_search_paths.iter() {
+        for path in self.archive.lib_search_paths.iter() {
             debug!("looking for {} inside {}", name, path.display());
             let test = path.join(oslibname.as_slice());
             if test.exists() { return test }
@@ -223,9 +304,9 @@ fn find_library(&self, name: &str) -> Path {
                 if test.exists() { return test }
             }
         }
-        self.handler.fatal(format!("could not find native static library `{}`, \
-                                 perhaps an -L flag is missing?",
-                                name).as_slice());
+        self.archive.handler.fatal(format!("could not find native static library `{}`, \
+                                            perhaps an -L flag is missing?",
+                                           name).as_slice());
     }
 }
 
index a0730360ec7298c6aa9b41a16eeb6e454f9ef90c..9bb90427e7ccf24127a290115ab18369654a05e2 100644 (file)
@@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a0:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd => {
+          abi::OsFreebsd | abi::OsDragonfly => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index 4176d0e9a6f57a5ac3fddbd4c6f320cb9b6d9909..43bf3e8e4af385efeb1ad5b1553f86ce98d8e277 100644 (file)
@@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a0:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd => {
+          abi::OsFreebsd | abi::OsDragonfly => {
             "E-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index d3ea9d3aa7237e2facabd94138bc3863bb3a2a17..87f74e72504ac01dec6d411f04466e67355b2e73 100644 (file)
@@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a0:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd => {
+          abi::OsFreebsd | abi::OsDragonfly => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index e298e1dbfe94acba5f456f649dadfd6d8fce0434..94d197ad06a8d23c6e9f84402657400aeb3e797d 100644 (file)
@@ -37,6 +37,12 @@ pub fn get_rpath_flags(config: RPathConfig) -> Vec<String> {
                         "-Wl,-rpath,/usr/local/lib/gcc44".to_string(),
                         "-Wl,-z,origin".to_string()]);
     }
+    else if config.os == abi::OsDragonfly {
+        flags.push_all(["-Wl,-rpath,/usr/lib/gcc47".to_string(),
+                        "-Wl,-rpath,/usr/lib/gcc44".to_string(),
+                        "-Wl,-z,origin".to_string()]);
+    }
+
 
     debug!("preparing the RPATH!");
 
@@ -105,7 +111,7 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig,
 
     // Mac doesn't appear to support $ORIGIN
     let prefix = match config.os {
-        abi::OsAndroid | abi::OsLinux | abi::OsFreebsd
+        abi::OsAndroid | abi::OsLinux | abi::OsFreebsd | abi::OsDragonfly
                           => "$ORIGIN",
         abi::OsMacos => "@loader_path",
         abi::OsWin32 | abi::OsiOS => unreachable!()
@@ -222,6 +228,20 @@ fn test_rpath_relative() {
         assert_eq!(res.as_slice(), "$ORIGIN/../lib");
     }
 
+    #[test]
+    #[cfg(target_os = "dragonfly")]
+    fn test_rpath_relative() {
+        let config = &mut RPathConfig {
+            os: abi::OsDragonfly,
+            used_crates: Vec::new(),
+            out_filename: Path::new("bin/rustc"),
+            get_install_prefix_lib_path: || fail!(),
+            realpath: |p| Ok(p.clone())
+        };
+        let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so"));
+        assert_eq!(res.as_slice(), "$ORIGIN/../lib");
+    }
+
     #[test]
     #[cfg(target_os = "macos")]
     fn test_rpath_relative() {
index b4d67bc98d2e3b14c3a315f43d2814a927965679..3c444806e13e55c45b113b54b2d9f33702053a52 100644 (file)
@@ -48,6 +48,10 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
           abi::OsFreebsd => {
             "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
           }
+          abi::OsDragonfly => {
+            "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
+          }
+
         },
 
         target_triple: target_triple,
index 70807edc9960e3c9ec05a623d5235102fd528a71..b4b5765986bab3b3533bd22fe6b5254984485620 100644 (file)
@@ -52,6 +52,12 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
+          abi::OsDragonfly => {
+            "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
+          }
+
         },
 
         target_triple: target_triple,
index f07c016367634919387f6794fed522fd6a7673f9..f22950e7a299e235c8922a1d7edeec6d513c514e 100644 (file)
@@ -63,6 +63,27 @@ pub struct flock {
         pub static F_SETLKW: libc::c_int = 13;
     }
 
+    #[cfg(target_os = "dragonfly")]
+    mod os {
+        use libc;
+
+        pub struct flock {
+            pub l_start: libc::off_t,
+            pub l_len: libc::off_t,
+            pub l_pid: libc::pid_t,
+            pub l_type: libc::c_short,
+            pub l_whence: libc::c_short,
+
+            // not actually here, but brings in line with freebsd
+            pub l_sysid: libc::c_int,
+        }
+
+        pub static F_UNLCK: libc::c_short = 2;
+        pub static F_WRLCK: libc::c_short = 3;
+        pub static F_SETLK: libc::c_int = 8;
+        pub static F_SETLKW: libc::c_int = 9;
+    }
+
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "ios")]
     mod os {
index c6d6843db5fb32d029f1a82b359831a32f06de62..2fb3143b0bf6e077f7c2886bfdfc0be0c3af8b47 100644 (file)
@@ -663,31 +663,27 @@ fn fmt_inner<'a>(f: &mut fmt::Formatter,
             context.push(m.name.as_slice());
             let path = context.connect("::");
 
-            // the total width of each row's stability summary, in pixels
-            let width = 500;
-
             try!(write!(f, "<tr>"));
-            try!(write!(f, "<td class='summary'>\
-                            <a class='summary' href='{}'>{}</a></td>",
+            try!(write!(f, "<td><a href='{}'>{}</a></td>",
                         Vec::from_slice(context.slice_from(1))
                             .append_one("index.html").connect("/"),
                         path));
-            try!(write!(f, "<td>"));
+            try!(write!(f, "<td class='summary-column'>"));
             try!(write!(f, "<span class='summary Stable' \
-                            style='width: {}px; display: inline-block'>&nbsp</span>",
-                        (width * cnt.stable)/tot));
+                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
+                        (100 * cnt.stable) as f64/tot as f64));
             try!(write!(f, "<span class='summary Unstable' \
-                            style='width: {}px; display: inline-block'>&nbsp</span>",
-                        (width * cnt.unstable)/tot));
+                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
+                        (100 * cnt.unstable) as f64/tot as f64));
             try!(write!(f, "<span class='summary Experimental' \
-                            style='width: {}px; display: inline-block'>&nbsp</span>",
-                        (width * cnt.experimental)/tot));
+                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
+                        (100 * cnt.experimental) as f64/tot as f64));
             try!(write!(f, "<span class='summary Deprecated' \
-                            style='width: {}px; display: inline-block'>&nbsp</span>",
-                        (width * cnt.deprecated)/tot));
+                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
+                        (100 * cnt.deprecated) as f64/tot as f64));
             try!(write!(f, "<span class='summary Unmarked' \
-                            style='width: {}px; display: inline-block'>&nbsp</span>",
-                        (width * cnt.unmarked)/tot));
+                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
+                        (100 * cnt.unmarked) as f64/tot as f64));
             try!(write!(f, "</td></tr>"));
 
             for submodule in m.submodules.iter() {
@@ -699,20 +695,33 @@ fn fmt_inner<'a>(f: &mut fmt::Formatter,
 
         let mut context = Vec::new();
 
+        let tot = self.counts.total();
+        let (stable, unstable, experimental, deprecated, unmarked) = if tot == 0 {
+            (0, 0, 0, 0, 0)
+        } else {
+            ((100 * self.counts.stable)/tot,
+             (100 * self.counts.unstable)/tot,
+             (100 * self.counts.experimental)/tot,
+             (100 * self.counts.deprecated)/tot,
+             (100 * self.counts.unmarked)/tot)
+        };
+
         try!(write!(f,
-r"<h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>{}</a></h1>
+r"<h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>{name}</a></h1>
 This dashboard summarizes the stability levels for all of the public modules of
-the crate, according to the total number of items at each level in the module and its children:
+the crate, according to the total number of items at each level in the module and
+its children (percentages total for {name}):
 <blockquote>
-<a class='stability Stable'></a> stable,<br/>
-<a class='stability Unstable'></a> unstable,<br/>
-<a class='stability Experimental'></a> experimental,<br/>
-<a class='stability Deprecated'></a> deprecated,<br/>
-<a class='stability Unmarked'></a> unmarked
+<a class='stability Stable'></a> stable ({}%),<br/>
+<a class='stability Unstable'></a> unstable ({}%),<br/>
+<a class='stability Experimental'></a> experimental ({}%),<br/>
+<a class='stability Deprecated'></a> deprecated ({}%),<br/>
+<a class='stability Unmarked'></a> unmarked ({}%)
 </blockquote>
 The counts do not include methods or trait
 implementations that are visible only through a re-exported type.",
-self.name));
+stable, unstable, experimental, deprecated, unmarked,
+name=self.name));
         try!(write!(f, "<table>"))
         try!(fmt_inner(f, &mut context, self));
         write!(f, "</table>")
index 95637d311d8c9f302c607672ca63049e8f102400..084ba46797ef9f0492f5fbea60da25496c89c83a 100644 (file)
@@ -1734,17 +1734,19 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
         }
     }).peekable();
     match s.struct_type {
-        doctree::Plain if fields.peek().is_some() => {
-            try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
-            for field in fields {
-                try!(write!(w, "<tr><td id='structfield.{name}'>\
-                                  {stab}<code>{name}</code></td><td>",
-                              stab = ConciseStability(&field.stability),
-                              name = field.name.get_ref().as_slice()));
-                try!(document(w, field));
-                try!(write!(w, "</td></tr>"));
+        doctree::Plain => {
+            if fields.peek().is_some() {
+                try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
+                for field in fields {
+                    try!(write!(w, "<tr><td id='structfield.{name}'>\
+                                      {stab}<code>{name}</code></td><td>",
+                                  stab = ConciseStability(&field.stability),
+                                  name = field.name.get_ref().as_slice()));
+                    try!(document(w, field));
+                    try!(write!(w, "</td></tr>"));
+                }
+                try!(write!(w, "</table>"));
             }
-            try!(write!(w, "</table>"));
         }
         _ => {}
     }
index 4f790f96750286c9442ded17339bf560d92b7915..45e6694853cb407d73061daf2a00eea6b776acd8 100644 (file)
@@ -129,6 +129,14 @@ pre {
     padding: 20px;
 }
 
+.content.source {
+    margin-top: 50px;
+    max-width: none;
+    overflow: visible;
+    margin-left: 0px;
+    min-width: 70em;
+}
+
 nav.sub {
     font-size: 16px;
     text-transform: uppercase;
@@ -407,7 +415,7 @@ h1 .stability {
 .stability.Stable { border-color: #54A759; color: #2D8632; }
 .stability.Frozen { border-color: #009431; color: #007726; }
 .stability.Locked { border-color: #0084B6; color: #00668c; }
-.stability.Unmarked { border-color: #FFFFFF; }
+.stability.Unmarked { border-color: #BBBBBB; }
 
 .summary {
     padding-right: 0px;
@@ -416,7 +424,7 @@ h1 .stability {
 .summary.Experimental { background-color: #D46D6A; }
 .summary.Unstable { background-color: #D4B16A; }
 .summary.Stable { background-color: #54A759; }
-.summary.Unmarked { background-color: #FFFFFF; }
+.summary.Unmarked { background-color: #BBBBBB; }
 
 :target { background: #FDFFD3; }
 
index 1869031dab3c2eca35df3e355089634ee1d3ef4b..8688e031890b91315a2dad053da5f117836a986b 100644 (file)
@@ -42,6 +42,9 @@
             $('.docblock.short').width(function() {
                 return contentWidth - 40 - $(this).prev().width();
             }).addClass('nowrap');
+            $('.summary-column').width(function() {
+                return contentWidth - 40 - $(this).prev().width();
+            })
         }, 150);
     }
     resizeShortBlocks();
@@ -58,7 +61,7 @@
             }
             $('#' + from)[0].scrollIntoView();
             $('.line-numbers span').removeClass('line-highlighted');
-            for (i = from; i <= to; i += 1) {
+            for (i = from; i <= to; ++i) {
                 $('#' + i).addClass('line-highlighted');
             }
         }
             stripped = '',
             len = rootPath.match(/\.\.\//g).length + 1;
 
-        for (i = 0; i < len; i += 1) {
+        for (i = 0; i < len; ++i) {
             match = url.match(/\/[^\/]*$/);
             if (i < len - 1) {
                 stripped = match[0] + stripped;
 
         document.location.href = url;
     });
+    /**
+     * A function to compute the Levenshtein distance between two strings
+     * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
+     * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
+     * This code is an unmodified version of the code written by Marco de Wit 
+     * and was found at http://stackoverflow.com/a/18514751/745719
+     */
+    var levenshtein = (function() {
+        var row2 = [];
+        return function(s1, s2) {
+            if (s1 === s2) {
+                return 0;
+            } else {
+                var s1_len = s1.length, s2_len = s2.length;
+                if (s1_len && s2_len) {
+                    var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
+                    while (i1 < s1_len)
+                        row[i1] = ++i1;
+                    while (i2 < s2_len) {
+                        c2 = s2.charCodeAt(i2);
+                        a = i2;
+                        ++i2;
+                        b = i2;
+                        for (i1 = 0; i1 < s1_len; ++i1) {
+                            c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+                            a = row[i1];
+                            b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+                            row[i1] = b;
+                        }
+                    }
+                    return b;
+                } else {
+                    return s1_len + s2_len;
+                }
+            }
+        };
+    })();
 
     function initSearch(rawSearchIndex) {
         var currentResults, index, searchIndex;
+        var MAX_LEV_DISTANCE = 3;
         var params = getQueryStringParams();
 
         // Populate search bar with query string search term when provided,
                 split = valLower.split("::");
 
             //remove empty keywords
-            for (var j = 0; j < split.length; j++) {
+            for (var j = 0; j < split.length; ++j) {
                 split[j].toLowerCase();
                 if (split[j] === "") {
                     split.splice(j, 1);
                 val.charAt(val.length - 1) === val.charAt(0))
             {
                 val = val.substr(1, val.length - 2);
-                for (var i = 0; i < nSearchWords; i += 1) {
+                for (var i = 0; i < nSearchWords; ++i) {
                     if (searchWords[i] === val) {
                         // filter type: ... queries
                         if (typeFilter < 0 || typeFilter === searchIndex[i].ty) {
             } else {
                 // gather matching search results up to a certain maximum
                 val = val.replace(/\_/g, "");
-                for (var i = 0; i < split.length; i++) {
-                    for (var j = 0; j < nSearchWords; j += 1) {
+                for (var i = 0; i < split.length; ++i) {
+                    for (var j = 0; j < nSearchWords; ++j) {
+                        var lev_distance;
                         if (searchWords[j].indexOf(split[i]) > -1 ||
                             searchWords[j].indexOf(val) > -1 ||
                             searchWords[j].replace(/_/g, "").indexOf(val) > -1)
                         {
                             // filter type: ... queries
                             if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
-                                results.push({id: j, index: searchWords[j].replace(/_/g, "").indexOf(val)});
+                                results.push({
+                                    id: j,
+                                    index: searchWords[j].replace(/_/g, "").indexOf(val),
+                                    lev: 0,
+                                });
+                            }
+                        } else if (
+                            (lev_distance = levenshtein(searchWords[j], val)) <= 
+                                MAX_LEV_DISTANCE) {
+                            if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
+                                results.push({
+                                    id: j,
+                                    index: 0,
+                                    // we want lev results to go lower than others
+                                    lev: lev_distance,
+                                });
                             }
                         }
                         if (results.length === max) {
             }
 
             var nresults = results.length;
-            for (var i = 0; i < nresults; i += 1) {
+            for (var i = 0; i < nresults; ++i) {
                 results[i].word = searchWords[results[i].id];
                 results[i].item = searchIndex[results[i].id] || {};
             }
             results.sort(function(aaa, bbb) {
                 var a, b;
 
+                // Sort by non levenshtein results and then levenshtein results by the distance
+                // (less changes required to match means higher rankings)
+                a = (aaa.lev);
+                b = (bbb.lev);
+                if (a !== b) return a - b;
+
                 // sort by crate (non-current crate goes later)
                 a = (aaa.item.crate !== window.currentCrate);
                 b = (bbb.item.crate !== window.currentCrate);
                     results[i].id = -1;
                 }
             }
-            for (var i = 0; i < results.length; i++) {
+            for (var i = 0; i < results.length; ++i) {
                 var result = results[i],
                     name = result.item.name.toLowerCase(),
                     path = result.item.path.toLowerCase(),
          * @return {[boolean]}       [Whether the result is valid or not]
          */
         function validateResult(name, path, keys, parent) {
-            //initially valid
-            var validate = true;
-            //if there is a parent, then validate against parent
-            if (parent !== undefined) {
-                for (var i = 0; i < keys.length; i++) {
-                    // if previous keys are valid and current key is in the
-                    // path, name or parent
-                    if ((validate) &&
-                        (name.toLowerCase().indexOf(keys[i]) > -1 ||
-                         path.toLowerCase().indexOf(keys[i]) > -1 ||
-                         parent.name.toLowerCase().indexOf(keys[i]) > -1))
-                    {
-                        validate = true;
-                    } else {
-                        validate = false;
-                    }
-                }
-            } else {
-                for (var i = 0; i < keys.length; i++) {
-                    // if previous keys are valid and current key is in the
-                    // path, name
-                    if ((validate) &&
-                        (name.toLowerCase().indexOf(keys[i]) > -1 ||
-                         path.toLowerCase().indexOf(keys[i]) > -1))
-                    {
-                        validate = true;
-                    } else {
-                        validate = false;
-                    }
+            for (var i=0; i < keys.length; ++i) {
+                // each check is for validation so we negate the conditions and invalidate
+                if (!( 
+                    // check for an exact name match
+                    name.toLowerCase().indexOf(keys[i]) > -1 ||
+                    // then an exact path match
+                    path.toLowerCase().indexOf(keys[i]) > -1 ||
+                    // next if there is a parent, check for exact parent match
+                    (parent !== undefined && 
+                        parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
+                    // lastly check to see if the name was a levenshtein match
+                    levenshtein(name.toLowerCase(), keys[i]) <= 
+                        MAX_LEV_DISTANCE)) {
+                    return false;
                 }
             }
-            return validate;
+            return true;
         }
 
         function getQuery() {
 
             resultIndex = execQuery(query, 20000, index);
             len = resultIndex.length;
-            for (i = 0; i < len; i += 1) {
+            for (i = 0; i < len; ++i) {
                 if (resultIndex[i].id > -1) {
                     obj = searchIndex[resultIndex[i].id];
                     filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
                 // faster analysis operations
                 var len = items.length;
                 var lastPath = "";
-                for (var i = 0; i < len; i += 1) {
+                for (var i = 0; i < len; ++i) {
                     var rawRow = items[i];
                     var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
                                path: rawRow[2] || lastPath, desc: rawRow[3],
                 crates.push(crate);
             }
             crates.sort();
-            for (var i = 0; i < crates.length; i++) {
+            for (var i = 0; i < crates.length; ++i) {
                 var klass = 'crate';
                 if (crates[i] == window.currentCrate) {
                     klass += ' current';
     window.register_implementors = function(imp) {
         var list = $('#implementors-list');
         var libs = Object.getOwnPropertyNames(imp);
-        for (var i = 0; i < libs.length; i++) {
+        for (var i = 0; i < libs.length; ++i) {
             if (libs[i] == currentCrate) continue;
             var structs = imp[libs[i]];
-            for (var j = 0; j < structs.length; j++) {
+            for (var j = 0; j < structs.length; ++j) {
                 var code = $('<code>').append(structs[j]);
                 $.each(code.find('a'), function(idx, a) {
                     var href = $(a).attr('href');
index af6de0cf605a204119deefbe2ebf8b683d8c2cb1..531bbe038fcbbc5664097ced27680ad9bb3f377c 100644 (file)
@@ -42,6 +42,7 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 mod imp {
     use core::prelude::*;
 
index fd290491eaf1e1208a50782ec707ed5ba3a84572..dc96aecff8017c7c858934ad3ebb56668f4fb79e 100644 (file)
 //! decrement() manually.
 
 use core::atomics;
+use core::ops::Drop;
 
 use mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
 
 static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
 static mut TASK_LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
 
-pub fn increment() {
+pub struct Token { _private: () }
+
+impl Drop for Token {
+    fn drop(&mut self) { decrement() }
+}
+
+/// Increment the number of live tasks, returning a token which will decrement
+/// the count when dropped.
+pub fn increment() -> Token {
     let _ = unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst) };
+    Token { _private: () }
 }
 
 pub fn decrement() {
index f018b3fc16b3b63a8b26145731084f6df32af474..789723af1b1332e8fc73bb58cf0c70e2dbcaebb1 100644 (file)
@@ -94,6 +94,9 @@ pub enum _Unwind_Context {}
 #[link(name = "gcc")]
 extern {}
 
+#[cfg(target_os = "dragonfly")]
+#[link(name = "gcc_pic")]
+extern {}
 
 extern "C" {
     // iOS on armv7 uses SjLj exceptions and requires to link
index bdb1c60b6d6f8db7acedcbb32d2aeb0d1ffe3f49..e2a5eef0d99e18637ce5ae4e12d479826be21d38 100644 (file)
@@ -125,8 +125,8 @@ fn try_take() {
         }).join();
     }
 
-    fn cleanup_task(mut t: Box<Task>) {
-        t.destroyed = true;
+    fn cleanup_task(t: Box<Task>) {
+        t.drop();
     }
 
 }
index c999a08eb93b65269faa82dc5b038200b1598d84..f24c2609d09e81b93f6f7a1af38ba0201c9ee4d0 100644 (file)
@@ -347,6 +347,7 @@ mod imp {
     type pthread_condattr_t = libc::c_void;
 
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     mod os {
         use libc;
 
index 0eacd40f01cee052d45bcf48e9fe47cfa19a21b2..6544c020e09494bfd6707ac13fe97f7f69da8710 100644 (file)
@@ -194,6 +194,10 @@ unsafe fn target_record_sp_limit(limit: uint) {
     unsafe fn target_record_sp_limit(limit: uint) {
         asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile")
     }
+    #[cfg(target_arch = "x86_64", target_os = "dragonfly")] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile")
+    }
 
     // x86
     #[cfg(target_arch = "x86", target_os = "macos")]
@@ -272,6 +276,13 @@ unsafe fn target_get_sp_limit() -> uint {
         asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
+    #[cfg(target_arch = "x86_64", target_os = "dragonfly")] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+
 
     // x86
     #[cfg(target_arch = "x86", target_os = "macos")]
index d27a4f25b4e70ce60cd7a96091ea65431a19a606..e3d9b7d136ec2e05b6b16816e89dbb29d35418d9 100644 (file)
@@ -100,12 +100,21 @@ pub struct Task {
     pub storage: LocalStorage,
     pub unwinder: Unwinder,
     pub death: Death,
-    pub destroyed: bool,
     pub name: Option<SendStr>,
 
+    state: TaskState,
     imp: Option<Box<Runtime + Send>>,
 }
 
+// Once a task has entered the `Armed` state it must be destroyed via `drop`,
+// and no other method. This state is used to track this transition.
+#[deriving(PartialEq)]
+enum TaskState {
+    New,
+    Armed,
+    Destroyed,
+}
+
 pub struct TaskOpts {
     /// Invoke this procedure with the result of the task when it finishes.
     pub on_exit: Option<proc(Result): Send>,
@@ -159,7 +168,7 @@ pub fn new() -> Task {
             storage: LocalStorage(None),
             unwinder: Unwinder::new(),
             death: Death::new(),
-            destroyed: false,
+            state: New,
             name: None,
             imp: None,
         }
@@ -203,7 +212,7 @@ pub fn new() -> Task {
     /// }).destroy();
     /// # }
     /// ```
-    pub fn run(self: Box<Task>, f: ||) -> Box<Task> {
+    pub fn run(mut self: Box<Task>, f: ||) -> Box<Task> {
         assert!(!self.is_destroyed(), "cannot re-use a destroyed task");
 
         // First, make sure that no one else is in TLS. This does not allow
@@ -212,6 +221,7 @@ pub fn run(self: Box<Task>, f: ||) -> Box<Task> {
         if Local::exists(None::<Task>) {
             fail!("cannot run a task recursively inside another");
         }
+        self.state = Armed;
         Local::put(self);
 
         // There are two primary reasons that general try/catch is unsafe. The
@@ -333,12 +343,12 @@ fn cleanup(self: Box<Task>, result: Result) -> Box<Task> {
         // Now that we're done, we remove the task from TLS and flag it for
         // destruction.
         let mut task: Box<Task> = Local::take();
-        task.destroyed = true;
+        task.state = Destroyed;
         return task;
     }
 
     /// Queries whether this can be destroyed or not.
-    pub fn is_destroyed(&self) -> bool { self.destroyed }
+    pub fn is_destroyed(&self) -> bool { self.state == Destroyed }
 
     /// Inserts a runtime object into this task, transferring ownership to the
     /// task. It is illegal to replace a previous runtime object in this task
@@ -453,12 +463,20 @@ pub fn stack_bounds(&self) -> (uint, uint) {
     pub fn can_block(&self) -> bool {
         self.imp.get_ref().can_block()
     }
+
+    /// Consume this task, flagging it as a candidate for destruction.
+    ///
+    /// This function is required to be invoked to destroy a task. A task
+    /// destroyed through a normal drop will abort.
+    pub fn drop(mut self) {
+        self.state = Destroyed;
+    }
 }
 
 impl Drop for Task {
     fn drop(&mut self) {
         rtdebug!("called drop for a task: {}", self as *mut Task as uint);
-        rtassert!(self.destroyed);
+        rtassert!(self.state != Armed);
     }
 }
 
@@ -634,12 +652,17 @@ fn test_begin_unwind() {
         begin_unwind("cause", file!(), line!())
     }
 
+    #[test]
+    fn drop_new_task_ok() {
+        drop(Task::new());
+    }
+
     // Task blocking tests
 
     #[test]
     fn block_and_wake() {
         let task = box Task::new();
         let mut task = BlockedTask::block(task).wake().unwrap();
-        task.destroyed = true;
+        task.drop();
     }
 }
index 3b9ee31d8e5078ff8170b246562ab2fbbf091abf..b9b12686170c0eacb01d2672be93bf231079b57b 100644 (file)
@@ -43,6 +43,7 @@ pub unsafe fn destroy(key: Key) {
 
 #[cfg(target_os="linux")]
 #[cfg(target_os="freebsd")]
+#[cfg(target_os="dragonfly")]
 #[cfg(target_os="android")]
 #[cfg(target_os = "ios")]
 #[allow(non_camel_case_types)] // foreign type
index d0d6287695d5c3b1c94671f6ce094b64626da5ad..2bcd2101d890b979a81ca1833fb86d98922b4efd 100644 (file)
@@ -719,6 +719,7 @@ pub fn uv_signal_start(h: *mut uv_signal_t, cb: uv_signal_cb,
 extern {}
 
 #[cfg(target_os = "linux")]
+#[cfg(target_os = "dragonfly")]
 #[link(name = "rt")]
 extern {}
 
@@ -729,5 +730,6 @@ pub fn uv_signal_start(h: *mut uv_signal_t, cb: uv_signal_cb,
 extern {}
 
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 #[link(name = "kvm")]
 extern {}
index dfce1eeb832d574a635e4ac8abf8041513470dfd..c3434466836175f85242aabbbbff81c343fc3469 100644 (file)
@@ -1023,8 +1023,124 @@ mod tests {
     use ebml::writer;
     use {Encodable, Decodable};
 
-    use std::io::MemWriter;
+    use std::io::{IoError, IoResult, SeekStyle};
+    use std::io;
     use std::option::{None, Option, Some};
+    use std::slice;
+
+    static BUF_CAPACITY: uint = 128;
+
+    fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+        // compute offset as signed and clamp to prevent overflow
+        let pos = match seek {
+            io::SeekSet => 0,
+            io::SeekEnd => end,
+            io::SeekCur => cur,
+        } as i64;
+
+        if offset + pos < 0 {
+            Err(IoError {
+                kind: io::InvalidInput,
+                desc: "invalid seek to a negative offset",
+                detail: None
+            })
+        } else {
+            Ok((offset + pos) as u64)
+        }
+    }
+
+    /// Writes to an owned, growable byte vector that supports seeking.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # #![allow(unused_must_use)]
+    /// use std::io::SeekableMemWriter;
+    ///
+    /// let mut w = SeekableMemWriter::new();
+    /// w.write([0, 1, 2]);
+    ///
+    /// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+    /// ```
+    pub struct SeekableMemWriter {
+        buf: Vec<u8>,
+        pos: uint,
+    }
+
+    impl SeekableMemWriter {
+        /// Create a new `SeekableMemWriter`.
+        #[inline]
+        pub fn new() -> SeekableMemWriter {
+            SeekableMemWriter::with_capacity(BUF_CAPACITY)
+        }
+        /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+        /// the internal buffer.
+        #[inline]
+        pub fn with_capacity(n: uint) -> SeekableMemWriter {
+            SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+        }
+
+        /// Acquires an immutable reference to the underlying buffer of this
+        /// `SeekableMemWriter`.
+        ///
+        /// No method is exposed for acquiring a mutable reference to the buffer
+        /// because it could corrupt the state of this `MemWriter`.
+        #[inline]
+        pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+        /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+        #[inline]
+        pub fn unwrap(self) -> Vec<u8> { self.buf }
+    }
+
+    impl Writer for SeekableMemWriter {
+        #[inline]
+        fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+            if self.pos == self.buf.len() {
+                self.buf.push_all(buf)
+            } else {
+                // Make sure the internal buffer is as least as big as where we
+                // currently are
+                let difference = self.pos as i64 - self.buf.len() as i64;
+                if difference > 0 {
+                    self.buf.grow(difference as uint, &0);
+                }
+
+                // Figure out what bytes will be used to overwrite what's currently
+                // there (left), and what will be appended on the end (right)
+                let cap = self.buf.len() - self.pos;
+                let (left, right) = if cap <= buf.len() {
+                    (buf.slice_to(cap), buf.slice_from(cap))
+                } else {
+                    (buf, &[])
+                };
+
+                // Do the necessary writes
+                if left.len() > 0 {
+                    slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+                }
+                if right.len() > 0 {
+                    self.buf.push_all(right);
+                }
+            }
+
+            // Bump us forward
+            self.pos += buf.len();
+            Ok(())
+        }
+    }
+
+    impl Seek for SeekableMemWriter {
+        #[inline]
+        fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+        #[inline]
+        fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+            let new = try!(combine(style, self.pos, self.buf.len(), pos));
+            self.pos = new as uint;
+            Ok(())
+        }
+    }
 
     #[test]
     fn test_vuint_at() {
@@ -1078,7 +1194,7 @@ fn test_vuint_at() {
     fn test_option_int() {
         fn test_v(v: Option<int>) {
             debug!("v == {}", v);
-            let mut wr = MemWriter::new();
+            let mut wr = SeekableMemWriter::new();
             {
                 let mut ebml_w = writer::Encoder::new(&mut wr);
                 let _ = v.encode(&mut ebml_w);
index a56904c9ef4db700d0c2917d7f5b531082327488..0752c68f4d0b29d5bb9f107438f9cc1165345608 100644 (file)
@@ -2991,7 +2991,7 @@ fn assert_stream_equal(src: &str,
                 Some(e) => e,
                 None => { break; }
             };
-            let (ref expected_evt, ref expected_stack) = *expected.get(i);
+            let (ref expected_evt, ref expected_stack) = expected[i];
             if !parser.stack().is_equal_to(expected_stack.as_slice()) {
                 fail!("Parser stack is not equal to {}", expected_stack);
             }
index bcc0761d92a3a75a90861183df084847d9d47c8c..7731cd12ec28f8c9dde42df997982a5ea17d49bf 100644 (file)
 use mem;
 use option::{Option, Some, None};
 use slice::{ImmutableVector, MutableVector, Vector};
-use str::{Str, StrAllocating, StrSlice};
+use str::{Str, StrSlice};
+use str;
 use string::String;
 use to_string::IntoStr;
 use vec::Vec;
 
+#[deprecated="this trait has been renamed to `AsciiExt`"]
+pub use StrAsciiExt = self::AsciiExt;
+
+#[deprecated="this trait has been renamed to `OwnedAsciiExt`"]
+pub use OwnedStrAsciiExt = self::OwnedAsciiExt;
+
+
 /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
 #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
 pub struct Ascii { chr: u8 }
@@ -366,108 +374,133 @@ fn into_bytes(self) -> Vec<u8> {
     }
 }
 
+
 /// Extension methods for ASCII-subset only operations on owned strings
-pub trait OwnedStrAsciiExt {
+pub trait OwnedAsciiExt {
     /// Convert the string to ASCII upper case:
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
     /// but non-ASCII letters are unchanged.
-    fn into_ascii_upper(self) -> String;
+    fn into_ascii_upper(self) -> Self;
 
     /// Convert the string to ASCII lower case:
     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
     /// but non-ASCII letters are unchanged.
-    fn into_ascii_lower(self) -> String;
+    fn into_ascii_lower(self) -> Self;
 }
 
 /// Extension methods for ASCII-subset only operations on string slices
-pub trait StrAsciiExt {
+pub trait AsciiExt<T> {
     /// Makes a copy of the string in ASCII upper case:
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
     /// but non-ASCII letters are unchanged.
-    fn to_ascii_upper(&self) -> String;
+    fn to_ascii_upper(&self) -> T;
 
     /// Makes a copy of the string in ASCII lower case:
     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
     /// but non-ASCII letters are unchanged.
-    fn to_ascii_lower(&self) -> String;
+    fn to_ascii_lower(&self) -> T;
 
     /// Check that two strings are an ASCII case-insensitive match.
     /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
     /// but without allocating and copying temporary strings.
-    fn eq_ignore_ascii_case(&self, other: &str) -> bool;
+    fn eq_ignore_ascii_case(&self, other: Self) -> bool;
 }
 
-impl<'a> StrAsciiExt for &'a str {
+impl<'a> AsciiExt<String> for &'a str {
     #[inline]
     fn to_ascii_upper(&self) -> String {
-        unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
+        // Vec<u8>::to_ascii_upper() preserves the UTF-8 invariant.
+        unsafe { str::raw::from_utf8_owned(self.as_bytes().to_ascii_upper()) }
     }
 
     #[inline]
     fn to_ascii_lower(&self) -> String {
-        unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }
+        // Vec<u8>::to_ascii_lower() preserves the UTF-8 invariant.
+        unsafe { str::raw::from_utf8_owned(self.as_bytes().to_ascii_lower()) }
     }
 
     #[inline]
     fn eq_ignore_ascii_case(&self, other: &str) -> bool {
-        self.len() == other.len() &&
-            self.as_bytes().iter().zip(other.as_bytes().iter()).all(
-            |(byte_self, byte_other)| {
-                ASCII_LOWER_MAP[*byte_self as uint] ==
-                    ASCII_LOWER_MAP[*byte_other as uint]
-            })
+        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
     }
 }
 
-impl OwnedStrAsciiExt for String {
+impl OwnedAsciiExt for String {
     #[inline]
     fn into_ascii_upper(self) -> String {
-        unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
+        // Vec<u8>::into_ascii_upper() preserves the UTF-8 invariant.
+        unsafe { str::raw::from_utf8_owned(self.into_bytes().into_ascii_upper()) }
     }
 
     #[inline]
     fn into_ascii_lower(self) -> String {
-        unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }
+        // Vec<u8>::into_ascii_lower() preserves the UTF-8 invariant.
+        unsafe { str::raw::from_utf8_owned(self.into_bytes().into_ascii_lower()) }
     }
 }
 
-#[inline]
-unsafe fn str_map_bytes(string: String, map: &'static [u8]) -> String {
-    let mut bytes = string.into_bytes();
+impl<'a> AsciiExt<Vec<u8>> for &'a [u8] {
+    #[inline]
+    fn to_ascii_upper(&self) -> Vec<u8> {
+        self.iter().map(|&byte| ASCII_UPPER_MAP[byte as uint]).collect()
+    }
 
-    for b in bytes.mut_iter() {
-        *b = map[*b as uint];
+    #[inline]
+    fn to_ascii_lower(&self) -> Vec<u8> {
+        self.iter().map(|&byte| ASCII_LOWER_MAP[byte as uint]).collect()
     }
 
-    String::from_utf8(bytes).unwrap()
+    #[inline]
+    fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
+        self.len() == other.len() &&
+            self.iter().zip(other.iter()).all(
+            |(byte_self, byte_other)| {
+                ASCII_LOWER_MAP[*byte_self as uint] ==
+                    ASCII_LOWER_MAP[*byte_other as uint]
+            })
+    }
 }
 
-#[inline]
-unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String {
-    let mut s = String::from_str(string);
-    for b in s.as_mut_bytes().mut_iter() {
-        *b = map[*b as uint];
+impl OwnedAsciiExt for Vec<u8> {
+    #[inline]
+    fn into_ascii_upper(mut self) -> Vec<u8> {
+        for byte in self.mut_iter() {
+            *byte = ASCII_UPPER_MAP[*byte as uint];
+        }
+        self
+    }
+
+    #[inline]
+    fn into_ascii_lower(mut self) -> Vec<u8> {
+        for byte in self.mut_iter() {
+            *byte = ASCII_LOWER_MAP[*byte as uint];
+        }
+        self
     }
-    s.into_string()
 }
 
-static ASCII_LOWER_MAP: &'static [u8] = &[
+
+pub static ASCII_LOWER_MAP: [u8, ..256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-    0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
-    0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
-    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+    b'@',
+
+          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+    b'x', b'y', b'z',
+
+                      b'[', b'\\', b']', b'^', b'_',
+    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
@@ -486,23 +519,27 @@ unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String {
     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
 ];
 
-static ASCII_UPPER_MAP: &'static [u8] = &[
+pub static ASCII_UPPER_MAP: [u8, ..256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
-    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-    0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
-    0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
+    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
+    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
+    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
+    b'`',
+
+          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
+    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
+    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
+    b'X', b'Y', b'Z',
+
+                      b'{', b'|', b'}', b'~', 0x7f,
     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
index 834d461f20ba1517f85fede4cd68ccdbfaaf264d..d231189aeded04f51b1968e0e4466508f1bbf917 100644 (file)
@@ -113,7 +113,7 @@ macro_rules! bitflags(
     ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
         $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
     }) => (
-        #[deriving(PartialEq, Eq, Clone)]
+        #[deriving(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
         $(#[$attr])*
         pub struct $BitFlags {
             bits: $T,
@@ -220,6 +220,7 @@ fn not(&self) -> $BitFlags {
 
 #[cfg(test)]
 mod tests {
+    use hash;
     use option::{Some, None};
     use ops::{BitOr, BitAnd, Sub, Not};
 
@@ -336,4 +337,42 @@ fn test_operators() {
         assert!((e1 - e2) == FlagA);     // set difference
         assert!(!e2 == FlagA);           // set complement
     }
+
+    #[test]
+    fn test_lt() {
+        let mut a = Flags::empty();
+        let mut b = Flags::empty();
+
+        assert!(!(a < b) && !(b < a));
+        b = FlagB;
+        assert!(a < b);
+        a = FlagC;
+        assert!(!(a < b) && b < a);
+        b = FlagC | FlagB;
+        assert!(a < b);
+    }
+
+    #[test]
+    fn test_ord() {
+        let mut a = Flags::empty();
+        let mut b = Flags::empty();
+
+        assert!(a <= b && a >= b);
+        a = FlagA;
+        assert!(a > b && a >= b);
+        assert!(b < a && b <= a);
+        b = FlagB;
+        assert!(b > a && b >= a);
+        assert!(a < b && a <= b);
+    }
+
+    #[test]
+    fn test_hash() {
+      let mut x = Flags::empty();
+      let mut y = Flags::empty();
+      assert!(hash::hash(&x) == hash::hash(&y));
+      x = Flags::all();
+      y = FlagABC;
+      assert!(hash::hash(&x) == hash::hash(&y));
+    }
 }
index 8b6e6d61842ae965c2971251bd537d74b53db949..a569ee4a32a18554e9611514a81fb6eb8a843eee 100644 (file)
@@ -675,7 +675,7 @@ fn reserve(&mut self, new_capacity: uint) {
 /// Hood bucket stealing.
 ///
 /// The hashes are all keyed by the task-local random number generator
-/// on creation by default, this means the ordering of the keys is
+/// on creation by default. This means that the ordering of the keys is
 /// randomized, but makes the tables more resistant to
 /// denial-of-service attacks (Hash DoS). This behaviour can be
 /// overridden with one of the constructors.
index 5980245fa79a24e53f445b0192e920a67b8b01bf..2c4e0ea67010f2c9143d5b6a33ffc87a32cc7ec4 100644 (file)
@@ -193,6 +193,7 @@ fn test_loading_cosine() {
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "macos")]
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     fn test_errors_do_not_crash() {
         // Open /dev/null as a library to get an error, and make sure
         // that only causes an error, and not a crash.
@@ -209,6 +210,7 @@ fn test_errors_do_not_crash() {
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 pub mod dl {
 
     use c_str::{CString, ToCStr};
index c7dec49a76d1fe0f2b82568300b81ab11488a1dc..1b2706b3f5b22c8434e6af0853911e52ad1554fa 100644 (file)
@@ -114,7 +114,7 @@ impl File {
     /// `FileMode` and `FileAccess` provide information about the permissions
     /// context in which a given stream is created. More information about them
     /// can be found in `std::io`'s docs. If a file is opened with `Write`
-    /// or `ReadWrite` access, then it will be created it does not already
+    /// or `ReadWrite` access, then it will be created if it does not already
     /// exist.
     ///
     /// Note that, with this function, a `File` is returned regardless of the
@@ -273,7 +273,7 @@ pub fn stat(&mut self) -> IoResult<FileStat> {
 ///
 /// # Error
 ///
-/// This function will return an error if the path points to a directory, the
+/// This function will return an error if `path` points to a directory, if the
 /// user lacks permissions to remove the file, or if some other filesystem-level
 /// error occurs.
 pub fn unlink(path: &Path) -> IoResult<()> {
@@ -332,8 +332,8 @@ fn do_unlink(path: &Path) -> IoResult<()> {
 ///
 /// # Error
 ///
-/// This call will return an error if the user lacks the requisite permissions
-/// to perform a `stat` call on the given path or if there is no entry in the
+/// This function will return an error if the user lacks the requisite permissions
+/// to perform a `stat` call on the given `path` or if there is no entry in the
 /// filesystem at the provided path.
 pub fn stat(path: &Path) -> IoResult<FileStat> {
     let err = match LocalIo::maybe_raise(|io| io.fs_stat(&path.to_c_str())) {
@@ -415,9 +415,9 @@ fn from_rtio(s: rtio::FileStat) -> FileStat {
 ///
 /// # Error
 ///
-/// Will return an error if the provided `path` doesn't exist, the process lacks
-/// permissions to view the contents, or if some other intermittent I/O error
-/// occurs.
+/// This function will return an error if the provided `from` doesn't exist, if
+/// the process lacks permissions to view the contents, or if some other
+/// intermittent I/O error occurs.
 pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
     let err = LocalIo::maybe_raise(|io| {
         io.fs_rename(&from.to_c_str(), &to.to_c_str())
@@ -444,8 +444,8 @@ pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
 ///
 /// # Error
 ///
-/// Will return an error in the following situations, but is not limited to
-/// just these cases:
+/// This function will return an error in the following situations, but is not
+/// limited to just these cases:
 ///
 /// * The `from` path is not a file
 /// * The `from` file does not exist
@@ -503,9 +503,9 @@ fn update_err<T>(result: IoResult<T>, from: &Path, to: &Path) -> IoResult<T> {
 ///
 /// # Error
 ///
-/// If this function encounters an I/O error, it will return an `Err` value.
-/// Some possible error situations are not having the permission to
-/// change the attributes of a file or the file not existing.
+/// This function will return an error if the provided `path` doesn't exist, if
+/// the process lacks permissions to change the attributes of the file, or if
+/// some other I/O error is encountered.
 pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> {
     let err = LocalIo::maybe_raise(|io| {
         io.fs_chmod(&path.to_c_str(), mode.bits() as uint)
@@ -577,8 +577,8 @@ pub fn readlink(path: &Path) -> IoResult<Path> {
 ///
 /// # Error
 ///
-/// This call will return an error if the user lacks permissions to make a new
-/// directory at the provided path, or if the directory already exists.
+/// This function will return an error if the user lacks permissions to make a
+/// new directory at the provided `path`, or if the directory already exists.
 pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
     let err = LocalIo::maybe_raise(|io| {
         io.fs_mkdir(&path.to_c_str(), mode.bits() as uint)
@@ -602,8 +602,8 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
 ///
 /// # Error
 ///
-/// This call will return an error if the user lacks permissions to remove the
-/// directory at the provided path, or if the directory isn't empty.
+/// This function will return an error if the user lacks permissions to remove
+/// the directory at the provided `path`, or if the directory isn't empty.
 pub fn rmdir(path: &Path) -> IoResult<()> {
     let err = LocalIo::maybe_raise(|io| {
         io.fs_rmdir(&path.to_c_str())
@@ -640,9 +640,9 @@ pub fn rmdir(path: &Path) -> IoResult<()> {
 ///
 /// # Error
 ///
-/// Will return an error if the provided `from` doesn't exist, the process lacks
-/// permissions to view the contents or if the `path` points at a non-directory
-/// file
+/// This function will return an error if the provided `path` doesn't exist, if
+/// the process lacks permissions to view the contents or if the `path` points
+/// at a non-directory file
 pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
     let err = LocalIo::maybe_raise(|io| {
         Ok(try!(io.fs_readdir(&path.to_c_str(), 0)).move_iter().map(|a| {
@@ -697,8 +697,7 @@ fn next(&mut self) -> Option<Path> {
 ///
 /// # Error
 ///
-/// This function will return an `Err` value if an error happens, see
-/// `fs::mkdir` for more information about error conditions and performance.
+/// See `fs::mkdir`.
 pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> {
     // tjc: if directory exists but with different permissions,
     // should we return false?
@@ -735,8 +734,7 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> {
 ///
 /// # Error
 ///
-/// This function will return an `Err` value if an error happens. See
-/// `file::unlink` and `fs::readdir` for possible error conditions.
+/// See `file::unlink` and `fs::readdir`
 pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
     let mut rm_stack = Vec::new();
     rm_stack.push(path.clone());
@@ -957,7 +955,7 @@ macro_rules! error( ($e:expr, $s:expr) => (
         }
     ) )
 
-    struct TempDir(Path);
+    pub struct TempDir(Path);
 
     impl TempDir {
         fn join(&self, path: &str) -> Path {
index b93b84b7d63f3a6dc5eedb524f8bf6f5629e88ac..8879f7e25063cb56890d5f57daee1d5cb8717e55 100644 (file)
@@ -22,6 +22,8 @@
 use slice::{Vector, ImmutableVector, MutableVector};
 use vec::Vec;
 
+static BUF_CAPACITY: uint = 128;
+
 fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
     // compute offset as signed and clamp to prevent overflow
     let pos = match seek {
@@ -54,29 +56,26 @@ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64>
 ///
 /// assert_eq!(w.unwrap(), vec!(0, 1, 2));
 /// ```
+#[deriving(Clone)]
 pub struct MemWriter {
     buf: Vec<u8>,
-    pos: uint,
 }
 
 impl MemWriter {
     /// Create a new `MemWriter`.
     #[inline]
     pub fn new() -> MemWriter {
-        MemWriter::with_capacity(128)
+        MemWriter::with_capacity(BUF_CAPACITY)
     }
     /// Create a new `MemWriter`, allocating at least `n` bytes for
     /// the internal buffer.
     #[inline]
     pub fn with_capacity(n: uint) -> MemWriter {
-        MemWriter { buf: Vec::with_capacity(n), pos: 0 }
+        MemWriter { buf: Vec::with_capacity(n) }
     }
 
     /// Acquires an immutable reference to the underlying buffer of this
     /// `MemWriter`.
-    ///
-    /// No method is exposed for acquiring a mutable reference to the buffer
-    /// because it could corrupt the state of this `MemWriter`.
     #[inline]
     pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
 
@@ -88,44 +87,7 @@ pub fn unwrap(self) -> Vec<u8> { self.buf }
 impl Writer for MemWriter {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        // Make sure the internal buffer is as least as big as where we
-        // currently are
-        let difference = self.pos as i64 - self.buf.len() as i64;
-        if difference > 0 {
-            self.buf.grow(difference as uint, &0);
-        }
-
-        // Figure out what bytes will be used to overwrite what's currently
-        // there (left), and what will be appended on the end (right)
-        let cap = self.buf.len() - self.pos;
-        let (left, right) = if cap <= buf.len() {
-            (buf.slice_to(cap), buf.slice_from(cap))
-        } else {
-            (buf, &[])
-        };
-
-        // Do the necessary writes
-        if left.len() > 0 {
-            slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
-        }
-        if right.len() > 0 {
-            self.buf.push_all(right);
-        }
-
-        // Bump us forward
-        self.pos += buf.len();
-        Ok(())
-    }
-}
-
-impl Seek for MemWriter {
-    #[inline]
-    fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-
-    #[inline]
-    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
-        let new = try!(combine(style, self.pos, self.buf.len(), pos));
-        self.pos = new as uint;
+        self.buf.push_all(buf);
         Ok(())
     }
 }
@@ -381,30 +343,10 @@ mod test {
     #[test]
     fn test_mem_writer() {
         let mut writer = MemWriter::new();
-        assert_eq!(writer.tell(), Ok(0));
         writer.write([0]).unwrap();
-        assert_eq!(writer.tell(), Ok(1));
         writer.write([1, 2, 3]).unwrap();
         writer.write([4, 5, 6, 7]).unwrap();
-        assert_eq!(writer.tell(), Ok(8));
         assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]);
-
-        writer.seek(0, SeekSet).unwrap();
-        assert_eq!(writer.tell(), Ok(0));
-        writer.write([3, 4]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]);
-
-        writer.seek(1, SeekCur).unwrap();
-        writer.write([0, 1]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]);
-
-        writer.seek(-1, SeekEnd).unwrap();
-        writer.write([1, 2]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]);
-
-        writer.seek(1, SeekEnd).unwrap();
-        writer.write([1]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
     }
 
     #[test]
@@ -570,10 +512,6 @@ fn seek_past_end() {
         r.seek(10, SeekSet).unwrap();
         assert!(r.read(&mut []).is_err());
 
-        let mut r = MemWriter::new();
-        r.seek(10, SeekSet).unwrap();
-        assert!(r.write([3]).is_ok());
-
         let mut buf = [0];
         let mut r = BufWriter::new(buf);
         r.seek(10, SeekSet).unwrap();
@@ -589,9 +527,6 @@ fn seek_before_0() {
         let mut r = MemReader::new(vec!(10));
         assert!(r.seek(-1, SeekSet).is_err());
 
-        let mut r = MemWriter::new();
-        assert!(r.seek(-1, SeekSet).is_err());
-
         let mut buf = [0];
         let mut r = BufWriter::new(buf);
         assert!(r.seek(-1, SeekSet).is_err());
@@ -614,6 +549,7 @@ fn io_read_at_least() {
     fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) {
         let src: Vec<u8> = Vec::from_elem(len, 5);
 
+        b.bytes = (times * len) as u64;
         b.iter(|| {
             let mut wr = MemWriter::new();
             for _ in range(0, times) {
index 4277b509962cca1bdd14df052d03c2c0ab71cc4f..f1b92b973c8bb1649a0e404882f11dd878423831 100644 (file)
@@ -223,6 +223,7 @@ fn file_product(p: &Path) -> IoResult<u32> {
 
 use char::Char;
 use collections::Collection;
+use default::Default;
 use fmt;
 use int;
 use iter::Iterator;
@@ -1795,7 +1796,6 @@ pub struct UnstableFileStat {
 bitflags!(
     #[doc="A set of permissions for a file or directory is represented
 by a set of flags which are or'd together."]
-    #[deriving(Hash)]
     #[deriving(Show)]
     flags FilePermission: u32 {
         static UserRead     = 0o400,
@@ -1830,6 +1830,11 @@ pub struct UnstableFileStat {
     }
 )
 
+impl Default for FilePermission {
+    #[inline]
+    fn default() -> FilePermission { FilePermission::empty() }
+}
+
 #[cfg(test)]
 mod tests {
     use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput};
index ebcb60253f59cedbab80ce92bfde482d452e6e23..7fff510a60a4b19ae7a2c69c97c46d723b63320c 100644 (file)
@@ -651,6 +651,7 @@ pub fn dll_filename(base: &str) -> String {
 pub fn self_exe_name() -> Option<Path> {
 
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     fn load_self() -> Option<Vec<u8>> {
         unsafe {
             use libc::funcs::bsd44::*;
@@ -913,6 +914,16 @@ fn errno_location() -> *const c_int {
         }
     }
 
+    #[cfg(target_os = "dragonfly")]
+    fn errno_location() -> *const c_int {
+        extern {
+            fn __dfly_error() -> *const c_int;
+        }
+        unsafe {
+            __dfly_error()
+        }
+    }
+
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
     fn errno_location() -> *const c_int {
@@ -961,6 +972,7 @@ fn strerror(errnum: uint) -> String {
         #[cfg(target_os = "ios")]
         #[cfg(target_os = "android")]
         #[cfg(target_os = "freebsd")]
+        #[cfg(target_os = "dragonfly")]
         fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t)
                       -> c_int {
             extern {
@@ -1167,6 +1179,7 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
     use rt;
 
@@ -1767,6 +1780,37 @@ pub mod consts {
     pub static EXE_EXTENSION: &'static str = "";
 }
 
+#[cfg(target_os = "dragonfly")]
+pub mod consts {
+    pub use os::arch_consts::ARCH;
+
+    pub static FAMILY: &'static str = "unix";
+
+    /// A string describing the specific operating system in use: in this
+    /// case, `dragonfly`.
+    pub static SYSNAME: &'static str = "dragonfly";
+
+    /// Specifies the filename prefix used for shared libraries on this
+    /// platform: in this case, `lib`.
+    pub static DLL_PREFIX: &'static str = "lib";
+
+    /// Specifies the filename suffix used for shared libraries on this
+    /// platform: in this case, `.so`.
+    pub static DLL_SUFFIX: &'static str = ".so";
+
+    /// Specifies the file extension used for shared libraries on this
+    /// platform that goes after the dot: in this case, `so`.
+    pub static DLL_EXTENSION: &'static str = "so";
+
+    /// Specifies the filename suffix used for executable binaries on this
+    /// platform: in this case, the empty string.
+    pub static EXE_SUFFIX: &'static str = "";
+
+    /// Specifies the file extension, if any, used for executable binaries
+    /// on this platform: in this case, the empty string.
+    pub static EXE_EXTENSION: &'static str = "";
+}
+
 #[cfg(target_os = "android")]
 pub mod consts {
     pub use os::arch_consts::ARCH;
index 0c93f8e6de979cde2a8cee3e15a80982e83c48e7..1e9ec32d759435baebbc3122097421f182676728 100644 (file)
@@ -178,16 +178,13 @@ fn as_str<'a>(&'a self) -> Option<&'a str> {
     fn into_vec(self) -> Vec<u8>;
 
     /// Returns an object that implements `Show` for printing paths
-    ///
-    /// This will print the equivalent of `to_display_str()` when used with a {} format parameter.
     fn display<'a>(&'a self) -> Display<'a, Self> {
         Display{ path: self, filename: false }
     }
 
     /// Returns an object that implements `Show` for printing filenames
     ///
-    /// This will print the equivalent of `to_filename_display_str()` when used with a {}
-    /// format parameter. If there is no filename, nothing will be printed.
+    /// If there is no filename, nothing will be printed.
     fn filename_display<'a>(&'a self) -> Display<'a, Self> {
         Display{ path: self, filename: true }
     }
index d075f9a1205c7062903b8f76b94824cf820df3b9..80493ebb4a936907563cf443e9689a7b68cc1997 100644 (file)
@@ -464,11 +464,15 @@ fn backtrace_syminfo(state: *mut backtrace_state,
         // the symbols. The libbacktrace API also states that the filename must
         // be in "permanent memory", so we copy it to a static and then use the
         // static as the pointer.
+        //
+        // FIXME: We also call self_exe_name() on DragonFly BSD. I haven't
+        //        tested if this is required or not.
         unsafe fn init_state() -> *mut backtrace_state {
             static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state;
             static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256];
             if !STATE.is_null() { return STATE }
-            let selfname = if cfg!(target_os = "freebsd") {
+            let selfname = if cfg!(target_os = "freebsd") ||
+                              cfg!(target_os = "dragonfly") {
                 os::self_exe_name()
             } else {
                 None
index 0ffac99775c11a75ceac8651d1083d98b41ba7fc..1717aeb84300013696e1d92576015a83b7393377 100644 (file)
 #[link(name = "pthread")]
 extern {}
 
+#[cfg(target_os = "dragonfly")]
+#[link(name = "pthread")]
+extern {}
+
 #[cfg(target_os = "macos")]
 #[link(name = "System")]
 extern {}
index 6f809383620494f4cb58ae940a4b0a437d330e20..c50a5661973f5ed69f109388032e13ab01a6f385 100644 (file)
@@ -11,7 +11,8 @@
 use std::fmt;
 
 #[deriving(PartialEq)]
-pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, }
+pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS,
+              OsDragonfly }
 
 #[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)]
 pub enum Abi {
@@ -150,7 +151,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             OsMacos => "macos".fmt(f),
             OsiOS => "ios".fmt(f),
             OsAndroid => "android".fmt(f),
-            OsFreebsd => "freebsd".fmt(f)
+            OsFreebsd => "freebsd".fmt(f),
+            OsDragonfly => "dragonfly".fmt(f)
         }
     }
 }
index 8159aee99d12c5bee1008f62b6aeefb67f6ddcea..e19d39a4dc53a5ce16d6226cbd7e5b202041e2da 100644 (file)
@@ -334,8 +334,10 @@ pub enum Pat_ {
     /// records this pattern's NodeId in an auxiliary
     /// set (of "PatIdents that refer to nullary enums")
     PatIdent(BindingMode, SpannedIdent, Option<Gc<Pat>>),
-    PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where
-                                     * we don't bind the fields to names */
+
+    /// "None" means a * pattern where we don't bind the fields to names.
+    PatEnum(Path, Option<Vec<Gc<Pat>>>),
+
     PatStruct(Path, Vec<FieldPat>, bool),
     PatTup(Vec<Gc<Pat>>),
     PatBox(Gc<Pat>),
index a66d6839ab0743d5d5884c8507b1515a4784b07d..d00406e07b77dcacd6066f43c1cbed23e1b7e56d 100644 (file)
@@ -382,6 +382,9 @@ fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
     syntax_expanders.insert(intern("quote_pat"),
                        builtin_normal_expander(
                             ext::quote::expand_quote_pat));
+    syntax_expanders.insert(intern("quote_arm"),
+                       builtin_normal_expander(
+                            ext::quote::expand_quote_arm));
     syntax_expanders.insert(intern("quote_stmt"),
                        builtin_normal_expander(
                             ext::quote::expand_quote_stmt));
index 7d683382589b90bed49df493c08363c89c3f25b0..6c9e113f41a4c5f2514cfe671b5df77353fe65a9 100644 (file)
@@ -170,6 +170,13 @@ fn pat_enum(&self, span: Span, path: ast::Path,
                 subpats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat>;
     fn pat_struct(&self, span: Span,
                   path: ast::Path, field_pats: Vec<ast::FieldPat> ) -> Gc<ast::Pat>;
+    fn pat_tuple(&self, span: Span, pats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat>;
+
+    fn pat_some(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat>;
+    fn pat_none(&self, span: Span) -> Gc<ast::Pat>;
+
+    fn pat_ok(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat>;
+    fn pat_err(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat>;
 
     fn arm(&self, span: Span, pats: Vec<Gc<ast::Pat>> , expr: Gc<ast::Expr>) -> ast::Arm;
     fn arm_unreachable(&self, span: Span) -> ast::Arm;
@@ -178,6 +185,7 @@ fn pat_struct(&self, span: Span,
     fn expr_if(&self, span: Span,
                cond: Gc<ast::Expr>, then: Gc<ast::Expr>,
                els: Option<Gc<ast::Expr>>) -> Gc<ast::Expr>;
+    fn expr_loop(&self, span: Span, block: P<ast::Block>) -> Gc<ast::Expr>;
 
     fn lambda_fn_decl(&self, span: Span,
                       fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr>;
@@ -777,6 +785,46 @@ fn pat_struct(&self, span: Span,
         let pat = ast::PatStruct(path, field_pats, false);
         self.pat(span, pat)
     }
+    fn pat_tuple(&self, span: Span, pats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat> {
+        let pat = ast::PatTup(pats);
+        self.pat(span, pat)
+    }
+
+    fn pat_some(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+        let some = vec!(
+            self.ident_of("std"),
+            self.ident_of("option"),
+            self.ident_of("Some"));
+        let path = self.path_global(span, some);
+        self.pat_enum(span, path, vec!(pat))
+    }
+
+    fn pat_none(&self, span: Span) -> Gc<ast::Pat> {
+        let some = vec!(
+            self.ident_of("std"),
+            self.ident_of("option"),
+            self.ident_of("None"));
+        let path = self.path_global(span, some);
+        self.pat_enum(span, path, vec!())
+    }
+
+    fn pat_ok(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+        let some = vec!(
+            self.ident_of("std"),
+            self.ident_of("result"),
+            self.ident_of("Ok"));
+        let path = self.path_global(span, some);
+        self.pat_enum(span, path, vec!(pat))
+    }
+
+    fn pat_err(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+        let some = vec!(
+            self.ident_of("std"),
+            self.ident_of("result"),
+            self.ident_of("Err"));
+        let path = self.path_global(span, some);
+        self.pat_enum(span, path, vec!(pat))
+    }
 
     fn arm(&self, _span: Span, pats: Vec<Gc<ast::Pat>> , expr: Gc<ast::Expr>) -> ast::Arm {
         ast::Arm {
@@ -803,6 +851,10 @@ fn expr_if(&self, span: Span,
         self.expr(span, ast::ExprIf(cond, self.block_expr(then), els))
     }
 
+    fn expr_loop(&self, span: Span, block: P<ast::Block>) -> Gc<ast::Expr> {
+        self.expr(span, ast::ExprLoop(block, None))
+    }
+
     fn lambda_fn_decl(&self, span: Span,
                       fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr> {
         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
index 3b098ea8a3dfd5278bda47a061e579cf31592d9f..808532d55bb2e924ead563cadc2a41d4fd9464c1 100644 (file)
@@ -536,13 +536,16 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
                 } => {
                     // take it apart:
                     let Local {
-                        ty: _,
+                        ty: ty,
                         pat: pat,
                         init: init,
                         id: id,
                         span: span,
                         source: source,
                     } = **local;
+                    // expand the ty since TyFixedLengthVec contains an Expr
+                    // and thus may have a macro use
+                    let expanded_ty = fld.fold_ty(ty);
                     // expand the pat (it might contain macro uses):
                     let expanded_pat = fld.fold_pat(pat);
                     // find the PatIdents in the pattern:
@@ -566,7 +569,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
                     let new_init_opt = init.map(|e| fld.fold_expr(e));
                     let rewritten_local =
                         box(GC) Local {
-                            ty: local.ty,
+                            ty: expanded_ty,
                             pat: rewritten_pat,
                             init: new_init_opt,
                             id: id,
index a7ede6f742d9f86718bd5fbefc929e0289cd2000..dcfb019812774ff94ed6b312d0185ff35fc7aee9 100644 (file)
@@ -144,8 +144,10 @@ fn to_source(&self) -> String {
     impl_to_source!(Generics, generics_to_string)
     impl_to_source!(Gc<ast::Item>, item_to_string)
     impl_to_source!(Gc<ast::Method>, method_to_string)
+    impl_to_source!(Gc<ast::Stmt>, stmt_to_string)
     impl_to_source!(Gc<ast::Expr>, expr_to_string)
     impl_to_source!(Gc<ast::Pat>, pat_to_string)
+    impl_to_source!(ast::Arm, arm_to_string)
     impl_to_source_slice!(ast::Ty, ", ")
     impl_to_source_slice!(Gc<ast::Item>, "\n\n")
 
@@ -239,11 +241,13 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
     impl_to_tokens!(ast::Ident)
     impl_to_tokens!(Gc<ast::Item>)
     impl_to_tokens!(Gc<ast::Pat>)
+    impl_to_tokens!(ast::Arm)
     impl_to_tokens!(Gc<ast::Method>)
     impl_to_tokens_lifetime!(&'a [Gc<ast::Item>])
     impl_to_tokens!(ast::Ty)
     impl_to_tokens_lifetime!(&'a [ast::Ty])
     impl_to_tokens!(Generics)
+    impl_to_tokens!(Gc<ast::Stmt>)
     impl_to_tokens!(Gc<ast::Expr>)
     impl_to_tokens!(ast::Block)
     impl_to_tokens!(ast::Arg)
@@ -345,6 +349,14 @@ pub fn expand_quote_pat(cx: &mut ExtCtxt,
     base::MacExpr::new(expanded)
 }
 
+pub fn expand_quote_arm(cx: &mut ExtCtxt,
+                        sp: Span,
+                        tts: &[ast::TokenTree])
+                        -> Box<base::MacResult> {
+    let expanded = expand_parse_call(cx, sp, "parse_arm", vec!(), tts);
+    base::MacExpr::new(expanded)
+}
+
 pub fn expand_quote_ty(cx: &mut ExtCtxt,
                        sp: Span,
                        tts: &[ast::TokenTree])
index 0116518d537a75dee4ddb72c2dc878c26683583a..945a643d2b4780d1426db72861e9fe64a9f29d9d 100644 (file)
@@ -1954,19 +1954,6 @@ pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
             token::BINOP(token::OR) |  token::OROR => {
                 return self.parse_lambda_expr();
             },
-            _ if self.eat_keyword(keywords::Proc) => {
-                let decl = self.parse_proc_decl();
-                let body = self.parse_expr();
-                let fakeblock = P(ast::Block {
-                        view_items: Vec::new(),
-                        stmts: Vec::new(),
-                        expr: Some(body),
-                        id: ast::DUMMY_NODE_ID,
-                        rules: DefaultBlock,
-                        span: body.span,
-                    });
-                return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
-            },
             // FIXME #13626: Should be able to stick in
             // token::SELF_KEYWORD_NAME
             token::IDENT(id @ ast::Ident{
@@ -1978,48 +1965,6 @@ pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
                 ex = ExprPath(path);
                 hi = self.last_span.hi;
             }
-            _ if self.eat_keyword(keywords::If) => {
-                return self.parse_if_expr();
-            },
-            _ if self.eat_keyword(keywords::For) => {
-                return self.parse_for_expr(None);
-            },
-            _ if self.eat_keyword(keywords::While) => {
-                return self.parse_while_expr();
-            },
-            _ if Parser::token_is_lifetime(&self.token) => {
-                let lifetime = self.get_lifetime();
-                self.bump();
-                self.expect(&token::COLON);
-                if self.eat_keyword(keywords::For) {
-                    return self.parse_for_expr(Some(lifetime))
-                } else if self.eat_keyword(keywords::Loop) {
-                    return self.parse_loop_expr(Some(lifetime))
-                } else {
-                    self.fatal("expected `for` or `loop` after a label")
-                }
-            },
-            _ if self.eat_keyword(keywords::Loop) => {
-                return self.parse_loop_expr(None);
-            },
-            _ if self.eat_keyword(keywords::Continue) => {
-                let lo = self.span.lo;
-                let ex = if Parser::token_is_lifetime(&self.token) {
-                    let lifetime = self.get_lifetime();
-                    self.bump();
-                    ExprAgain(Some(lifetime))
-                } else {
-                    ExprAgain(None)
-                };
-                let hi = self.span.hi;
-                return self.mk_expr(lo, hi, ex);
-            },
-            _ if self.eat_keyword(keywords::Match) => {
-                return self.parse_match_expr();
-            },
-            _ if self.eat_keyword(keywords::Unsafe) => {
-                return self.parse_block_expr(lo, UnsafeBlock(ast::UserProvided));
-            },
             token::LBRACKET => {
                 self.bump();
 
@@ -2057,88 +2002,158 @@ pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
                 }
                 hi = self.last_span.hi;
             },
-            _ if self.eat_keyword(keywords::Return) => {
-                // RETURN expression
-                if can_begin_expr(&self.token) {
-                    let e = self.parse_expr();
-                    hi = e.span.hi;
-                    ex = ExprRet(Some(e));
-                } else { ex = ExprRet(None); }
-            },
-            _ if self.eat_keyword(keywords::Break) => {
-                // BREAK expression
+            _ => {
+                if self.eat_keyword(keywords::Proc) {
+                    let decl = self.parse_proc_decl();
+                    let body = self.parse_expr();
+                    let fakeblock = P(ast::Block {
+                            view_items: Vec::new(),
+                            stmts: Vec::new(),
+                            expr: Some(body),
+                            id: ast::DUMMY_NODE_ID,
+                            rules: DefaultBlock,
+                            span: body.span,
+                        });
+                    return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
+                }
+                if self.eat_keyword(keywords::If) {
+                    return self.parse_if_expr();
+                }
+                if self.eat_keyword(keywords::For) {
+                    return self.parse_for_expr(None);
+                }
+                if self.eat_keyword(keywords::While) {
+                    return self.parse_while_expr();
+                }
                 if Parser::token_is_lifetime(&self.token) {
                     let lifetime = self.get_lifetime();
                     self.bump();
-                    ex = ExprBreak(Some(lifetime));
-                } else {
-                    ex = ExprBreak(None);
+                    self.expect(&token::COLON);
+                    if self.eat_keyword(keywords::For) {
+                        return self.parse_for_expr(Some(lifetime))
+                    }
+                    if self.eat_keyword(keywords::Loop) {
+                        return self.parse_loop_expr(Some(lifetime))
+                    }
+                    self.fatal("expected `for` or `loop` after a label")
                 }
-                hi = self.span.hi;
-            },
-            _ if self.token == token::MOD_SEP ||
-                is_ident(&self.token) && !self.is_keyword(keywords::True) &&
-                !self.is_keyword(keywords::False) => {
-                let pth = self.parse_path(LifetimeAndTypesWithColons).path;
-
-                // `!`, as an operator, is prefix, so we know this isn't that
-                if self.token == token::NOT {
-                    // MACRO INVOCATION expression
-                    self.bump();
-
-                    let ket = token::close_delimiter_for(&self.token)
-                        .unwrap_or_else(|| self.fatal("expected open delimiter"));
-                    self.bump();
-
-                    let tts = self.parse_seq_to_end(&ket,
-                                                    seq_sep_none(),
-                                                    |p| p.parse_token_tree());
+                if self.eat_keyword(keywords::Loop) {
+                    return self.parse_loop_expr(None);
+                }
+                if self.eat_keyword(keywords::Continue) {
+                    let lo = self.span.lo;
+                    let ex = if Parser::token_is_lifetime(&self.token) {
+                        let lifetime = self.get_lifetime();
+                        self.bump();
+                        ExprAgain(Some(lifetime))
+                    } else {
+                        ExprAgain(None)
+                    };
                     let hi = self.span.hi;
+                    return self.mk_expr(lo, hi, ex);
+                }
+                if self.eat_keyword(keywords::Match) {
+                    return self.parse_match_expr();
+                }
+                if self.eat_keyword(keywords::Unsafe) {
+                    return self.parse_block_expr(
+                        lo,
+                        UnsafeBlock(ast::UserProvided));
+                }
+                if self.eat_keyword(keywords::Return) {
+                    // RETURN expression
+                    if can_begin_expr(&self.token) {
+                        let e = self.parse_expr();
+                        hi = e.span.hi;
+                        ex = ExprRet(Some(e));
+                    } else {
+                        ex = ExprRet(None);
+                    }
+                } else if self.eat_keyword(keywords::Break) {
+                    // BREAK expression
+                    if Parser::token_is_lifetime(&self.token) {
+                        let lifetime = self.get_lifetime();
+                        self.bump();
+                        ex = ExprBreak(Some(lifetime));
+                    } else {
+                        ex = ExprBreak(None);
+                    }
+                    hi = self.span.hi;
+                } else if self.token == token::MOD_SEP ||
+                        is_ident(&self.token) &&
+                        !self.is_keyword(keywords::True) &&
+                        !self.is_keyword(keywords::False) {
+                    let pth =
+                        self.parse_path(LifetimeAndTypesWithColons).path;
+
+                    // `!`, as an operator, is prefix, so we know this isn't that
+                    if self.token == token::NOT {
+                        // MACRO INVOCATION expression
+                        self.bump();
 
-                    return self.mk_mac_expr(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT));
-                } else if self.token == token::LBRACE {
-                    // This is a struct literal, unless we're prohibited from
-                    // parsing struct literals here.
-                    if self.restriction != RESTRICT_NO_STRUCT_LITERAL {
-                        // It's a struct literal.
+                        let ket = token::close_delimiter_for(&self.token)
+                            .unwrap_or_else(|| {
+                                self.fatal("expected open delimiter")
+                            });
                         self.bump();
-                        let mut fields = Vec::new();
-                        let mut base = None;
 
-                        while self.token != token::RBRACE {
-                            if self.eat(&token::DOTDOT) {
-                                base = Some(self.parse_expr());
-                                break;
+                        let tts = self.parse_seq_to_end(
+                            &ket,
+                            seq_sep_none(),
+                            |p| p.parse_token_tree());
+                        let hi = self.span.hi;
+
+                        return self.mk_mac_expr(lo,
+                                                hi,
+                                                MacInvocTT(pth,
+                                                           tts,
+                                                           EMPTY_CTXT));
+                    }
+                    if self.token == token::LBRACE {
+                        // This is a struct literal, unless we're prohibited
+                        // from parsing struct literals here.
+                        if self.restriction != RESTRICT_NO_STRUCT_LITERAL {
+                            // It's a struct literal.
+                            self.bump();
+                            let mut fields = Vec::new();
+                            let mut base = None;
+
+                            while self.token != token::RBRACE {
+                                if self.eat(&token::DOTDOT) {
+                                    base = Some(self.parse_expr());
+                                    break;
+                                }
+
+                                fields.push(self.parse_field());
+                                self.commit_expr(fields.last().unwrap().expr,
+                                                 &[token::COMMA],
+                                                 &[token::RBRACE]);
                             }
 
-                            fields.push(self.parse_field());
-                            self.commit_expr(fields.last().unwrap().expr,
-                                             &[token::COMMA], &[token::RBRACE]);
-                        }
+                            if fields.len() == 0 && base.is_none() {
+                                let last_span = self.last_span;
+                                self.span_err(last_span,
+                                              "structure literal must either \
+                                              have at least one field or use \
+                                              functional structure update \
+                                              syntax");
+                            }
 
-                        if fields.len() == 0 && base.is_none() {
-                            let last_span = self.last_span;
-                            self.span_err(last_span,
-                                          "structure literal must either have at \
-                                          least one field or use functional \
-                                          structure update syntax");
+                            hi = self.span.hi;
+                            self.expect(&token::RBRACE);
+                            ex = ExprStruct(pth, fields, base);
+                            return self.mk_expr(lo, hi, ex);
                         }
-
-                        hi = self.span.hi;
-                        self.expect(&token::RBRACE);
-                        ex = ExprStruct(pth, fields, base);
-                        return self.mk_expr(lo, hi, ex);
                     }
-                }
 
-            hi = pth.span.hi;
-            ex = ExprPath(pth);
-            },
-            _ => {
-                // other literal expression
-                let lit = self.parse_lit();
-                hi = lit.span.hi;
-                ex = ExprLit(box(GC) lit);
+                    hi = pth.span.hi;
+                    ex = ExprPath(pth);
+                } else {
+                    // other literal expression
+                    let lit = self.parse_lit();
+                    hi = lit.span.hi;
+                    ex = ExprLit(box(GC) lit);
+                }
             }
         }
 
@@ -2501,37 +2516,41 @@ pub fn parse_prefix_expr(&mut self) -> Gc<Expr> {
               }
             };
           }
-          token::IDENT(_, _) if self.is_keyword(keywords::Box) => {
-            self.bump();
+          token::IDENT(_, _) => {
+              if self.is_keyword(keywords::Box) {
+                self.bump();
 
-            // Check for a place: `box(PLACE) EXPR`.
-            if self.eat(&token::LPAREN) {
-                // Support `box() EXPR` as the default.
-                if !self.eat(&token::RPAREN) {
-                    let place = self.parse_expr();
-                    self.expect(&token::RPAREN);
-                    let subexpression = self.parse_prefix_expr();
-                    hi = subexpression.span.hi;
-                    ex = ExprBox(place, subexpression);
-                    return self.mk_expr(lo, hi, ex);
+                // Check for a place: `box(PLACE) EXPR`.
+                if self.eat(&token::LPAREN) {
+                    // Support `box() EXPR` as the default.
+                    if !self.eat(&token::RPAREN) {
+                        let place = self.parse_expr();
+                        self.expect(&token::RPAREN);
+                        let subexpression = self.parse_prefix_expr();
+                        hi = subexpression.span.hi;
+                        ex = ExprBox(place, subexpression);
+                        return self.mk_expr(lo, hi, ex);
+                    }
                 }
-            }
 
-            // Otherwise, we use the unique pointer default.
-            let subexpression = self.parse_prefix_expr();
-            hi = subexpression.span.hi;
-            // HACK: turn `box [...]` into a boxed-vec
-            ex = match subexpression.node {
-                ExprVec(..) | ExprRepeat(..) => {
-                    let last_span = self.last_span;
-                    self.obsolete(last_span, ObsoleteOwnedVector);
-                    ExprVstore(subexpression, ExprVstoreUniq)
-                }
-                ExprLit(lit) if lit_is_str(lit) => {
-                    ExprVstore(subexpression, ExprVstoreUniq)
-                }
-                _ => self.mk_unary(UnUniq, subexpression)
-            };
+                // Otherwise, we use the unique pointer default.
+                let subexpression = self.parse_prefix_expr();
+                hi = subexpression.span.hi;
+                // HACK: turn `box [...]` into a boxed-vec
+                ex = match subexpression.node {
+                    ExprVec(..) | ExprRepeat(..) => {
+                        let last_span = self.last_span;
+                        self.obsolete(last_span, ObsoleteOwnedVector);
+                        ExprVstore(subexpression, ExprVstoreUniq)
+                    }
+                    ExprLit(lit) if lit_is_str(lit) => {
+                        ExprVstore(subexpression, ExprVstoreUniq)
+                    }
+                    _ => self.mk_unary(UnUniq, subexpression)
+                };
+              } else {
+                return self.parse_dot_or_call_expr()
+              }
           }
           _ => return self.parse_dot_or_call_expr()
         }
@@ -2708,37 +2727,41 @@ fn parse_match_expr(&mut self) -> Gc<Expr> {
         self.commit_expr_expecting(discriminant, token::LBRACE);
         let mut arms: Vec<Arm> = Vec::new();
         while self.token != token::RBRACE {
-            let attrs = self.parse_outer_attributes();
-            let pats = self.parse_pats();
-            let mut guard = None;
-            if self.eat_keyword(keywords::If) {
-                guard = Some(self.parse_expr());
-            }
-            self.expect(&token::FAT_ARROW);
-            let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
-
-            let require_comma =
-                !classify::expr_is_simple_block(expr)
-                && self.token != token::RBRACE;
-
-            if require_comma {
-                self.commit_expr(expr, &[token::COMMA], &[token::RBRACE]);
-            } else {
-                self.eat(&token::COMMA);
-            }
-
-            arms.push(ast::Arm {
-                attrs: attrs,
-                pats: pats,
-                guard: guard,
-                body: expr
-            });
+            arms.push(self.parse_arm());
         }
         let hi = self.span.hi;
         self.bump();
         return self.mk_expr(lo, hi, ExprMatch(discriminant, arms));
     }
 
+    pub fn parse_arm(&mut self) -> Arm {
+        let attrs = self.parse_outer_attributes();
+        let pats = self.parse_pats();
+        let mut guard = None;
+        if self.eat_keyword(keywords::If) {
+            guard = Some(self.parse_expr());
+        }
+        self.expect(&token::FAT_ARROW);
+        let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
+
+        let require_comma =
+            !classify::expr_is_simple_block(expr)
+            && self.token != token::RBRACE;
+
+        if require_comma {
+            self.commit_expr(expr, &[token::COMMA], &[token::RBRACE]);
+        } else {
+            self.eat(&token::COMMA);
+        }
+
+        ast::Arm {
+            attrs: attrs,
+            pats: pats,
+            guard: guard,
+            body: expr,
+        }
+    }
+
     /// Parse an expression
     pub fn parse_expr(&mut self) -> Gc<Expr> {
         return self.parse_expr_res(UNRESTRICTED);
@@ -3832,17 +3855,6 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
                 }
                 SelfStatic
             }
-            token::IDENT(..) if self.is_self_ident() => {
-                let self_ident = self.expect_self_ident();
-
-                // Determine whether this is the fully explicit form, `self:
-                // TYPE`.
-                if self.eat(&token::COLON) {
-                    SelfExplicit(self.parse_ty(false), self_ident)
-                } else {
-                    SelfValue(self_ident)
-                }
-            }
             token::BINOP(token::STAR) => {
                 // Possibly "*self" or "*mut self" -- not supported. Try to avoid
                 // emitting cryptic "unexpected token" errors.
@@ -3860,30 +3872,47 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
                 // error case, making bogus self ident:
                 SelfValue(special_idents::self_)
             }
-            _ if Parser::token_is_mutability(&self.token) &&
-                    self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
-                mutbl_self = self.parse_mutability();
-                let self_ident = self.expect_self_ident();
-
-                // Determine whether this is the fully explicit form, `self:
-                // TYPE`.
-                if self.eat(&token::COLON) {
-                    SelfExplicit(self.parse_ty(false), self_ident)
+            token::IDENT(..) => {
+                if self.is_self_ident() {
+                    let self_ident = self.expect_self_ident();
+
+                    // Determine whether this is the fully explicit form, `self:
+                    // TYPE`.
+                    if self.eat(&token::COLON) {
+                        SelfExplicit(self.parse_ty(false), self_ident)
+                    } else {
+                        SelfValue(self_ident)
+                    }
+                } else if Parser::token_is_mutability(&self.token) &&
+                        self.look_ahead(1, |t| {
+                            token::is_keyword(keywords::Self, t)
+                        }) {
+                    mutbl_self = self.parse_mutability();
+                    let self_ident = self.expect_self_ident();
+
+                    // Determine whether this is the fully explicit form,
+                    // `self: TYPE`.
+                    if self.eat(&token::COLON) {
+                        SelfExplicit(self.parse_ty(false), self_ident)
+                    } else {
+                        SelfValue(self_ident)
+                    }
+                } else if Parser::token_is_mutability(&self.token) &&
+                        self.look_ahead(1, |t| *t == token::TILDE) &&
+                        self.look_ahead(2, |t| {
+                            token::is_keyword(keywords::Self, t)
+                        }) {
+                    mutbl_self = self.parse_mutability();
+                    self.bump();
+                    drop(self.expect_self_ident());
+                    let last_span = self.last_span;
+                    self.obsolete(last_span, ObsoleteOwnedSelf);
+                    SelfStatic
                 } else {
-                    SelfValue(self_ident)
+                    SelfStatic
                 }
             }
-            _ if Parser::token_is_mutability(&self.token) &&
-                    self.look_ahead(1, |t| *t == token::TILDE) &&
-                    self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
-                mutbl_self = self.parse_mutability();
-                self.bump();
-                drop(self.expect_self_ident());
-                let last_span = self.last_span;
-                self.obsolete(last_span, ObsoleteOwnedSelf);
-                SelfStatic
-            }
-            _ => SelfStatic
+            _ => SelfStatic,
         };
 
         let explicit_self_sp = mk_sp(lo, self.span.hi);
index ac8355651916e0a5c03b2b4d9da6c5cc6c994f83..675588a4460fffd3ba82f3cfbaefed12040bd5c1 100644 (file)
@@ -18,7 +18,6 @@
 use codemap::{CodeMap, BytePos};
 use codemap;
 use diagnostic;
-use parse::classify::expr_is_simple_block;
 use parse::token;
 use parse::lexer::comments;
 use parse;
@@ -137,7 +136,7 @@ pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
         // downcasts.
         let (_, wr): (uint, Box<MemWriter>) = mem::transmute_copy(&s.s.out);
         let result =
-            String::from_utf8(Vec::from_slice(wr.get_ref())).unwrap();
+            String::from_utf8(Vec::from_slice(wr.get_ref().as_slice())).unwrap();
         mem::forget(wr);
         result.to_string()
     }
@@ -151,6 +150,10 @@ pub fn pat_to_string(pat: &ast::Pat) -> String {
     to_string(|s| s.print_pat(pat))
 }
 
+pub fn arm_to_string(arm: &ast::Arm) -> String {
+    to_string(|s| s.print_arm(arm))
+}
+
 pub fn expr_to_string(e: &ast::Expr) -> String {
     to_string(|s| s.print_expr(e))
 }
@@ -1402,53 +1405,8 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                 try!(self.print_expr(&**expr));
                 try!(space(&mut self.s));
                 try!(self.bopen());
-                let len = arms.len();
-                for (i, arm) in arms.iter().enumerate() {
-                    // I have no idea why this check is necessary, but here it
-                    // is :(
-                    if arm.attrs.is_empty() {
-                        try!(space(&mut self.s));
-                    }
-                    try!(self.cbox(indent_unit));
-                    try!(self.ibox(0u));
-                    try!(self.print_outer_attributes(arm.attrs.as_slice()));
-                    let mut first = true;
-                    for p in arm.pats.iter() {
-                        if first {
-                            first = false;
-                        } else {
-                            try!(space(&mut self.s));
-                            try!(self.word_space("|"));
-                        }
-                        try!(self.print_pat(&**p));
-                    }
-                    try!(space(&mut self.s));
-                    match arm.guard {
-                        Some(ref e) => {
-                            try!(self.word_space("if"));
-                            try!(self.print_expr(&**e));
-                            try!(space(&mut self.s));
-                        }
-                        None => ()
-                    }
-                    try!(self.word_space("=>"));
-
-                    match arm.body.node {
-                        ast::ExprBlock(ref blk) => {
-                            // the block will close the pattern's ibox
-                            try!(self.print_block_unclosed_indent(&**blk,
-                                                                  indent_unit));
-                        }
-                        _ => {
-                            try!(self.end()); // close the ibox for the pattern
-                            try!(self.print_expr(&*arm.body));
-                        }
-                    }
-                    if !expr_is_simple_block(expr.clone())
-                        && i < len - 1 {
-                        try!(word(&mut self.s, ","));
-                    }
-                    try!(self.end()); // close enclosing cbox
+                for arm in arms.iter() {
+                    try!(self.print_arm(arm));
                 }
                 try!(self.bclose_(expr.span, indent_unit));
             }
@@ -1882,6 +1840,51 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
         self.ann.post(self, NodePat(pat))
     }
 
+    fn print_arm(&mut self, arm: &ast::Arm) -> IoResult<()> {
+        // I have no idea why this check is necessary, but here it
+        // is :(
+        if arm.attrs.is_empty() {
+            try!(space(&mut self.s));
+        }
+        try!(self.cbox(indent_unit));
+        try!(self.ibox(0u));
+        try!(self.print_outer_attributes(arm.attrs.as_slice()));
+        let mut first = true;
+        for p in arm.pats.iter() {
+            if first {
+                first = false;
+            } else {
+                try!(space(&mut self.s));
+                try!(self.word_space("|"));
+            }
+            try!(self.print_pat(&**p));
+        }
+        try!(space(&mut self.s));
+        match arm.guard {
+            Some(ref e) => {
+                try!(self.word_space("if"));
+                try!(self.print_expr(&**e));
+                try!(space(&mut self.s));
+            }
+            None => ()
+        }
+        try!(self.word_space("=>"));
+
+        match arm.body.node {
+            ast::ExprBlock(ref blk) => {
+                // the block will close the pattern's ibox
+                try!(self.print_block_unclosed_indent(&**blk,
+                                                      indent_unit));
+            }
+            _ => {
+                try!(self.end()); // close the ibox for the pattern
+                try!(self.print_expr(&*arm.body));
+                try!(word(&mut self.s, ","));
+            }
+        }
+        self.end() // close enclosing cbox
+    }
+
     // Returns whether it printed anything
     fn print_explicit_self(&mut self,
                            explicit_self: ast::ExplicitSelf_,
index b95fc3c495eed1a994e3d0cd7f4423d30c5d5520..c7e27c0083612f100085b995cd144411207717c4 100644 (file)
@@ -11,7 +11,7 @@
 //! Types/fns concerning URLs (see RFC 3986)
 
 #![crate_name = "url"]
-#![experimental]
+#![deprecated="This is being removed. Use rust-url instead. http://servo.github.io/rust-url/"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
@@ -35,6 +35,7 @@
 /// # Example
 ///
 /// ```rust
+/// # #![allow(deprecated)]
 /// use url::Url;
 ///
 /// let raw = "https://username@example.com:8080/foo/bar?baz=qux#quz";
@@ -214,6 +215,7 @@ fn encode_inner<T: BytesContainer>(c: T, full_url: bool) -> String {
 /// # Example
 ///
 /// ```rust
+/// # #![allow(deprecated)]
 /// use url::encode;
 ///
 /// let url = encode("https://example.com/Rust (programming language)");
@@ -241,6 +243,7 @@ pub fn encode_component<T: BytesContainer>(container: T) -> String {
 /// # Example
 ///
 /// ```rust
+/// # #![allow(deprecated)]
 /// use url::decode;
 ///
 /// let url = decode("https://example.com/Rust%20(programming%20language)");
@@ -428,6 +431,7 @@ fn query_from_str(rawquery: &str) -> DecodeResult<Query> {
 /// # Example
 ///
 /// ```rust
+/// # #![allow(deprecated)]
 /// let query = vec![("title".to_string(), "The Village".to_string()),
 ///                  ("north".to_string(), "52.91".to_string()),
 ///                  ("west".to_string(), "4.10".to_string())];
@@ -453,6 +457,7 @@ pub fn query_to_str(query: &Query) -> String {
 /// # Example
 ///
 /// ```rust
+/// # #![allow(deprecated)]
 /// use url::get_scheme;
 ///
 /// let scheme = match get_scheme("https://example.com/") {
index 0e29e6215032ae104c3531a8748424bae6c0b94b..037afce9b167a7c5a404ff3906af076d7ffa8bca 100644 (file)
@@ -790,16 +790,12 @@ fn test_rand_rand() {
 
     #[test]
     fn test_serialize_round_trip() {
-        use serialize::ebml::Doc;
-        use serialize::ebml::writer::Encoder;
-        use serialize::ebml::reader::Decoder;
+        use serialize::json;
         use serialize::{Encodable, Decodable};
 
         let u = Uuid::new_v4();
-        let mut wr = MemWriter::new();
-        let _ = u.encode(&mut Encoder::new(&mut wr));
-        let doc = Doc::new(wr.get_ref());
-        let u2 = Decodable::decode(&mut Decoder::new(doc)).unwrap();
+        let s = json::encode(&u);
+        let u2 = json::decode(s.as_slice()).unwrap();
         assert_eq!(u, u2);
     }
 
index cd24b5c6633b27df2b84249a65a46a610b734494..0d999e5b315b6ff78fcea772466d985ce53fd8dc 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit cd24b5c6633b27df2b84249a65a46a610b734494
+Subproject commit 0d999e5b315b6ff78fcea772466d985ce53fd8dc
index 6ccabbf5994d5f4549f870540ec3cb4b5a0968bd..c82da57c12847af48603e9bbc1660d0a57a4e36f 100644 (file)
 
 #if defined(__APPLE__)
 #define EXHAUSTED               _rust_stack_exhausted
-#elif defined(__linux__) || defined(__FreeBSD__)
+#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
 #define EXHAUSTED               rust_stack_exhausted@PLT
 #else
 #define EXHAUSTED               rust_stack_exhausted
 #endif
 
-#if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
        .hidden MORESTACK
 #else
 #if defined(__APPLE__)
index ed077e69978a9416b2fcd8ff72da3573e33cad00..89cb27c1f1ae1473aa32a8b166f9df88c7586d46 100644 (file)
@@ -70,7 +70,7 @@ extern char **environ;
 #endif
 #endif
 
-#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__)
+#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || defined(__DragonFly__)
 extern char **environ;
 #endif
 
@@ -357,6 +357,13 @@ rust_unset_sigprocmask() {
 
 #endif
 
+#if defined(__DragonFly__)
+#include <errno.h>
+// In DragonFly __error() is an inline function and as such
+// no symbol exists for it.
+int *__dfly_error(void) { return __error(); }
+#endif
+
 //
 // Local Variables:
 // mode: C++
index bdc5bfdc10a3ab22d13bd14ee355d18ccb26a845..afba5a4dfd8c2fa0cd6176d4b6ae2d633d3722dd 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2014-07-22
+2014-07-29
index c6020df2bc2ea4ecca23acbcd532328911375eb4..049bec3d37bef9a4c32d3f634b7fb9141623e274 100644 (file)
@@ -11,9 +11,6 @@
 #![allow(unused_variable)]
 #![allow(dead_assignment)]
 
-fn cond() -> bool { fail!() }
-fn link<'a>(v: &'a uint, w: &mut &'a uint) -> bool { *w = v; true }
-
 fn separate_arms() {
     // Here both arms perform assignments, but only is illegal.
 
@@ -31,28 +28,4 @@ fn separate_arms() {
     x.clone(); // just to prevent liveness warnings
 }
 
-fn guard() {
-    // Here the guard performs a borrow. This borrow "infects" all
-    // subsequent arms (but not the prior ones).
-
-    let mut a = box 3u;
-    let mut b = box 4u;
-    let mut w = &*a;
-    match 22i {
-        _ if cond() => {
-            b = box 5u;
-        }
-
-        _ if link(&*b, &mut w) => {
-            b = box 6u; //~ ERROR cannot assign
-        }
-
-        _ => {
-            b = box 7u; //~ ERROR cannot assign
-        }
-    }
-
-    b = box 8; //~ ERROR cannot assign
-}
-
 fn main() {}
diff --git a/src/test/compile-fail/borrowck-mutate-in-guard.rs b/src/test/compile-fail/borrowck-mutate-in-guard.rs
new file mode 100644 (file)
index 0000000..8a904a3
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Enum<'a> {
+    A(&'a int),
+    B(bool),
+}
+
+fn foo() -> int {
+    let mut n = 42;
+    let mut x = A(&mut n);
+    match x {
+        A(_) if { x = B(false); false } => 1,
+        //~^ ERROR cannot assign in a pattern guard
+        A(_) if { let y = &mut x; *y = B(false); false } => 1,
+        //~^ ERROR cannot mutably borrow in a pattern guard
+        //~^^ ERROR cannot assign in a pattern guard
+        A(p) => *p,
+        B(_) => 2,
+    }
+}
+
+fn main() {
+    foo();
+}
+
diff --git a/src/test/compile-fail/deprecated-url.rs b/src/test/compile-fail/deprecated-url.rs
new file mode 100644 (file)
index 0000000..9f1c1fd
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+
+#![deny(deprecated)]
+
+extern crate url;
+
+fn main() {
+    let _ = url::Url::parse("http://example.com");
+    //~^ ERROR use of deprecated item: This is being removed. Use rust-url instead. http://servo.github.io/rust-url/
+}
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
new file mode 100644 (file)
index 0000000..a9f57a4
--- /dev/null
@@ -0,0 +1,95 @@
+#![feature(phase)]
+#![no_std]
+#![feature(globs)]
+#[phase(plugin, link)]
+extern crate std = "std";
+extern crate rt = "native";
+use std::prelude::*;
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pretty-compare-only
+// pretty-mode:typed
+// pp-exact:issue-4264.pp
+
+// #4264 fixed-length vector types
+
+pub fn foo(_: [int, ..(3 as uint)]) { }
+
+pub fn bar() {
+    static FOO: uint = ((5u as uint) - (4u as uint) as uint);
+    let _: [(), ..(FOO as uint)] = ([(() as ())] as [(), .. 1]);
+
+    let _: [(), ..(1u as uint)] = ([(() as ())] as [(), .. 1]);
+
+    let _ =
+        (((&((([(1i as int), (2 as int), (3 as int)] as [int, .. 3])) as
+                [int, .. 3]) as &[int, .. 3]) as *const _ as
+             *const [int, .. 3]) as *const [int, ..(3u as uint)] as
+            *const [int, .. 3]);
+    (match (() as ()) {
+         () => {
+             #[inline]
+             #[allow(dead_code)]
+             static __STATIC_FMTSTR:
+                    [::std::fmt::rt::Piece<'static>, ..(1u as uint)] =
+                 ([((::std::fmt::rt::String as
+                        fn(&'static str) -> core::fmt::rt::Piece<'static>)(("test"
+                                                                               as
+                                                                               &'static str))
+                       as core::fmt::rt::Piece<'static>)] as
+                     [core::fmt::rt::Piece<'static>, .. 1]);
+             let __args_vec =
+                 (&([] as &'static [core::fmt::Argument<'static>]) as
+                     &'static [core::fmt::Argument<'static>]);
+             let __args =
+                 (unsafe {
+                      ((::std::fmt::Arguments::new as
+                           unsafe fn(&'static [core::fmt::rt::Piece<'static>], &'a [core::fmt::Argument<'a>]) -> core::fmt::Arguments<'a>)((__STATIC_FMTSTR
+                                                                                                                                               as
+                                                                                                                                               [core::fmt::rt::Piece<'static>, .. 1]),
+                                                                                                                                           (__args_vec
+                                                                                                                                               as
+                                                                                                                                               &'static [core::fmt::Argument<'static>]))
+                          as core::fmt::Arguments<'static>)
+                  } as core::fmt::Arguments<'static>);
+
+
+
+
+
+
+
+
+             ((::std::fmt::format as
+                  fn(&core::fmt::Arguments<'_>) -> collections::string::String)((&(__args
+                                                                                      as
+                                                                                      core::fmt::Arguments<'static>)
+                                                                                    as
+                                                                                    &core::fmt::Arguments<'static>))
+                 as collections::string::String)
+         }
+     } as collections::string::String);
+}
+pub type Foo = [int, ..(3u as uint)];
+pub struct Bar {
+    pub x: [int, ..(3u as uint)],
+}
+pub struct TupleBar([int, ..(4u as uint)]);
+pub enum Baz { BazVariant([int, ..(5u as uint)]), }
+pub fn id<T>(x: T) -> T { (x as T) }
+pub fn use_id() {
+    let _ =
+        ((id::<[int, ..(3u as uint)]> as
+             fn([int, .. 3]) -> [int, .. 3])(([(1 as int), (2 as int),
+                                               (3 as int)] as [int, .. 3])) as
+            [int, .. 3]);
+}
+fn main() { }
diff --git a/src/test/pretty/issue-4264.rs b/src/test/pretty/issue-4264.rs
new file mode 100644 (file)
index 0000000..ad407f4
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pretty-compare-only
+// pretty-mode:typed
+// pp-exact:issue-4264.pp
+
+// #4264 fixed-length vector types
+
+pub fn foo(_: [int, ..3]) {}
+
+pub fn bar() {
+    static FOO: uint = 5u - 4u;
+    let _: [(), ..FOO] = [()];
+
+    let _ : [(), ..1u] = [()];
+
+    let _ = &([1i,2,3]) as *const _ as *const [int, ..3u];
+
+    format!("test");
+}
+
+pub type Foo = [int, ..3u];
+
+pub struct Bar {
+    pub x: [int, ..3u]
+}
+
+pub struct TupleBar([int, ..4u]);
+
+pub enum Baz {
+    BazVariant([int, ..5u])
+}
+
+pub fn id<T>(x: T) -> T { x }
+
+pub fn use_id() {
+    let _ = id::<[int, ..3u]>([1,2,3]);
+}
+
+
+fn main() {}
diff --git a/src/test/pretty/match-block-expr.rs b/src/test/pretty/match-block-expr.rs
new file mode 100644 (file)
index 0000000..44771a2
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+
+fn main() {
+    let x = match { 5i } { 1 => 5i, 2 => 6, _ => 7, };
+    assert_eq!(x , 7);
+}
index c03ad499478925cbea5dd7e6afa5774e96c3c5f6..d2f8157ef62131e9f9efd82c1e47b1c841833fad 100644 (file)
@@ -19,6 +19,6 @@ fn main() {
              "long".to_string(), "string".to_string()],
             None =>
             ["none".to_string(), "a".to_string(), "a".to_string(),
-             "a".to_string(), "a".to_string()]
+             "a".to_string(), "a".to_string()],
         };
 }
index 67c389f7e1f0870748224e1bb40db04f79517f48..6b4f579f9c51c61c966874fe4049f771ce01f003 100644 (file)
@@ -15,6 +15,6 @@ fn main() {
     let _y =
         match x {
             Some(_) => "some(_)".to_string(),
-            None => "none".to_string()
+            None => "none".to_string(),
         };
 }
index 251798fc7ed889d47de3bd9265ee8eb97b061d1b..2b7088fbc33ff2e0345af84b22f4658393e45b9a 100644 (file)
@@ -6,15 +6,16 @@ digraph block {
     N4[label="expr 777i"];
     N5[label="expr 7777i"];
     N6[label="expr [7i, 77i, 777i, 7777i]"];
-    N7[label="expr match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y }"];
-    N8[label="local x"];
-    N9[label="local y"];
-    N10[label="pat .."];
-    N11[label="pat [x, y, ..]"];
-    N12[label="expr x"];
-    N13[label="expr y"];
-    N14[label="expr x + y"];
-    N15[label="block { match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y }; }"];
+    N7[label="expr match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y, }"];
+    N8[label="(dummy_node)"];
+    N9[label="local x"];
+    N10[label="local y"];
+    N11[label="pat .."];
+    N12[label="pat [x, y, ..]"];
+    N13[label="expr x"];
+    N14[label="expr y"];
+    N15[label="expr x + y"];
+    N16[label="block { match [7i, 77i, 777i, 7777i] { [x, y, ..] => x + y, }; }"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
@@ -27,7 +28,8 @@ digraph block {
     N11 -> N12;
     N12 -> N13;
     N13 -> N14;
-    N14 -> N7;
-    N7 -> N15;
-    N15 -> N1;
+    N14 -> N15;
+    N15 -> N7;
+    N7 -> N16;
+    N16 -> N1;
 }
index 2be43dcaa7b66709a71c26802ce2282cbf8512fb..5d1d1253b22386dd5d564d060813a3fbf5229f09 100644 (file)
@@ -7,19 +7,21 @@ digraph block {
     N5[label="local x"];
     N6[label="local _y"];
     N7[label="expr x"];
-    N8[label="expr match x { E13a => _y = 1, E13b(v) => _y = v + 1 }"];
-    N9[label="local E13a"];
-    N10[label="expr 1"];
-    N11[label="expr _y"];
-    N12[label="expr _y = 1"];
-    N13[label="local v"];
-    N14[label="pat E13b(v)"];
-    N15[label="expr v"];
-    N16[label="expr 1"];
-    N17[label="expr v + 1"];
-    N18[label="expr _y"];
-    N19[label="expr _y = v + 1"];
-    N20[label="block {\l    let x = E13b(13);\l    let _y;\l    match x { E13a => _y = 1, E13b(v) => _y = v + 1 }\l}\l"];
+    N8[label="expr match x { E13a => _y = 1, E13b(v) => _y = v + 1, }"];
+    N9[label="(dummy_node)"];
+    N10[label="local E13a"];
+    N11[label="expr 1"];
+    N12[label="expr _y"];
+    N13[label="expr _y = 1"];
+    N14[label="(dummy_node)"];
+    N15[label="local v"];
+    N16[label="pat E13b(v)"];
+    N17[label="expr v"];
+    N18[label="expr 1"];
+    N19[label="expr v + 1"];
+    N20[label="expr _y"];
+    N21[label="expr _y = v + 1"];
+    N22[label="block {\l    let x = E13b(13);\l    let _y;\l    match x { E13a => _y = 1, E13b(v) => _y = v + 1, }\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
@@ -30,15 +32,17 @@ digraph block {
     N9 -> N10;
     N10 -> N11;
     N11 -> N12;
-    N12 -> N8;
-    N7 -> N13;
-    N13 -> N14;
+    N12 -> N13;
+    N13 -> N8;
+    N9 -> N14;
     N14 -> N15;
     N15 -> N16;
     N16 -> N17;
     N17 -> N18;
     N18 -> N19;
-    N19 -> N8;
-    N8 -> N20;
-    N20 -> N1;
+    N19 -> N20;
+    N20 -> N21;
+    N21 -> N8;
+    N8 -> N22;
+    N22 -> N1;
 }
diff --git a/src/test/run-make/issue-7349/Makefile b/src/test/run-make/issue-7349/Makefile
new file mode 100644 (file)
index 0000000..18ba80a
--- /dev/null
@@ -0,0 +1,11 @@
+-include ../tools.mk
+
+# Test to make sure that inner functions within a polymorphic outer function
+# don't get re-translated when the outer function is monomorphized.  The test
+# code monomorphizes the outer function several times, but the magic constant
+# `8675309` used in the inner function should appear only once in the generated
+# IR.
+
+all:
+       $(RUSTC) foo.rs --emit=ir
+       [ "$$(grep -c 8675309 "$(TMPDIR)/foo.ll")" -eq "1" ]
diff --git a/src/test/run-make/issue-7349/foo.rs b/src/test/run-make/issue-7349/foo.rs
new file mode 100644 (file)
index 0000000..775b731
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn outer<T>() {
+    #[allow(dead_code)]
+    fn inner() -> uint {
+        8675309
+    }
+}
+
+fn main() {
+    outer::<int>();
+    outer::<uint>();
+}
index 36b525c134b9940e7e01d6c26ca984edaa42f4a5..a5cf8e46b7e43033ba5242913453232fb1724949 100644 (file)
@@ -72,6 +72,8 @@ fn main() {
     let pat = quote_pat!(cx, Some(_));
     check_pp(ext_cx, pat, pprust::print_pat, "Some(_)".to_string());
 
+    let arm = quote_arm!(cx, (ref x, ref y) => (x, y));
+    check_pp(ext_cx, arm, pprust::print_stmt, "(ref x, ref y) = (x, y)".to_string());
 }
 
 fn check_pp<T>(cx: fake_ext_ctxt,
index 11c3dfb2241f74ccef7e13f3d425f950c2e6af00..60b8f09bb3dedcebaea433f0277027eba156717c 100644 (file)
@@ -26,6 +26,7 @@ fn syntax_extension(cx: &ExtCtxt) {
     let _b: Option<Gc<syntax::ast::Item>> = quote_item!(cx, static foo : int = $e_toks; );
     let _c: Gc<syntax::ast::Pat> = quote_pat!(cx, (x, 1 .. 4, *) );
     let _d: Gc<syntax::ast::Stmt> = quote_stmt!(cx, let x = $a; );
+    let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) );
     let _e: Gc<syntax::ast::Expr> = quote_expr!(cx, match foo { $p_toks => 10 } );
 
     let _f: Gc<syntax::ast::Expr> = quote_expr!(cx, ());
index a7738bb803cf5cae24f1531f9d8c9977c3841ea2..9eef83184e139e49d049bedc996a6068e53a8138 100644 (file)
@@ -16,9 +16,7 @@
 use std::cell::{Cell, RefCell};
 use std::io::MemWriter;
 use serialize::{Encodable, Decodable};
-use serialize::ebml;
-use serialize::ebml::writer::Encoder;
-use serialize::ebml::reader::Decoder;
+use serialize::json;
 
 #[deriving(Encodable, Decodable)]
 struct A {
@@ -36,20 +34,8 @@ fn main() {
         foo: Cell::new(true),
         bar: RefCell::new( A { baz: 2 } )
     };
-    let mut w = MemWriter::new();
-    {
-        let mut e = Encoder::new(&mut w);
-        match obj.encode(&mut e) {
-            Ok(()) => (),
-            Err(e) => fail!("Failed to encode: {}", e)
-        };
-    }
-    let doc = ebml::Doc::new(w.get_ref());
-    let mut dec = Decoder::new(doc);
-    let obj2: B = match Decodable::decode(&mut dec) {
-        Ok(v) => v,
-        Err(e) => fail!("Failed to decode: {}", e)
-    };
+    let s = json::encode(&obj);
+    let obj2: B = json::decode(s.as_slice()).unwrap();
     assert!(obj.foo.get() == obj2.foo.get());
     assert!(obj.bar.borrow().baz == obj2.bar.borrow().baz);
 }
index c3c22cb26d27ab074fcd5fd7e6f6afe171238fa1..76dedaba40f0bbc9d6573daf374d9bf578dc7a38 100644 (file)
@@ -23,6 +23,9 @@ mod hello;
 #[cfg(target_os = "freebsd")]
 mod hello;
 
+#[cfg(target_os = "dragonfly")]
+mod hello;
+
 #[cfg(target_os = "android")]
 mod hello;
 
index 84593ececd0af6a23005bfca1bac0e7ca5e3e657..197b92ba635263c92d757aa30d637e6091a77a27 100644 (file)
@@ -20,6 +20,7 @@ mod rusti {
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 mod m {
     #[main]
     #[cfg(target_arch = "x86")]
index 934adc07e2f15a4607feb773eca1cca544caf25f..df4342bfeb57e4fcc35dafbc08fa7f395bc3af36 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::ascii::StrAsciiExt;
+use std::ascii::AsciiExt;
 
 static NAME: &'static str = "hello world";
 
index e0cd91adb1c595724bdd945be55d390032824141..d7f487b629b5eb05817ad3f93631d0606eb1fba8 100644 (file)
 
 extern crate serialize;
 
+use std::io;
+use std::io::{IoError, IoResult, SeekStyle};
+use std::slice;
+
 use serialize::{Encodable, Encoder};
 use serialize::json;
 use serialize::ebml::writer;
-use std::io::MemWriter;
+
+static BUF_CAPACITY: uint = 128;
+
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+    // compute offset as signed and clamp to prevent overflow
+    let pos = match seek {
+        io::SeekSet => 0,
+        io::SeekEnd => end,
+        io::SeekCur => cur,
+    } as i64;
+
+    if offset + pos < 0 {
+        Err(IoError {
+            kind: io::InvalidInput,
+            desc: "invalid seek to a negative offset",
+            detail: None
+        })
+    } else {
+        Ok((offset + pos) as u64)
+    }
+}
+
+/// Writes to an owned, growable byte vector that supports seeking.
+///
+/// # Example
+///
+/// ```rust
+/// # #![allow(unused_must_use)]
+/// use std::io::SeekableMemWriter;
+///
+/// let mut w = SeekableMemWriter::new();
+/// w.write([0, 1, 2]);
+///
+/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// ```
+pub struct SeekableMemWriter {
+    buf: Vec<u8>,
+    pos: uint,
+}
+
+impl SeekableMemWriter {
+    /// Create a new `SeekableMemWriter`.
+    #[inline]
+    pub fn new() -> SeekableMemWriter {
+        SeekableMemWriter::with_capacity(BUF_CAPACITY)
+    }
+    /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+    /// the internal buffer.
+    #[inline]
+    pub fn with_capacity(n: uint) -> SeekableMemWriter {
+        SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+    }
+
+    /// Acquires an immutable reference to the underlying buffer of this
+    /// `SeekableMemWriter`.
+    ///
+    /// No method is exposed for acquiring a mutable reference to the buffer
+    /// because it could corrupt the state of this `MemWriter`.
+    #[inline]
+    pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+    /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+    #[inline]
+    pub fn unwrap(self) -> Vec<u8> { self.buf }
+}
+
+impl Writer for SeekableMemWriter {
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+        if self.pos == self.buf.len() {
+            self.buf.push_all(buf)
+        } else {
+            // Make sure the internal buffer is as least as big as where we
+            // currently are
+            let difference = self.pos as i64 - self.buf.len() as i64;
+            if difference > 0 {
+                self.buf.grow(difference as uint, &0);
+            }
+
+            // Figure out what bytes will be used to overwrite what's currently
+            // there (left), and what will be appended on the end (right)
+            let cap = self.buf.len() - self.pos;
+            let (left, right) = if cap <= buf.len() {
+                (buf.slice_to(cap), buf.slice_from(cap))
+            } else {
+                (buf, &[])
+            };
+
+            // Do the necessary writes
+            if left.len() > 0 {
+                slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+            }
+            if right.len() > 0 {
+                self.buf.push_all(right);
+            }
+        }
+
+        // Bump us forward
+        self.pos += buf.len();
+        Ok(())
+    }
+}
+
+impl Seek for SeekableMemWriter {
+    #[inline]
+    fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+    #[inline]
+    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+        let new = try!(combine(style, self.pos, self.buf.len(), pos));
+        self.pos = new as uint;
+        Ok(())
+    }
+}
 
 #[deriving(Encodable)]
 struct Foo {
@@ -34,21 +151,21 @@ enum WireProtocol {
 fn encode_json<'a,
                T: Encodable<json::Encoder<'a>,
                             std::io::IoError>>(val: &T,
-                                               wr: &'a mut MemWriter) {
+                                               wr: &'a mut SeekableMemWriter) {
     let mut encoder = json::Encoder::new(wr);
     val.encode(&mut encoder);
 }
 fn encode_ebml<'a,
-               T: Encodable<writer::Encoder<'a, MemWriter>,
+               T: Encodable<writer::Encoder<'a, SeekableMemWriter>,
                             std::io::IoError>>(val: &T,
-                                               wr: &'a mut MemWriter) {
+                                               wr: &'a mut SeekableMemWriter) {
     let mut encoder = writer::Encoder::new(wr);
     val.encode(&mut encoder);
 }
 
 pub fn main() {
     let target = Foo{baz: false,};
-    let mut wr = MemWriter::new();
+    let mut wr = SeekableMemWriter::new();
     let proto = JSON;
     match proto {
         JSON => encode_json(&target, &mut wr),
index 6330e1bf3c16e60f62b3c4e84d2f6c05a8811fee..f541ca6794f62d05dadf5755aba52e651ad24677 100644 (file)
 #[link(name = "execinfo")]
 extern {}
 
+#[cfg(target_os = "dragonfly")]
+#[link(name = "c")]
+extern {}
+
 #[cfg(target_os = "macos")]
 #[link(name = "System")]
 extern {}
diff --git a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs
new file mode 100644 (file)
index 0000000..847024d
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(macro_rules)]
+
+macro_rules! four (
+    () => (4)
+)
+fn main() {
+    let _x: [u16, ..four!()];
+}
index cf254d54793a44f0584e1bac4c287efbe5df45eb..ada012fc2f5016a64dadf33eacec5ec672ac3a77 100644 (file)
@@ -39,6 +39,7 @@ struct Outer {
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 mod m {
     #[cfg(target_arch = "x86")]
     pub mod m {
diff --git a/src/test/run-pass/spawn-stack-too-big.rs b/src/test/run-pass/spawn-stack-too-big.rs
new file mode 100644 (file)
index 0000000..e1c4a48
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-macos apparently gargantuan mmap requests are ok?
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate green;
+extern crate native;
+
+use std::task::TaskBuilder;
+use native::NativeTaskBuilder;
+
+green_start!(main)
+
+fn main() {
+    test();
+
+    let (tx, rx) = channel();
+    TaskBuilder::new().native().spawn(proc() {
+        tx.send(test());
+    });
+    rx.recv();
+}
+
+#[cfg(not(target_word_size = "64"))]
+fn test() {}
+
+#[cfg(target_word_size = "64")]
+fn test() {
+    let (tx, rx) = channel();
+    spawn(proc() {
+        TaskBuilder::new().stack_size(1024 * 1024 * 1024 * 64).spawn(proc() {
+        });
+        tx.send(());
+    });
+
+    assert!(rx.recv_opt().is_err());
+}
index b2cf771faee3cea213c4a42b91f25531a90118e4..66dbb6b161954b274059c0531d2c6591d0d34760 100644 (file)
@@ -33,5 +33,6 @@ pub fn main() {
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
 #[cfg(target_os = "android")]
 pub fn main() { }