From: bors Date: Thu, 31 Jul 2014 16:41:36 +0000 (+0000) Subject: auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=8c00357f9d60ef67479a85e8df83aa59fe690623;hp=da6070dbef81c1028ce3e87fd0102b2abbbc181e;p=rust.git auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis 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 --- diff --git a/configure b/configure index 53fb8e25c5f..e08e28e0aec 100755 --- 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 ;; diff --git a/mk/platform.mk b/mk/platform.mk index b72574f6fe3..29643ea25f7 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -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 diff --git a/mk/rt.mk b/mk/rt.mk index e41dc8f4daa..13ed4abb438 100644 --- 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 diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 6ef2a52086e..aa96f3e2727 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -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 { + 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 diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 6720b9a530f..851d12f814b 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -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(" ")) } diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs index 369e6b0af64..445e814a1eb 100644 --- a/src/compiletest/util.rs +++ b/src/compiletest/util.rs @@ -21,6 +21,7 @@ ("android", "android"), ("linux", "linux"), ("freebsd", "freebsd"), + ("dragonfly", "dragonfly"), ]; pub fn get_os(triple: &str) -> &'static str { diff --git a/src/doc/guide.md b/src/doc/guide.md index 387841ab3fc..2216d829e4b 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -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` (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 diff --git a/src/doc/index.md b/src/doc/index.md index c54f4e00905..c96f10a0be8 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -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 diff --git a/src/doc/intro.md b/src/doc/intro.md index 32c5f346de1..128d5c9d320 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -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`. diff --git a/src/doc/rust.md b/src/doc/rust.md index b015cb0fbb8..3f4be7bbf31 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -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 diff --git a/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang b/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang index 7c9780456cf..a934c426857 100644 --- a/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang +++ b/src/etc/gedit/share/gtksourceview-3.0/language-specs/rust.lang @@ -269,6 +269,14 @@ \\\%{common_escape} + + r(#*)" + "\%{1@start} + + + + + " " @@ -287,6 +295,8 @@ \] + + @@ -305,6 +315,7 @@ + diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh index e78f231b9d7..56ebd4f140f 100755 --- a/src/etc/local_stage0.sh +++ b/src/etc/local_stage0.sh @@ -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 diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py index f745f5d61cb..113c192ec07 100644 --- a/src/etc/mklldeps.py +++ b/src/etc/mklldeps.py @@ -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: diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 1ac2c9fc6be..bf477781aab 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -92,7 +92,7 @@ pub fn new(data: T) -> Arc { } #[inline] - fn inner<'a>(&'a self) -> &'a ArcInner { + fn inner(&self) -> &ArcInner { // 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 { #[experimental = "Deref is experimental."] impl Deref for Arc { #[inline] - fn deref<'a>(&'a self) -> &'a T { + fn deref(&self) -> &T { &self.inner().data } } @@ -155,7 +155,7 @@ impl Arc { /// 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> { } #[inline] - fn inner<'a>(&'a self) -> &'a ArcInner { + fn inner(&self) -> &ArcInner { // See comments above for why this is "safe" unsafe { &*self._ptr } } diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 68b6416b69b..5e3ce75eb95 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -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> Hash for DList { + 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 = list_from([]); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 64062dc0ccb..5b1722b2769 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -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, start: uint, end: uint) -> uint; } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index e5c2d985191..d9aea8b0a28 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -688,7 +688,7 @@ pub unsafe fn shift_byte(&mut self) -> Option { /// assert_eq!(s.shift_char(), Some('o')); /// assert_eq!(s.shift_char(), None); /// ``` - pub fn shift_char (&mut self) -> Option { + pub fn shift_char(&mut self) -> Option { let len = self.len(); if len == 0 { return None diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 82745663e0c..d4cf10b384f 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -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(); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index a3a82aeec5e..a3ae8e7c79e 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -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(); diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 62547b6669f..3350d8f548a 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -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; diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 96b9a6a1392..922bf768854 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -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. diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index 38bb6e355a7..b9144047df5 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -219,7 +219,7 @@ pub fn bootstrap(mut self: Box) { 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 diff --git a/src/libgreen/stack.rs b/src/libgreen/stack.rs index 633bd3c041a..af53766617c 100644 --- a/src/libgreen/stack.rs +++ b/src/libgreen/stack.rs @@ -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; diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs index 3d3b4133840..12d7b755697 100644 --- a/src/libgreen/task.rs +++ b/src/libgreen/task.rs @@ -442,15 +442,30 @@ fn spawn_sibling(mut self: Box, 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> } + 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 diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index fc4144a2868..1bc64ffcc92 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -269,7 +269,8 @@ #[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")] @@ -279,6 +280,7 @@ 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 { } diff --git a/src/liblog/directive.rs b/src/liblog/directive.rs index 2062bb4c7b1..a8def3e289d 100644 --- a/src/liblog/directive.rs +++ b/src/liblog/directive.rs @@ -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)] diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs index 9fbf3659d3f..af4d309dfe2 100644 --- a/src/libnative/io/c_unix.rs +++ b/src/libnative/io/c_unix.rs @@ -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, diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index ecdf4ad2c45..db5421481ee 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -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"] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index c3eb5e91e90..7a90ede8ca8 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -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(()) } diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index e3e6ae42526..c89a40d6513 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -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 } diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 35367ff2efa..c72d6c24a7c 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -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); }) } diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index acba750aaf4..4dd3817e475 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -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] diff --git a/src/libnum/integer.rs b/src/libnum/integer.rs index bcaebbd1368..b06e2b448d4 100644 --- a/src/libnum/integer.rs +++ b/src/libnum/integer.rs @@ -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] diff --git a/src/libnum/rational.rs b/src/libnum/rational.rs index a279ede6fa5..e0f6b4fb9af 100644 --- a/src/libnum/rational.rs +++ b/src/libnum/rational.rs @@ -38,13 +38,13 @@ pub struct Ratio { impl Ratio { - /// Create a ratio representing the integer `t`. + /// Creates a ratio representing the integer `t`. #[inline] pub fn from_integer(t: T) -> Ratio { 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 { Ratio { numer: numer, denom: denom } @@ -61,7 +61,7 @@ pub fn new(numer: T, denom: T) -> Ratio { 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 { let mut ret = self.clone(); ret.reduce(); ret } - /// Return the reciprocal + /// Returns the reciprocal. #[inline] pub fn recip(&self) -> Ratio { Ratio::new_raw(self.denom.clone(), self.numer.clone()) } + /// Rounds towards minus infinity. + #[inline] pub fn floor(&self) -> Ratio { if *self < Zero::zero() { Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) @@ -124,6 +126,8 @@ pub fn floor(&self) -> Ratio { } } + /// Rounds towards plus infinity. + #[inline] pub fn ceil(&self) -> Ratio { if *self < Zero::zero() { Ratio::from_integer(self.numer / self.denom) @@ -132,8 +136,12 @@ pub fn ceil(&self) -> Ratio { } } + /// 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 { + // 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 { } } + /// Rounds towards zero. #[inline] pub fn trunc(&self) -> Ratio { Ratio::from_integer(self.numer / self.denom) } + ///Returns the fractional part of a number. + #[inline] pub fn fract(&self) -> Ratio { Ratio::new_raw(self.numer % self.denom, self.denom.clone()) } } impl Ratio { - /// Converts a float into a rational number + /// Converts a float into a rational number. pub fn from_float(f: T) -> Option { if !f.is_finite() { return None; @@ -328,7 +339,7 @@ fn to_str_radix(&self, radix: uint) -> String { impl FromStr for Ratio { - /// Parses `numer/denom` or just `numer` + /// Parses `numer/denom` or just `numer`. fn from_str(s: &str) -> Option> { let mut split = s.splitn('/', 1); diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index c7dca1b93ef..0cf884eccbc 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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 { 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 diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 8b4fcb10907..f4309d9e51b 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -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 { 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 { for &(arch, abi) in architecture_abis.iter() { diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 9f15c9a9b3f..99855c7345c 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -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), diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2a7f7e8c54d..82040f14159 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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; } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 3f4f5123699..1667f2b6d5f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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"); } } _ => () diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 8896a068baa..9224647bc79 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -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; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6665e913e19..dbda4f58d96 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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(ebml_w: &mut Encoder, index: Vec>, - write_fn: |&mut MemWriter, &T|) { + write_fn: |&mut SeekableMemWriter, &T|) { let mut buckets: Vec>> = 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(ebml_w: &mut Encoder, index: Vec>, 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(ebml_w: &mut Encoder, index: Vec>, 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 { - 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, diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 1811c4f8612..4b9dd1003ec 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -251,6 +251,9 @@ 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" } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 15e4e85ddb7..f301dc3760d 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -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>; -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(w: &mut MemWriter, t: Option, enc_f: |&mut MemWriter, T|) { +fn enc_opt(w: &mut SeekableMemWriter, t: Option, enc_f: |&mut SeekableMemWriter, T|) { match t { None => mywrite!(w, "n"), Some(v) => { @@ -94,10 +95,10 @@ fn enc_opt(w: &mut MemWriter, t: Option, enc_f: |&mut MemWriter, T|) { } } -fn enc_vec_per_param_space(w: &mut MemWriter, +fn enc_vec_per_param_space(w: &mut SeekableMemWriter, cx: &ctxt, v: &VecPerParamSpace, - 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(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); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 722715405bc..9a587dd7741 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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>) { - 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); diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 4f6885f05ed..9cd46067c10 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -333,32 +333,37 @@ fn expr(&mut self, expr: Gc, 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 } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index e458b82f036..4d10676a589 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -11,6 +11,10 @@ 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 => {} + } + } +} + diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7995317d49f..605811555a1 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 5433923441a..ea301784c93 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1235,7 +1235,8 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext, output_type: ty::t, param_substs: &'a param_substs, sp: Option, - block_arena: &'a TypedArena>) + block_arena: &'a TypedArena>, + 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: ¶m_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, ¶m_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. diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index e2ad8b4fd46..f186af48321 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -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) { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index a65d208d4d2..98b2ebb70f3 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -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, diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 320e291e928..71ddc2e4045 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -221,6 +221,12 @@ fn substp(&self, tcx: &ty::ctxt, substs: ¶m_substs) -> T { pub type RvalueDatum = datum::Datum; pub type LvalueDatum = datum::Datum; +#[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> >, + + // How to handle items encountered during translation of this function. + pub handle_items: HandleItemsFlag, } impl<'a> FunctionContext<'a> { diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index f3457f3b0ae..bb528790314 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -121,10 +121,6 @@ pub struct CrateContext { /// Holds the LLVM values for closure IDs. pub unboxed_closure_vals: RefCell>, - /// 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, pub eh_personality: RefCell>, @@ -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()), diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index d8a8cc1c561..dd8fe5e9303 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -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") diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index f305ae90d46..cb46d62fca9 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -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, ¶m_substs::empty(), id, []); + base::trans_fn(ccx, decl, body, llfn, ¶m_substs::empty(), id, [], + TranslateItems); llfn } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 5c978d505cb..40288a33930 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -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()); diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index bf39f3a6aa3..877dd647c3b 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -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, - ¶m_substs::empty(), mth.id, []); + ¶m_substs::empty(), mth.id, [], TranslateItems); } local_def(mth.id) } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 53f89c9d8b8..4e6250883eb 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -75,7 +75,8 @@ pub fn trans_impl(ccx: &CrateContext, llfn, ¶m_substs::empty(), method.id, - []); + [], + TranslateItems); } else { let mut v = TransItemVisitor{ ccx: ccx }; visit::walk_method_helper(&mut v, &**method, ()); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index dac3b6bd8ee..986d3328f2c 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -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 } _ => { diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 7d8700b9426..eb0d77da551 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -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 diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index d202e61abf3..5e7426f3ae7 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -877,6 +877,7 @@ pub fn ast_ty_to_ty( } } 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 { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 08a26eefa22..bbb6e162ecb 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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) => { diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index c3e7d06f3f8..d94ac103ceb 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -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 index 00000000000..f153aca7fac --- /dev/null +++ b/src/librustc/util/io.rs @@ -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 or the MIT license +// , 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 { + // 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, + 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 { 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 { 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 = 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) + } +} diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index c4a9d9c80ef..e2cadf817d5 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -36,6 +36,17 @@ pub struct Archive<'a> { maybe_ar_prog: Option } +/// 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, + should_update_symbols: bool, +} + fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, args: &str, cwd: Option<&Path>, paths: &[&Path]) -> ProcessOutput { @@ -85,10 +96,8 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, } 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 { + 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 { - 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()); } } diff --git a/src/librustc_back/arm.rs b/src/librustc_back/arm.rs index a0730360ec7..9bb90427e7c 100644 --- a/src/librustc_back/arm.rs +++ b/src/librustc_back/arm.rs @@ -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\ diff --git a/src/librustc_back/mips.rs b/src/librustc_back/mips.rs index 4176d0e9a6f..43bf3e8e4af 100644 --- a/src/librustc_back/mips.rs +++ b/src/librustc_back/mips.rs @@ -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\ diff --git a/src/librustc_back/mipsel.rs b/src/librustc_back/mipsel.rs index d3ea9d3aa72..87f74e72504 100644 --- a/src/librustc_back/mipsel.rs +++ b/src/librustc_back/mipsel.rs @@ -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\ diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index e298e1dbfe9..94d197ad06a 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -37,6 +37,12 @@ pub fn get_rpath_flags(config: RPathConfig) -> Vec { "-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() { diff --git a/src/librustc_back/x86.rs b/src/librustc_back/x86.rs index b4d67bc98d2..3c444806e13 100644 --- a/src/librustc_back/x86.rs +++ b/src/librustc_back/x86.rs @@ -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, diff --git a/src/librustc_back/x86_64.rs b/src/librustc_back/x86_64.rs index 70807edc996..b4b5765986b 100644 --- a/src/librustc_back/x86_64.rs +++ b/src/librustc_back/x86_64.rs @@ -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, diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index f07c0163676..f22950e7a29 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -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 { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index c6d6843db5f..2fb3143b0bf 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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, "")); - try!(write!(f, "\ - {}", + try!(write!(f, "{}", Vec::from_slice(context.slice_from(1)) .append_one("index.html").connect("/"), path)); - try!(write!(f, "")); + try!(write!(f, "")); try!(write!(f, " ", - (width * cnt.stable)/tot)); + style='width: {:.4}%; display: inline-block'> ", + (100 * cnt.stable) as f64/tot as f64)); try!(write!(f, " ", - (width * cnt.unstable)/tot)); + style='width: {:.4}%; display: inline-block'> ", + (100 * cnt.unstable) as f64/tot as f64)); try!(write!(f, " ", - (width * cnt.experimental)/tot)); + style='width: {:.4}%; display: inline-block'> ", + (100 * cnt.experimental) as f64/tot as f64)); try!(write!(f, " ", - (width * cnt.deprecated)/tot)); + style='width: {:.4}%; display: inline-block'> ", + (100 * cnt.deprecated) as f64/tot as f64)); try!(write!(f, " ", - (width * cnt.unmarked)/tot)); + style='width: {:.4}%; display: inline-block'> ", + (100 * cnt.unmarked) as f64/tot as f64)); try!(write!(f, "")); 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"

Stability dashboard: crate {}

+r"

Stability dashboard: crate {name}

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}):
- stable,
- unstable,
- experimental,
- deprecated,
- unmarked + stable ({}%),
+ unstable ({}%),
+ experimental ({}%),
+ deprecated ({}%),
+ unmarked ({}%)
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, "")) try!(fmt_inner(f, &mut context, self)); write!(f, "
") diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 95637d311d8..084ba46797e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -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, "

Fields

\n")); - for field in fields { - try!(write!(w, "")); + doctree::Plain => { + if fields.peek().is_some() { + try!(write!(w, "

Fields

\n
\ - {stab}{name}", - stab = ConciseStability(&field.stability), - name = field.name.get_ref().as_slice())); - try!(document(w, field)); - try!(write!(w, "
")); + for field in fields { + try!(write!(w, "")); + } + try!(write!(w, "
\ + {stab}{name}", + stab = ConciseStability(&field.stability), + name = field.name.get_ref().as_slice())); + try!(document(w, field)); + try!(write!(w, "
")); } - try!(write!(w, "")); } _ => {} } diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 4f790f96750..45e6694853c 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -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; } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 1869031dab3..8688e031890 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -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'); } } @@ -99,7 +102,7 @@ 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; @@ -111,9 +114,47 @@ 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, @@ -140,7 +181,7 @@ 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); @@ -153,7 +194,7 @@ 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) { @@ -167,15 +208,31 @@ } 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) { @@ -186,7 +243,7 @@ } 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] || {}; } @@ -198,6 +255,12 @@ 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); @@ -255,7 +318,7 @@ 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(), @@ -285,38 +348,23 @@ * @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() { @@ -496,7 +544,7 @@ 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]); @@ -568,7 +616,7 @@ // 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], @@ -640,7 +688,7 @@ 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'; @@ -657,10 +705,10 @@ 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 = $('').append(structs[j]); $.each(code.find('a'), function(idx, a) { var href = $(a).attr('href'); diff --git a/src/librustrt/args.rs b/src/librustrt/args.rs index af6de0cf605..531bbe038fc 100644 --- a/src/librustrt/args.rs +++ b/src/librustrt/args.rs @@ -42,6 +42,7 @@ pub fn clone() -> Option>> { imp::clone() } #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "dragonfly")] mod imp { use core::prelude::*; diff --git a/src/librustrt/bookkeeping.rs b/src/librustrt/bookkeeping.rs index fd290491eaf..dc96aecff80 100644 --- a/src/librustrt/bookkeeping.rs +++ b/src/librustrt/bookkeeping.rs @@ -19,14 +19,24 @@ //! 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() { diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index f018b3fc16b..789723af1b1 100644 --- a/src/librustrt/libunwind.rs +++ b/src/librustrt/libunwind.rs @@ -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 diff --git a/src/librustrt/local.rs b/src/librustrt/local.rs index bdb1c60b6d6..e2a5eef0d99 100644 --- a/src/librustrt/local.rs +++ b/src/librustrt/local.rs @@ -125,8 +125,8 @@ fn try_take() { }).join(); } - fn cleanup_task(mut t: Box) { - t.destroyed = true; + fn cleanup_task(t: Box) { + t.drop(); } } diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs index c999a08eb93..f24c2609d09 100644 --- a/src/librustrt/mutex.rs +++ b/src/librustrt/mutex.rs @@ -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; diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs index 0eacd40f01c..6544c020e09 100644 --- a/src/librustrt/stack.rs +++ b/src/librustrt/stack.rs @@ -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")] diff --git a/src/librustrt/task.rs b/src/librustrt/task.rs index d27a4f25b4e..e3d9b7d136e 100644 --- a/src/librustrt/task.rs +++ b/src/librustrt/task.rs @@ -100,12 +100,21 @@ pub struct Task { pub storage: LocalStorage, pub unwinder: Unwinder, pub death: Death, - pub destroyed: bool, pub name: Option, + state: TaskState, imp: Option>, } +// 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, @@ -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, f: ||) -> Box { + pub fn run(mut self: Box, f: ||) -> Box { 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, f: ||) -> Box { if Local::exists(None::) { 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, result: Result) -> Box { // Now that we're done, we remove the task from TLS and flag it for // destruction. let mut task: Box = 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(); } } diff --git a/src/librustrt/thread_local_storage.rs b/src/librustrt/thread_local_storage.rs index 3b9ee31d8e5..b9b12686170 100644 --- a/src/librustrt/thread_local_storage.rs +++ b/src/librustrt/thread_local_storage.rs @@ -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 diff --git a/src/librustuv/uvll.rs b/src/librustuv/uvll.rs index d0d6287695d..2bcd2101d89 100644 --- a/src/librustuv/uvll.rs +++ b/src/librustuv/uvll.rs @@ -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 {} diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index dfce1eeb832..c3434466836 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -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 { + // 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, + 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 { 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 { 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) { 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); diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a56904c9ef4..0752c68f4d0 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -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); } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index bcc0761d92a..7731cd12ec2 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -20,11 +20,19 @@ 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 { } } + /// 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 { /// 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 for &'a str { #[inline] fn to_ascii_upper(&self) -> String { - unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) } + // Vec::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::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::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::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> for &'a [u8] { + #[inline] + fn to_ascii_upper(&self) -> Vec { + 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 { + 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 { + #[inline] + fn into_ascii_upper(mut self) -> Vec { + for byte in self.mut_iter() { + *byte = ASCII_UPPER_MAP[*byte as uint]; + } + self + } + + #[inline] + fn into_ascii_lower(mut self) -> Vec { + 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, diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index 834d461f20b..d231189aede 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -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)); + } } diff --git a/src/libstd/collections/hashmap.rs b/src/libstd/collections/hashmap.rs index 8b6e6d61842..a569ee4a32a 100644 --- a/src/libstd/collections/hashmap.rs +++ b/src/libstd/collections/hashmap.rs @@ -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. diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 5980245fa79..2c4e0ea6701 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -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}; diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index c7dec49a76d..1b2706b3f5b 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -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 { /// /// # 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 { 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(result: IoResult, from: &Path, to: &Path) -> IoResult { /// /// # 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 { /// /// # 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> { 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 { /// /// # 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 { diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index b93b84b7d63..8879f7e2506 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -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 { // 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 /// /// assert_eq!(w.unwrap(), vec!(0, 1, 2)); /// ``` +#[deriving(Clone)] pub struct MemWriter { buf: Vec, - 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 { 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 { 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 = Vec::from_elem(len, 5); + b.bytes = (times * len) as u64; b.iter(|| { let mut wr = MemWriter::new(); for _ in range(0, times) { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 4277b509962..f1b92b973c8 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -223,6 +223,7 @@ fn file_product(p: &Path) -> IoResult { 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}; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index ebcb60253f5..7fff510a60a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -651,6 +651,7 @@ pub fn dll_filename(base: &str) -> String { pub fn self_exe_name() -> Option { #[cfg(target_os = "freebsd")] + #[cfg(target_os = "dragonfly")] fn load_self() -> Option> { 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> { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "dragonfly")] fn real_args_as_bytes() -> Vec> { 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; diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 0c93f8e6de9..1e9ec32d759 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -178,16 +178,13 @@ fn as_str<'a>(&'a self) -> Option<&'a str> { fn into_vec(self) -> Vec; /// 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 } } diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index d075f9a1205..80493ebb4a9 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -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 diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs index 0ffac99775c..1717aeb8430 100644 --- a/src/libstd/rtdeps.rs +++ b/src/libstd/rtdeps.rs @@ -38,6 +38,10 @@ #[link(name = "pthread")] extern {} +#[cfg(target_os = "dragonfly")] +#[link(name = "pthread")] +extern {} + #[cfg(target_os = "macos")] #[link(name = "System")] extern {} diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 6f809383620..c50a5661973 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -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) } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8159aee99d1..e19d39a4dc5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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>), - PatEnum(Path, Option>>), /* "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>>), + PatStruct(Path, Vec, bool), PatTup(Vec>), PatBox(Gc), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a66d6839ab0..d00406e07b7 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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)); diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 7d683382589..6c9e113f41a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -170,6 +170,13 @@ fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec>) -> Gc; fn pat_struct(&self, span: Span, path: ast::Path, field_pats: Vec ) -> Gc; + fn pat_tuple(&self, span: Span, pats: Vec>) -> Gc; + + fn pat_some(&self, span: Span, pat: Gc) -> Gc; + fn pat_none(&self, span: Span) -> Gc; + + fn pat_ok(&self, span: Span, pat: Gc) -> Gc; + fn pat_err(&self, span: Span, pat: Gc) -> Gc; fn arm(&self, span: Span, pats: Vec> , expr: Gc) -> 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, then: Gc, els: Option>) -> Gc; + fn expr_loop(&self, span: Span, block: P) -> Gc; fn lambda_fn_decl(&self, span: Span, fn_decl: P, blk: P) -> Gc; @@ -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 { + let pat = ast::PatTup(pats); + self.pat(span, pat) + } + + fn pat_some(&self, span: Span, pat: Gc) -> Gc { + 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 { + 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) -> Gc { + 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) -> Gc { + 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> , expr: Gc) -> 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) -> Gc { + self.expr(span, ast::ExprLoop(block, None)) + } + fn lambda_fn_decl(&self, span: Span, fn_decl: P, blk: P) -> Gc { self.expr(span, ast::ExprFnBlock(fn_decl, blk)) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3b098ea8a3d..808532d55bb 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -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, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index a7ede6f742d..dcfb0198127 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -144,8 +144,10 @@ fn to_source(&self) -> String { impl_to_source!(Generics, generics_to_string) impl_to_source!(Gc, item_to_string) impl_to_source!(Gc, method_to_string) + impl_to_source!(Gc, stmt_to_string) impl_to_source!(Gc, expr_to_string) impl_to_source!(Gc, pat_to_string) + impl_to_source!(ast::Arm, arm_to_string) impl_to_source_slice!(ast::Ty, ", ") impl_to_source_slice!(Gc, "\n\n") @@ -239,11 +241,13 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec { impl_to_tokens!(ast::Ident) impl_to_tokens!(Gc) impl_to_tokens!(Gc) + impl_to_tokens!(ast::Arm) impl_to_tokens!(Gc) impl_to_tokens_lifetime!(&'a [Gc]) impl_to_tokens!(ast::Ty) impl_to_tokens_lifetime!(&'a [ast::Ty]) impl_to_tokens!(Generics) + impl_to_tokens!(Gc) impl_to_tokens!(Gc) 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 { + 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]) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0116518d537..945a643d2b4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1954,19 +1954,6 @@ pub fn parse_bottom_expr(&mut self) -> Gc { 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 { 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 { } 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 { } }; } - 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 { self.commit_expr_expecting(discriminant, token::LBRACE); let mut arms: Vec = 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 { 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); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ac835565191..675588a4460 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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) = 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_, diff --git a/src/liburl/lib.rs b/src/liburl/lib.rs index b95fc3c495e..c7e27c00836 100644 --- a/src/liburl/lib.rs +++ b/src/liburl/lib.rs @@ -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(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(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 { /// # 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/") { diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 0e29e621503..037afce9b16 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -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); } diff --git a/src/llvm b/src/llvm index cd24b5c6633..0d999e5b315 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit cd24b5c6633b27df2b84249a65a46a610b734494 +Subproject commit 0d999e5b315b6ff78fcea772466d985ce53fd8dc diff --git a/src/rt/arch/x86_64/morestack.S b/src/rt/arch/x86_64/morestack.S index 6ccabbf5994..c82da57c128 100644 --- a/src/rt/arch/x86_64/morestack.S +++ b/src/rt/arch/x86_64/morestack.S @@ -15,13 +15,13 @@ #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__) diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c index ed077e69978..89cb27c1f1a 100644 --- a/src/rt/rust_builtin.c +++ b/src/rt/rust_builtin.c @@ -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 +// 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++ diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index bdc5bfdc10a..afba5a4dfd8 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -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 diff --git a/src/test/compile-fail/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck-lend-flow-match.rs index c6020df2bc2..049bec3d37b 100644 --- a/src/test/compile-fail/borrowck-lend-flow-match.rs +++ b/src/test/compile-fail/borrowck-lend-flow-match.rs @@ -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 index 00000000000..8a904a3b5fb --- /dev/null +++ b/src/test/compile-fail/borrowck-mutate-in-guard.rs @@ -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 or the MIT license +// , 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 index 00000000000..9f1c1fdd7c7 --- /dev/null +++ b/src/test/compile-fail/deprecated-url.rs @@ -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 or the MIT license +// , 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 index 00000000000..a9f57a48f44 --- /dev/null +++ b/src/test/pretty/issue-4264.pp @@ -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 or the MIT license +// , 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(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 index 00000000000..ad407f48a7a --- /dev/null +++ b/src/test/pretty/issue-4264.rs @@ -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 or the MIT license +// , 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(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 index 00000000000..44771a29bb4 --- /dev/null +++ b/src/test/pretty/match-block-expr.rs @@ -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 or the MIT license +// , 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); +} diff --git a/src/test/pretty/match-naked-expr-medium.rs b/src/test/pretty/match-naked-expr-medium.rs index c03ad499478..d2f8157ef62 100644 --- a/src/test/pretty/match-naked-expr-medium.rs +++ b/src/test/pretty/match-naked-expr-medium.rs @@ -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()], }; } diff --git a/src/test/pretty/match-naked-expr.rs b/src/test/pretty/match-naked-expr.rs index 67c389f7e1f..6b4f579f9c5 100644 --- a/src/test/pretty/match-naked-expr.rs +++ b/src/test/pretty/match-naked-expr.rs @@ -15,6 +15,6 @@ fn main() { let _y = match x { Some(_) => "some(_)".to_string(), - None => "none".to_string() + None => "none".to_string(), }; } diff --git a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot index 251798fc7ed..2b7088fbc33 100644 --- a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot @@ -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; } diff --git a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot index 2be43dcaa7b..5d1d1253b22 100644 --- a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot @@ -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 index 00000000000..18ba80a712d --- /dev/null +++ b/src/test/run-make/issue-7349/Makefile @@ -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 index 00000000000..775b7314841 --- /dev/null +++ b/src/test/run-make/issue-7349/foo.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn outer() { + #[allow(dead_code)] + fn inner() -> uint { + 8675309 + } +} + +fn main() { + outer::(); + outer::(); +} diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 36b525c134b..a5cf8e46b7e 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -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(cx: fake_ext_ctxt, diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 11c3dfb2241..60b8f09bb3d 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -26,6 +26,7 @@ fn syntax_extension(cx: &ExtCtxt) { let _b: Option> = quote_item!(cx, static foo : int = $e_toks; ); let _c: Gc = quote_pat!(cx, (x, 1 .. 4, *) ); let _d: Gc = quote_stmt!(cx, let x = $a; ); + let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) ); let _e: Gc = quote_expr!(cx, match foo { $p_toks => 10 } ); let _f: Gc = quote_expr!(cx, ()); diff --git a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs index a7738bb803c..9eef83184e1 100644 --- a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs @@ -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); } diff --git a/src/test/run-pass/dupe-first-attr.rc b/src/test/run-pass/dupe-first-attr.rc index c3c22cb26d2..76dedaba40f 100644 --- a/src/test/run-pass/dupe-first-attr.rc +++ b/src/test/run-pass/dupe-first-attr.rc @@ -23,6 +23,9 @@ mod hello; #[cfg(target_os = "freebsd")] mod hello; +#[cfg(target_os = "dragonfly")] +mod hello; + #[cfg(target_os = "android")] mod hello; diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index 84593ececd0..197b92ba635 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -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")] diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index 934adc07e2f..df4342bfeb5 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -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"; diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index e0cd91adb1c..d7f487b629b 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -10,10 +10,127 @@ 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 { + // 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, + 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 { 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 { 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, 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, + T: Encodable, 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), diff --git a/src/test/run-pass/lang-item-public.rs b/src/test/run-pass/lang-item-public.rs index 6330e1bf3c1..f541ca6794f 100644 --- a/src/test/run-pass/lang-item-public.rs +++ b/src/test/run-pass/lang-item-public.rs @@ -28,6 +28,10 @@ #[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 index 00000000000..847024d42ba --- /dev/null +++ b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs @@ -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 or the MIT license +// , 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!()]; +} diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index cf254d54793..ada012fc2f5 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -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 index 00000000000..e1c4a480d1c --- /dev/null +++ b/src/test/run-pass/spawn-stack-too-big.rs @@ -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 or the MIT license +// , 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()); +} diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs index b2cf771faee..66dbb6b1619 100644 --- a/src/test/run-pass/x86stdcall.rs +++ b/src/test/run-pass/x86stdcall.rs @@ -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() { }