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
CFG_OSTYPE=unknown-freebsd
;;
+ DragonFly)
+ CFG_OSTYPE=unknown-dragonfly
+ ;;
+
Darwin)
CFG_OSTYPE=apple-darwin
;;
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
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
$$(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
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
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),
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 => {}
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
}
}
parse_name_directive(line, "no-pretty-expanded")
}
+fn parse_pretty_mode(line: &str) -> Option<String> {
+ parse_name_value_directive(line, "pretty-mode")
+}
+
+fn parse_pretty_compare_only(line: &str) -> bool {
+ parse_name_directive(line, "pretty-compare-only")
+}
+
fn parse_exec_env(line: &str) -> Option<(String, String)> {
parse_name_value_directive(line, "exec-env").map(|nv| {
// nv is either FOO or FOO=BAR
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 {}",
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);
#[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 )
}
#[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(" "))
}
("android", "android"),
("linux", "linux"),
("freebsd", "freebsd"),
+ ("dragonfly", "dragonfly"),
];
pub fn get_os(triple: &str) -> &'static str {
```{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)
$
```
```{notrust,ignore}
$ cargo build
- Compiling guessing_game v0.1.0 (file:/home/steve/tmp/guessing_game)
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
src/guessing_game.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option<uint>` (expected uint but found enum core::option::Option)
src/guessing_game.rs:22 match cmp(input_num, secret_number) {
^~~~~~~~~
```{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.
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
* [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
}
```
-**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`.
- `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
`"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.
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
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
<match>\\\%{common_escape}</match>
</context>
+ <context id="raw-string" style-ref="string" class="string" class-disabled="no-spell-check">
+ <start>r(#*)"</start>
+ <end>"\%{1@start}</end>
+ <include>
+ <context ref="def:line-continue"/>
+ </include>
+ </context>
+
<context id="string" style-ref="string" class="string" class-disabled="no-spell-check">
<start>"</start>
<end>"</end>
<end>\]</end>
<include>
<context ref="def:in-comment"/>
+ <context ref="string"/>
+ <context ref="raw-string"/>
</include>
</context>
<context ref="number"/>
<context ref="scope"/>
<context ref="string"/>
+ <context ref="raw-string"/>
<context ref="char"/>
<context ref="lifetime"/>
<context ref="attribute"/>
OS=`uname -s`
case $OS in
- ("Linux"|"FreeBSD")
+ ("Linux"|"FreeBSD"|"DragonFly")
BIN_SUF=
LIB_SUF=.so
break
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
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:
}
#[inline]
- fn inner<'a>(&'a self) -> &'a ArcInner<T> {
+ fn inner(&self) -> &ArcInner<T> {
// This unsafety is ok because while this arc is alive we're guaranteed
// that the inner pointer is valid. Furthermore, we know that the
// `ArcInner` structure itself is `Share` because the inner data is
#[experimental = "Deref is experimental."]
impl<T: Send + Share> Deref<T> for Arc<T> {
#[inline]
- fn deref<'a>(&'a self) -> &'a T {
+ fn deref(&self) -> &T {
&self.inner().data
}
}
/// 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.
}
#[inline]
- fn inner<'a>(&'a self) -> &'a ArcInner<T> {
+ fn inner(&self) -> &ArcInner<T> {
// See comments above for why this is "safe"
unsafe { &*self._ptr }
}
use core::iter;
use core::mem;
use core::ptr;
+use std::hash::{Writer, Hash};
use {Collection, Mutable, Deque, MutableSeq};
}
}
+impl<S: Writer, A: Hash<S>> Hash<S> for DList<A> {
+ fn hash(&self, state: &mut S) {
+ self.len().hash(state);
+ for elt in self.iter() {
+ elt.hash(state);
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use std::prelude::*;
use std::rand;
+ use std::hash;
use test::Bencher;
use test;
assert!(n != m);
}
+ #[test]
+ fn test_hash() {
+ let mut x = DList::new();
+ let mut y = DList::new();
+
+ assert!(hash::hash(&x) == hash::hash(&y));
+
+ x.push_back(1i);
+ x.push_back(2);
+ x.push_back(3);
+
+ y.push_front(3i);
+ y.push_front(2);
+ y.push_front(1);
+
+ assert!(hash::hash(&x) == hash::hash(&y));
+ }
+
#[test]
fn test_ord() {
let n: DList<int> = list_from([]);
*
* * src - A mutable vector of `T`
* * start - The index into `src` to start copying from
- * * end - The index into `str` to stop copying from
+ * * end - The index into `src` to stop copying from
*/
fn move_from(self, src: Vec<T>, start: uint, end: uint) -> uint;
}
/// assert_eq!(s.shift_char(), Some('o'));
/// assert_eq!(s.shift_char(), None);
/// ```
- pub fn shift_char (&mut self) -> Option<char> {
+ pub fn shift_char(&mut self) -> Option<char> {
let len = self.len();
if len == 0 {
return None
#[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
(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) }
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 }
#[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();
#[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
(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) }
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 }
#[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();
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;
/// 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.
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
// 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;
f: proc():Send) {
self.put_task(cur_task);
+ // First, set up a bomb which when it goes off will restore the local
+ // task unless its disarmed. This will allow us to gracefully fail from
+ // inside of `configure` which allocates a new task.
+ struct Bomb { inner: Option<Box<GreenTask>> }
+ impl Drop for Bomb {
+ fn drop(&mut self) {
+ let _ = self.inner.take().map(|task| task.put());
+ }
+ }
+ let mut bomb = Bomb { inner: Some(self) };
+
// Spawns a task into the current scheduler. We allocate the new task's
// stack from the scheduler's stack pool, and then configure it
// accordingly to `opts`. Afterwards we bootstrap it immediately by
// switching to it.
//
// Upon returning, our task is back in TLS and we're good to return.
- let mut sched = self.sched.take_unwrap();
- let sibling = GreenTask::configure(&mut sched.stack_pool, opts, f);
- sched.run_task(self, sibling)
+ let sibling = {
+ let sched = bomb.inner.get_mut_ref().sched.get_mut_ref();
+ GreenTask::configure(&mut sched.stack_pool, opts, f)
+ };
+ let mut me = bomb.inner.take().unwrap();
+ let sched = me.sched.take().unwrap();
+ sched.run_task(me, sibling)
}
// Local I/O is provided by the scheduler's event loop
#[cfg(windows)] pub use funcs::extra::kernel32::{MoveFileExW, VirtualProtect};
#[cfg(windows)] pub use funcs::extra::msvcrt::{get_osfhandle, open_osfhandle};
-#[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")]
+#[cfg(target_os = "linux")] #[cfg(target_os = "android")]
+#[cfg(target_os = "freebsd")] #[cfg(target_os = "dragonfly")]
pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC};
#[cfg(target_os = "linux")] #[cfg(target_os = "android")]
pub use consts::os::extra::{MAP_STACK};
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
pub use consts::os::bsd44::{TCP_KEEPIDLE};
#[cfg(target_os = "macos")]
}
}
+ #[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 {
}
#[cfg(target_os = "freebsd")]
+ #[cfg(target_os = "dragonfly")]
pub mod os {
pub mod c95 {
use types::os::arch::c95::{c_int, c_uint};
#[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;
}
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;
#[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};
#[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;
#[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;
#[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};
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;
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "freebsd")]
+ #[cfg(target_os = "dragonfly")]
pub mod posix08 {
pub mod unistd {
}
#[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};
}
#[cfg(target_os = "freebsd")]
+ #[cfg(target_os = "dragonfly")]
pub mod extra {
}
// 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)]
#[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")]
#[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")]
#[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")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
#[cfg(target_os = "linux")]
mod select {
use std::uint;
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)]
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
mod signal {
use libc;
#[cfg(target_os = "ios")]
pub type sigset_t = u32;
#[cfg(target_os = "freebsd")]
+ #[cfg(target_os = "dragonfly")]
pub struct sigset_t {
bits: [u32, ..4],
}
}
#[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,
#[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"]
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(())
}
#[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 }
// 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
let mut task = task;
task.put_runtime(ops);
drop(task.run(|| { f.take_unwrap()() }).destroy());
- bookkeeping::decrement();
+ drop(token);
})
}
#[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]
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]
/// ~~~
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.
///
((*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]
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() }
}
}
#[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]
impl<T: Clone + Integer + PartialOrd>
Ratio<T> {
- /// Create a ratio representing the integer `t`.
+ /// Creates a ratio representing the integer `t`.
#[inline]
pub fn from_integer(t: T) -> Ratio<T> {
Ratio::new_raw(t, One::one())
}
- /// Create a ratio without checking for `denom == 0` or reducing.
+ /// Creates a ratio without checking for `denom == 0` or reducing.
#[inline]
pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
Ratio { numer: numer, denom: denom }
ret
}
- /// Convert to an integer.
+ /// Converts to an integer.
#[inline]
pub fn to_integer(&self) -> T {
self.trunc().numer
&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()
}
}
- /// Return a `reduce`d copy of self.
+ /// Returns a `reduce`d copy of self.
pub fn reduced(&self) -> Ratio<T> {
let mut ret = self.clone();
ret.reduce();
ret
}
- /// Return the reciprocal
+ /// Returns the reciprocal.
#[inline]
pub fn recip(&self) -> Ratio<T> {
Ratio::new_raw(self.denom.clone(), self.numer.clone())
}
+ /// Rounds towards minus infinity.
+ #[inline]
pub fn floor(&self) -> Ratio<T> {
if *self < Zero::zero() {
Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
}
}
+ /// Rounds towards plus infinity.
+ #[inline]
pub fn ceil(&self) -> Ratio<T> {
if *self < Zero::zero() {
Ratio::from_integer(self.numer / self.denom)
}
}
+ /// Rounds to the nearest integer. Rounds half-way cases away from zero.
+ ///
+ /// Note: This function is currently broken and always rounds away from zero.
#[inline]
pub fn round(&self) -> Ratio<T> {
+ // FIXME(#15826)
if *self < Zero::zero() {
Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
} else {
}
}
+ /// Rounds towards zero.
#[inline]
pub fn trunc(&self) -> Ratio<T> {
Ratio::from_integer(self.numer / self.denom)
}
+ ///Returns the fractional part of a number.
+ #[inline]
pub fn fract(&self) -> Ratio<T> {
Ratio::new_raw(self.numer % self.denom, self.denom.clone())
}
}
impl Ratio<BigInt> {
- /// Converts a float into a rational number
+ /// Converts a float into a rational number.
pub fn from_float<T: Float>(f: T) -> Option<BigRational> {
if !f.is_finite() {
return None;
impl<T: FromStr + Clone + Integer + PartialOrd>
FromStr for Ratio<T> {
- /// Parses `numer/denom` or just `numer`
+ /// Parses `numer/denom` or just `numer`.
fn from_str(s: &str) -> Option<Ratio<T>> {
let mut split = s.splitn('/', 1);
// 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;
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!("{}{}{}",
abi::OsLinux |
abi::OsAndroid |
abi::OsFreebsd |
+ abi::OsDragonfly |
abi::OsiOS => out_filename.clone(),
}
}
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);
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,
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:
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
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
// 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![];
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");
// 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());
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.
"-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
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
None
}
static os_names : &'static [(&'static str, abi::Os)] = &[
- ("mingw32", abi::OsWin32),
- ("win32", abi::OsWin32),
- ("darwin", abi::OsMacos),
- ("android", abi::OsAndroid),
- ("linux", abi::OsLinux),
- ("freebsd", abi::OsFreebsd),
- ("ios", abi::OsiOS)];
+ ("mingw32", abi::OsWin32),
+ ("win32", abi::OsWin32),
+ ("darwin", abi::OsMacos),
+ ("android", abi::OsAndroid),
+ ("linux", abi::OsLinux),
+ ("freebsd", abi::OsFreebsd),
+ ("dragonfly", abi::OsDragonfly),
+ ("ios", abi::OsiOS)];
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
for &(arch, abi) in architecture_abis.iter() {
("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),
#[phase(plugin, link)] extern crate log;
#[phase(plugin, link)] extern crate syntax;
+#[cfg(test)]
+extern crate test;
+
mod diagnostics;
pub mod back {
pub mod common;
pub mod ppaux;
+ pub mod io;
pub mod nodemap;
}
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");
}
}
_ => ()
#![macro_escape]
use std::hash;
-use std::ascii::StrAsciiExt;
+use std::ascii::AsciiExt;
use syntax::codemap::Span;
use syntax::visit::FnKind;
use syntax::ast;
use middle::typeck;
use middle::stability;
use middle;
+use util::io::SeekableMemWriter;
use util::nodemap::{NodeMap, NodeSet};
use serialize::Encodable;
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;
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,
// Path and definition ID indexing
fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
- write_fn: |&mut MemWriter, &T|) {
+ write_fn: |&mut SeekableMemWriter, &T|) {
let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
for elt in index.move_iter() {
let h = hash::hash(&elt.val) as uint;
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);
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);
}
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
0, 0, 0, 1 ];
pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
encode_metadata_inner(&mut wr, parms, krate);
wr.unwrap().move_iter().collect()
}
-fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
+fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate: &Crate) {
struct Stats {
attr_bytes: u64,
dep_bytes: u64,
// 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,
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";
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,
}
}
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"),
}
}
abi::OsWin32 => ".note.rustc",
abi::OsLinux => ".note.rustc",
abi::OsAndroid => ".note.rustc",
- abi::OsFreebsd => ".note.rustc"
+ abi::OsFreebsd => ".note.rustc",
+ abi::OsDragonfly => ".note.rustc"
}
}
use std::cell::RefCell;
use std::collections::HashMap;
-use std::io::MemWriter;
use middle::subst;
use middle::subst::VecPerParamSpace;
use syntax::diagnostic::SpanHandler;
use syntax::parse::token;
+use util::io::SeekableMemWriter;
+
macro_rules! mywrite( ($($arg:tt)*) => ({ write!($($arg)*); }) )
pub struct ctxt<'a> {
pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
-pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
+pub fn enc_ty(w: &mut SeekableMemWriter, cx: &ctxt, t: ty::t) {
match cx.abbrevs.borrow_mut().find(&t) {
Some(a) => { w.write(a.s.as_bytes()); return; }
None => {}
}
}
-fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
+fn enc_mutability(w: &mut SeekableMemWriter, mt: ast::Mutability) {
match mt {
MutImmutable => (),
MutMutable => mywrite!(w, "m"),
}
}
-fn enc_mt(w: &mut MemWriter, cx: &ctxt, mt: ty::mt) {
+fn enc_mt(w: &mut SeekableMemWriter, cx: &ctxt, mt: ty::mt) {
enc_mutability(w, mt.mutbl);
enc_ty(w, cx, mt.ty);
}
-fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
+fn enc_opt<T>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: |&mut SeekableMemWriter, T|) {
match t {
None => mywrite!(w, "n"),
Some(v) => {
}
}
-fn enc_vec_per_param_space<T>(w: &mut MemWriter,
+fn enc_vec_per_param_space<T>(w: &mut SeekableMemWriter,
cx: &ctxt,
v: &VecPerParamSpace<T>,
- op: |&mut MemWriter, &ctxt, &T|) {
+ op: |&mut SeekableMemWriter, &ctxt, &T|) {
for &space in subst::ParamSpace::all().iter() {
mywrite!(w, "[");
for t in v.get_slice(space).iter() {
}
}
-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");
}
}
-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);
}
}
-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);
}
}
-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) => {
}
}
-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"),
}
}
-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);
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);
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"),
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);
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};
use libc;
use std::io::Seek;
-use std::io::MemWriter;
use std::mem;
use std::gc::GC;
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.
#[cfg(test)]
fn roundtrip(in_item: Option<Gc<ast::Item>>) {
- use std::io::MemWriter;
-
let in_item = in_item.unwrap();
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
{
let mut ebml_w = writer::Encoder::new(&mut wr);
encode_item_ast(&mut ebml_w, in_item);
// [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
}
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;
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.
});
}
}
+
+/// 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 => {}
+ }
+ }
+}
+
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);
output_type: ty::t,
param_substs: &'a param_substs,
sp: Option<Span>,
- block_arena: &'a TypedArena<Block<'a>>)
+ block_arena: &'a TypedArena<Block<'a>>,
+ handle_items: HandleItemsFlag)
-> FunctionContext<'a> {
param_substs.validate();
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 {
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");
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
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");
abi,
false,
NotUnboxedClosure,
- |bcx| bcx);
+ |bcx| bcx,
+ handle_items);
}
pub fn trans_enum_variant(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);
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.
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.
// 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 {
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 {
Some(C_undef(llty.ptr_to()))
}
}
+ Some(expr::Ignore) => None
};
let mut llresult = unsafe {
// 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
// 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) {
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
}
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
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,
pub type RvalueDatum = datum::Datum<datum::Rvalue>;
pub type LvalueDatum = datum::Datum<datum::Lvalue>;
+#[deriving(Clone, Eq, PartialEq)]
+pub enum HandleItemsFlag {
+ IgnoreItems,
+ TranslateItems,
+}
+
// Function context. Every LLVM function we create will have one of
// these.
pub struct FunctionContext<'a> {
// Cleanup scopes.
pub scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
+
+ // How to handle items encountered during translation of this function.
+ pub handle_items: HandleItemsFlag,
}
impl<'a> FunctionContext<'a> {
/// Holds the LLVM values for closure IDs.
pub unboxed_closure_vals: RefCell<DefIdMap<ValueRef>>,
- /// Set when at least one function uses GC. Needed so that
- /// decl_gc_metadata knows whether to link to the module metadata, which
- /// is not emitted by LLVM's GC pass when no functions use GC.
- pub uses_gc: bool,
pub dbg_cx: Option<debuginfo::CrateDebugContext>,
pub eh_personality: RefCell<Option<ValueRef>>,
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()),
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")
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
}
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());
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)
}
llfn,
¶m_substs::empty(),
method.id,
- []);
+ [],
+ TranslateItems);
} else {
let mut v = TransItemVisitor{ ccx: ccx };
visit::walk_method_helper(&mut v, &**method, ());
} => {
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
}
_ => {
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) => {
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
}
_ => {
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
}
}
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 {
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, _: ()) { }
}
}
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) => {
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, ())
+ }
}
}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::io::{IoError, IoResult, SeekStyle};
+use std::io;
+use std::slice;
+
+static BUF_CAPACITY: uint = 128;
+
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+ // compute offset as signed and clamp to prevent overflow
+ let pos = match seek {
+ io::SeekSet => 0,
+ io::SeekEnd => end,
+ io::SeekCur => cur,
+ } as i64;
+
+ if offset + pos < 0 {
+ Err(IoError {
+ kind: io::InvalidInput,
+ desc: "invalid seek to a negative offset",
+ detail: None
+ })
+ } else {
+ Ok((offset + pos) as u64)
+ }
+}
+
+/// Writes to an owned, growable byte vector that supports seeking.
+///
+/// # Example
+///
+/// ```rust
+/// # #![allow(unused_must_use)]
+/// use std::io::SeekableMemWriter;
+///
+/// let mut w = SeekableMemWriter::new();
+/// w.write([0, 1, 2]);
+///
+/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// ```
+pub struct SeekableMemWriter {
+ buf: Vec<u8>,
+ pos: uint,
+}
+
+impl SeekableMemWriter {
+ /// Create a new `SeekableMemWriter`.
+ #[inline]
+ pub fn new() -> SeekableMemWriter {
+ SeekableMemWriter::with_capacity(BUF_CAPACITY)
+ }
+ /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ #[inline]
+ pub fn with_capacity(n: uint) -> SeekableMemWriter {
+ SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ }
+
+ /// Acquires an immutable reference to the underlying buffer of this
+ /// `SeekableMemWriter`.
+ ///
+ /// No method is exposed for acquiring a mutable reference to the buffer
+ /// because it could corrupt the state of this `MemWriter`.
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+ /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+ #[inline]
+ pub fn unwrap(self) -> Vec<u8> { self.buf }
+}
+
+impl Writer for SeekableMemWriter {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ if self.pos == self.buf.len() {
+ self.buf.push_all(buf)
+ } else {
+ // Make sure the internal buffer is as least as big as where we
+ // currently are
+ let difference = self.pos as i64 - self.buf.len() as i64;
+ if difference > 0 {
+ self.buf.grow(difference as uint, &0);
+ }
+
+ // Figure out what bytes will be used to overwrite what's currently
+ // there (left), and what will be appended on the end (right)
+ let cap = self.buf.len() - self.pos;
+ let (left, right) = if cap <= buf.len() {
+ (buf.slice_to(cap), buf.slice_from(cap))
+ } else {
+ (buf, &[])
+ };
+
+ // Do the necessary writes
+ if left.len() > 0 {
+ slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+ }
+ if right.len() > 0 {
+ self.buf.push_all(right);
+ }
+ }
+
+ // Bump us forward
+ self.pos += buf.len();
+ Ok(())
+ }
+}
+
+impl Seek for SeekableMemWriter {
+ #[inline]
+ fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+ #[inline]
+ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+ let new = try!(combine(style, self.pos, self.buf.len(), pos));
+ self.pos = new as uint;
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::SeekableMemWriter;
+ use std::io;
+ use test::Bencher;
+
+ #[test]
+ fn test_seekable_mem_writer() {
+ let mut writer = SeekableMemWriter::new();
+ assert_eq!(writer.tell(), Ok(0));
+ writer.write([0]).unwrap();
+ assert_eq!(writer.tell(), Ok(1));
+ writer.write([1, 2, 3]).unwrap();
+ writer.write([4, 5, 6, 7]).unwrap();
+ assert_eq!(writer.tell(), Ok(8));
+ assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]);
+
+ writer.seek(0, io::SeekSet).unwrap();
+ assert_eq!(writer.tell(), Ok(0));
+ writer.write([3, 4]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]);
+
+ writer.seek(1, io::SeekCur).unwrap();
+ writer.write([0, 1]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]);
+
+ writer.seek(-1, io::SeekEnd).unwrap();
+ writer.write([1, 2]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]);
+
+ writer.seek(1, io::SeekEnd).unwrap();
+ writer.write([1]).unwrap();
+ assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
+ }
+
+ #[test]
+ fn seek_past_end() {
+ let mut r = SeekableMemWriter::new();
+ r.seek(10, io::SeekSet).unwrap();
+ assert!(r.write([3]).is_ok());
+ }
+
+ #[test]
+ fn seek_before_0() {
+ let mut r = SeekableMemWriter::new();
+ assert!(r.seek(-1, io::SeekSet).is_err());
+ }
+
+ fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) {
+ let src: Vec<u8> = Vec::from_elem(len, 5);
+
+ b.bytes = (times * len) as u64;
+ b.iter(|| {
+ let mut wr = SeekableMemWriter::new();
+ for _ in range(0, times) {
+ wr.write(src.as_slice()).unwrap();
+ }
+
+ let v = wr.unwrap();
+ assert_eq!(v.len(), times * len);
+ assert!(v.iter().all(|x| *x == 5));
+ });
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 0)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 10)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 100)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 1, 1000)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 0)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 10)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 100)
+ }
+
+ #[bench]
+ fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) {
+ do_bench_seekable_mem_writer(b, 100, 1000)
+ }
+}
maybe_ar_prog: Option<String>
}
+/// Helper for adding many files to an archive with a single invocation of
+/// `ar`.
+#[must_use = "must call build() to finish building the archive"]
+pub struct ArchiveBuilder<'a> {
+ archive: Archive<'a>,
+ work_dir: TempDir,
+ /// Filename of each member that should be added to the archive.
+ members: Vec<Path>,
+ should_update_symbols: bool,
+}
+
fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
args: &str, cwd: Option<&Path>,
paths: &[&Path]) -> ProcessOutput {
}
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,
/// Opens an existing static archive
pub fn open(config: ArchiveConfig<'a>) -> Archive<'a> {
- let ArchiveConfig { handler, dst, lib_search_paths, os, maybe_ar_prog } = config;
- assert!(dst.exists());
- Archive {
- handler: handler,
- dst: dst,
- lib_search_paths: lib_search_paths,
- os: os,
- maybe_ar_prog: maybe_ar_prog
+ let archive = Archive::new(config);
+ assert!(archive.dst.exists());
+ archive
+ }
+
+ /// Removes a file from this archive
+ pub fn remove_file(&mut self, file: &str) {
+ run_ar(self.handler, &self.maybe_ar_prog, "d", None, [&self.dst, &Path::new(file)]);
+ }
+
+ /// Lists all files in an archive
+ pub fn files(&self) -> Vec<String> {
+ let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, [&self.dst]);
+ let output = str::from_utf8(output.output.as_slice()).unwrap();
+ // use lines_any because windows delimits output with `\r\n` instead of
+ // just `\n`
+ output.lines_any().map(|s| s.to_string()).collect()
+ }
+
+ /// Creates an `ArchiveBuilder` for adding files to this archive.
+ pub fn extend(self) -> ArchiveBuilder<'a> {
+ ArchiveBuilder::new(self)
+ }
+}
+
+impl<'a> ArchiveBuilder<'a> {
+ fn new(archive: Archive<'a>) -> ArchiveBuilder<'a> {
+ ArchiveBuilder {
+ archive: archive,
+ work_dir: TempDir::new("rsar").unwrap(),
+ members: vec![],
+ should_update_symbols: false,
}
}
+ /// Create a new static archive, ready for adding files.
+ pub fn create(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
+ let archive = Archive::new(config);
+ ArchiveBuilder::new(archive)
+ }
+
/// Adds all of the contents of a native library to this archive. This will
/// search in the relevant locations for a library named `name`.
pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> {
}
/// Adds an arbitrary file to this archive
- pub fn add_file(&mut self, file: &Path, has_symbols: bool) {
- let cmd = if has_symbols {"r"} else {"rS"};
- run_ar(self.handler, &self.maybe_ar_prog, cmd, None, [&self.dst, file]);
- }
-
- /// Removes a file from this archive
- pub fn remove_file(&mut self, file: &str) {
- run_ar(self.handler, &self.maybe_ar_prog, "d", None, [&self.dst, &Path::new(file)]);
+ pub fn add_file(&mut self, file: &Path) -> io::IoResult<()> {
+ let filename = Path::new(file.filename().unwrap());
+ let new_file = self.work_dir.path().join(&filename);
+ try!(fs::copy(file, &new_file));
+ self.members.push(filename);
+ Ok(())
}
- /// Updates all symbols in the archive (runs 'ar s' over it)
+ /// Indicate that the next call to `build` should updates all symbols in
+ /// the archive (run 'ar s' over it).
pub fn update_symbols(&mut self) {
- run_ar(self.handler, &self.maybe_ar_prog, "s", None, [&self.dst]);
+ self.should_update_symbols = true;
}
- /// Lists all files in an archive
- pub fn files(&self) -> Vec<String> {
- let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, [&self.dst]);
- let output = str::from_utf8(output.output.as_slice()).unwrap();
- // use lines_any because windows delimits output with `\r\n` instead of
- // just `\n`
- output.lines_any().map(|s| s.to_string()).collect()
+ /// Combine the provided files, rlibs, and native libraries into a single
+ /// `Archive`.
+ pub fn build(self) -> Archive<'a> {
+ // Get an absolute path to the destination, so `ar` will work even
+ // though we run it from `self.work_dir`.
+ let abs_dst = os::getcwd().join(&self.archive.dst);
+ assert!(!abs_dst.is_relative());
+ let mut args = vec![&abs_dst];
+ let mut total_len = abs_dst.as_vec().len();
+
+ if self.members.is_empty() {
+ // OSX `ar` does not allow using `r` with no members, but it does
+ // allow running `ar s file.a` to update symbols only.
+ if self.should_update_symbols {
+ run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+ "s", Some(self.work_dir.path()), args.as_slice());
+ }
+ return self.archive;
+ }
+
+ // Don't allow the total size of `args` to grow beyond 32,000 bytes.
+ // Windows will raise an error if the argument string is longer than
+ // 32,768, and we leave a bit of extra space for the program name.
+ static ARG_LENGTH_LIMIT: uint = 32000;
+
+ for member_name in self.members.iter() {
+ let len = member_name.as_vec().len();
+
+ // `len + 1` to account for the space that's inserted before each
+ // argument. (Windows passes command-line arguments as a single
+ // string, not an array of strings.)
+ if total_len + len + 1 > ARG_LENGTH_LIMIT {
+ // Add the archive members seen so far, without updating the
+ // symbol table (`S`).
+ run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+ "cruS", Some(self.work_dir.path()), args.as_slice());
+
+ args.clear();
+ args.push(&abs_dst);
+ total_len = abs_dst.as_vec().len();
+ }
+
+ args.push(member_name);
+ total_len += len + 1;
+ }
+
+ // Add the remaining archive members, and update the symbol table if
+ // necessary.
+ let flags = if self.should_update_symbols { "crus" } else { "cruS" };
+ run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+ flags, Some(self.work_dir.path()), args.as_slice());
+
+ self.archive
}
fn add_archive(&mut self, archive: &Path, name: &str,
skip: &[&str]) -> io::IoResult<()> {
let loc = TempDir::new("rsar").unwrap();
- // First, extract the contents of the archive to a temporary directory
+ // First, extract the contents of the archive to a temporary directory.
+ // We don't unpack directly into `self.work_dir` due to the possibility
+ // of filename collisions.
let archive = os::make_absolute(archive);
- run_ar(self.handler, &self.maybe_ar_prog, "x", Some(loc.path()), [&archive]);
+ run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
+ "x", Some(loc.path()), [&archive]);
// Next, we must rename all of the inputs to "guaranteed unique names".
- // The reason for this is that archives are keyed off the name of the
- // files, so if two files have the same name they will override one
- // another in the archive (bad).
+ // We move each file into `self.work_dir` under its new unique name.
+ // The reason for this renaming is that archives are keyed off the name
+ // of the files, so if two files have the same name they will override
+ // one another in the archive (bad).
//
// We skip any files explicitly desired for skipping, and we also skip
// all SYMDEF files as these are just magical placeholders which get
// re-created when we make a new archive anyway.
let files = try!(fs::readdir(loc.path()));
- let mut inputs = Vec::new();
for file in files.iter() {
let filename = file.filename_str().unwrap();
if skip.iter().any(|s| *s == filename) { continue }
} 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
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 }
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());
}
}
-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\
-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\
-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\
"-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!");
// 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!()
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() {
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,
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,
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 {
context.push(m.name.as_slice());
let path = context.connect("::");
- // the total width of each row's stability summary, in pixels
- let width = 500;
-
try!(write!(f, "<tr>"));
- try!(write!(f, "<td class='summary'>\
- <a class='summary' href='{}'>{}</a></td>",
+ try!(write!(f, "<td><a href='{}'>{}</a></td>",
Vec::from_slice(context.slice_from(1))
.append_one("index.html").connect("/"),
path));
- try!(write!(f, "<td>"));
+ try!(write!(f, "<td class='summary-column'>"));
try!(write!(f, "<span class='summary Stable' \
- style='width: {}px; display: inline-block'> </span>",
- (width * cnt.stable)/tot));
+ style='width: {:.4}%; display: inline-block'> </span>",
+ (100 * cnt.stable) as f64/tot as f64));
try!(write!(f, "<span class='summary Unstable' \
- style='width: {}px; display: inline-block'> </span>",
- (width * cnt.unstable)/tot));
+ style='width: {:.4}%; display: inline-block'> </span>",
+ (100 * cnt.unstable) as f64/tot as f64));
try!(write!(f, "<span class='summary Experimental' \
- style='width: {}px; display: inline-block'> </span>",
- (width * cnt.experimental)/tot));
+ style='width: {:.4}%; display: inline-block'> </span>",
+ (100 * cnt.experimental) as f64/tot as f64));
try!(write!(f, "<span class='summary Deprecated' \
- style='width: {}px; display: inline-block'> </span>",
- (width * cnt.deprecated)/tot));
+ style='width: {:.4}%; display: inline-block'> </span>",
+ (100 * cnt.deprecated) as f64/tot as f64));
try!(write!(f, "<span class='summary Unmarked' \
- style='width: {}px; display: inline-block'> </span>",
- (width * cnt.unmarked)/tot));
+ style='width: {:.4}%; display: inline-block'> </span>",
+ (100 * cnt.unmarked) as f64/tot as f64));
try!(write!(f, "</td></tr>"));
for submodule in m.submodules.iter() {
let mut context = Vec::new();
+ let tot = self.counts.total();
+ let (stable, unstable, experimental, deprecated, unmarked) = if tot == 0 {
+ (0, 0, 0, 0, 0)
+ } else {
+ ((100 * self.counts.stable)/tot,
+ (100 * self.counts.unstable)/tot,
+ (100 * self.counts.experimental)/tot,
+ (100 * self.counts.deprecated)/tot,
+ (100 * self.counts.unmarked)/tot)
+ };
+
try!(write!(f,
-r"<h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>{}</a></h1>
+r"<h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>{name}</a></h1>
This dashboard summarizes the stability levels for all of the public modules of
-the crate, according to the total number of items at each level in the module and its children:
+the crate, according to the total number of items at each level in the module and
+its children (percentages total for {name}):
<blockquote>
-<a class='stability Stable'></a> stable,<br/>
-<a class='stability Unstable'></a> unstable,<br/>
-<a class='stability Experimental'></a> experimental,<br/>
-<a class='stability Deprecated'></a> deprecated,<br/>
-<a class='stability Unmarked'></a> unmarked
+<a class='stability Stable'></a> stable ({}%),<br/>
+<a class='stability Unstable'></a> unstable ({}%),<br/>
+<a class='stability Experimental'></a> experimental ({}%),<br/>
+<a class='stability Deprecated'></a> deprecated ({}%),<br/>
+<a class='stability Unmarked'></a> unmarked ({}%)
</blockquote>
The counts do not include methods or trait
implementations that are visible only through a re-exported type.",
-self.name));
+stable, unstable, experimental, deprecated, unmarked,
+name=self.name));
try!(write!(f, "<table>"))
try!(fmt_inner(f, &mut context, self));
write!(f, "</table>")
}
}).peekable();
match s.struct_type {
- doctree::Plain if fields.peek().is_some() => {
- try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
- for field in fields {
- try!(write!(w, "<tr><td id='structfield.{name}'>\
- {stab}<code>{name}</code></td><td>",
- stab = ConciseStability(&field.stability),
- name = field.name.get_ref().as_slice()));
- try!(document(w, field));
- try!(write!(w, "</td></tr>"));
+ doctree::Plain => {
+ if fields.peek().is_some() {
+ try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
+ for field in fields {
+ try!(write!(w, "<tr><td id='structfield.{name}'>\
+ {stab}<code>{name}</code></td><td>",
+ stab = ConciseStability(&field.stability),
+ name = field.name.get_ref().as_slice()));
+ try!(document(w, field));
+ try!(write!(w, "</td></tr>"));
+ }
+ try!(write!(w, "</table>"));
}
- try!(write!(w, "</table>"));
}
_ => {}
}
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;
.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;
.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; }
$('.docblock.short').width(function() {
return contentWidth - 40 - $(this).prev().width();
}).addClass('nowrap');
+ $('.summary-column').width(function() {
+ return contentWidth - 40 - $(this).prev().width();
+ })
}, 150);
}
resizeShortBlocks();
}
$('#' + from)[0].scrollIntoView();
$('.line-numbers span').removeClass('line-highlighted');
- for (i = from; i <= to; i += 1) {
+ for (i = from; i <= to; ++i) {
$('#' + i).addClass('line-highlighted');
}
}
stripped = '',
len = rootPath.match(/\.\.\//g).length + 1;
- for (i = 0; i < len; i += 1) {
+ for (i = 0; i < len; ++i) {
match = url.match(/\/[^\/]*$/);
if (i < len - 1) {
stripped = match[0] + stripped;
document.location.href = url;
});
+ /**
+ * A function to compute the Levenshtein distance between two strings
+ * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
+ * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
+ * This code is an unmodified version of the code written by Marco de Wit
+ * and was found at http://stackoverflow.com/a/18514751/745719
+ */
+ var levenshtein = (function() {
+ var row2 = [];
+ return function(s1, s2) {
+ if (s1 === s2) {
+ return 0;
+ } else {
+ var s1_len = s1.length, s2_len = s2.length;
+ if (s1_len && s2_len) {
+ var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
+ while (i1 < s1_len)
+ row[i1] = ++i1;
+ while (i2 < s2_len) {
+ c2 = s2.charCodeAt(i2);
+ a = i2;
+ ++i2;
+ b = i2;
+ for (i1 = 0; i1 < s1_len; ++i1) {
+ c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+ a = row[i1];
+ b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+ row[i1] = b;
+ }
+ }
+ return b;
+ } else {
+ return s1_len + s2_len;
+ }
+ }
+ };
+ })();
function initSearch(rawSearchIndex) {
var currentResults, index, searchIndex;
+ var MAX_LEV_DISTANCE = 3;
var params = getQueryStringParams();
// Populate search bar with query string search term when provided,
split = valLower.split("::");
//remove empty keywords
- for (var j = 0; j < split.length; j++) {
+ for (var j = 0; j < split.length; ++j) {
split[j].toLowerCase();
if (split[j] === "") {
split.splice(j, 1);
val.charAt(val.length - 1) === val.charAt(0))
{
val = val.substr(1, val.length - 2);
- for (var i = 0; i < nSearchWords; i += 1) {
+ for (var i = 0; i < nSearchWords; ++i) {
if (searchWords[i] === val) {
// filter type: ... queries
if (typeFilter < 0 || typeFilter === searchIndex[i].ty) {
} else {
// gather matching search results up to a certain maximum
val = val.replace(/\_/g, "");
- for (var i = 0; i < split.length; i++) {
- for (var j = 0; j < nSearchWords; j += 1) {
+ for (var i = 0; i < split.length; ++i) {
+ for (var j = 0; j < nSearchWords; ++j) {
+ var lev_distance;
if (searchWords[j].indexOf(split[i]) > -1 ||
searchWords[j].indexOf(val) > -1 ||
searchWords[j].replace(/_/g, "").indexOf(val) > -1)
{
// filter type: ... queries
if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
- results.push({id: j, index: searchWords[j].replace(/_/g, "").indexOf(val)});
+ results.push({
+ id: j,
+ index: searchWords[j].replace(/_/g, "").indexOf(val),
+ lev: 0,
+ });
+ }
+ } else if (
+ (lev_distance = levenshtein(searchWords[j], val)) <=
+ MAX_LEV_DISTANCE) {
+ if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
+ results.push({
+ id: j,
+ index: 0,
+ // we want lev results to go lower than others
+ lev: lev_distance,
+ });
}
}
if (results.length === max) {
}
var nresults = results.length;
- for (var i = 0; i < nresults; i += 1) {
+ for (var i = 0; i < nresults; ++i) {
results[i].word = searchWords[results[i].id];
results[i].item = searchIndex[results[i].id] || {};
}
results.sort(function(aaa, bbb) {
var a, b;
+ // Sort by non levenshtein results and then levenshtein results by the distance
+ // (less changes required to match means higher rankings)
+ a = (aaa.lev);
+ b = (bbb.lev);
+ if (a !== b) return a - b;
+
// sort by crate (non-current crate goes later)
a = (aaa.item.crate !== window.currentCrate);
b = (bbb.item.crate !== window.currentCrate);
results[i].id = -1;
}
}
- for (var i = 0; i < results.length; i++) {
+ for (var i = 0; i < results.length; ++i) {
var result = results[i],
name = result.item.name.toLowerCase(),
path = result.item.path.toLowerCase(),
* @return {[boolean]} [Whether the result is valid or not]
*/
function validateResult(name, path, keys, parent) {
- //initially valid
- var validate = true;
- //if there is a parent, then validate against parent
- if (parent !== undefined) {
- for (var i = 0; i < keys.length; i++) {
- // if previous keys are valid and current key is in the
- // path, name or parent
- if ((validate) &&
- (name.toLowerCase().indexOf(keys[i]) > -1 ||
- path.toLowerCase().indexOf(keys[i]) > -1 ||
- parent.name.toLowerCase().indexOf(keys[i]) > -1))
- {
- validate = true;
- } else {
- validate = false;
- }
- }
- } else {
- for (var i = 0; i < keys.length; i++) {
- // if previous keys are valid and current key is in the
- // path, name
- if ((validate) &&
- (name.toLowerCase().indexOf(keys[i]) > -1 ||
- path.toLowerCase().indexOf(keys[i]) > -1))
- {
- validate = true;
- } else {
- validate = false;
- }
+ for (var i=0; i < keys.length; ++i) {
+ // each check is for validation so we negate the conditions and invalidate
+ if (!(
+ // check for an exact name match
+ name.toLowerCase().indexOf(keys[i]) > -1 ||
+ // then an exact path match
+ path.toLowerCase().indexOf(keys[i]) > -1 ||
+ // next if there is a parent, check for exact parent match
+ (parent !== undefined &&
+ parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
+ // lastly check to see if the name was a levenshtein match
+ levenshtein(name.toLowerCase(), keys[i]) <=
+ MAX_LEV_DISTANCE)) {
+ return false;
}
}
- return validate;
+ return true;
}
function getQuery() {
resultIndex = execQuery(query, 20000, index);
len = resultIndex.length;
- for (i = 0; i < len; i += 1) {
+ for (i = 0; i < len; ++i) {
if (resultIndex[i].id > -1) {
obj = searchIndex[resultIndex[i].id];
filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
// faster analysis operations
var len = items.length;
var lastPath = "";
- for (var i = 0; i < len; i += 1) {
+ for (var i = 0; i < len; ++i) {
var rawRow = items[i];
var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
path: rawRow[2] || lastPath, desc: rawRow[3],
crates.push(crate);
}
crates.sort();
- for (var i = 0; i < crates.length; i++) {
+ for (var i = 0; i < crates.length; ++i) {
var klass = 'crate';
if (crates[i] == window.currentCrate) {
klass += ' current';
window.register_implementors = function(imp) {
var list = $('#implementors-list');
var libs = Object.getOwnPropertyNames(imp);
- for (var i = 0; i < libs.length; i++) {
+ for (var i = 0; i < libs.length; ++i) {
if (libs[i] == currentCrate) continue;
var structs = imp[libs[i]];
- for (var j = 0; j < structs.length; j++) {
+ for (var j = 0; j < structs.length; ++j) {
var code = $('<code>').append(structs[j]);
$.each(code.find('a'), function(idx, a) {
var href = $(a).attr('href');
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
mod imp {
use core::prelude::*;
//! 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() {
#[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
}).join();
}
- fn cleanup_task(mut t: Box<Task>) {
- t.destroyed = true;
+ fn cleanup_task(t: Box<Task>) {
+ t.drop();
}
}
type pthread_condattr_t = libc::c_void;
#[cfg(target_os = "freebsd")]
+ #[cfg(target_os = "dragonfly")]
mod os {
use libc;
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")]
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")]
pub storage: LocalStorage,
pub unwinder: Unwinder,
pub death: Death,
- pub destroyed: bool,
pub name: Option<SendStr>,
+ state: TaskState,
imp: Option<Box<Runtime + Send>>,
}
+// Once a task has entered the `Armed` state it must be destroyed via `drop`,
+// and no other method. This state is used to track this transition.
+#[deriving(PartialEq)]
+enum TaskState {
+ New,
+ Armed,
+ Destroyed,
+}
+
pub struct TaskOpts {
/// Invoke this procedure with the result of the task when it finishes.
pub on_exit: Option<proc(Result): Send>,
storage: LocalStorage(None),
unwinder: Unwinder::new(),
death: Death::new(),
- destroyed: false,
+ state: New,
name: None,
imp: None,
}
/// }).destroy();
/// # }
/// ```
- pub fn run(self: Box<Task>, f: ||) -> Box<Task> {
+ pub fn run(mut self: Box<Task>, f: ||) -> Box<Task> {
assert!(!self.is_destroyed(), "cannot re-use a destroyed task");
// First, make sure that no one else is in TLS. This does not allow
if Local::exists(None::<Task>) {
fail!("cannot run a task recursively inside another");
}
+ self.state = Armed;
Local::put(self);
// There are two primary reasons that general try/catch is unsafe. The
// Now that we're done, we remove the task from TLS and flag it for
// destruction.
let mut task: Box<Task> = Local::take();
- task.destroyed = true;
+ task.state = Destroyed;
return task;
}
/// Queries whether this can be destroyed or not.
- pub fn is_destroyed(&self) -> bool { self.destroyed }
+ pub fn is_destroyed(&self) -> bool { self.state == Destroyed }
/// Inserts a runtime object into this task, transferring ownership to the
/// task. It is illegal to replace a previous runtime object in this task
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);
}
}
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();
}
}
#[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
extern {}
#[cfg(target_os = "linux")]
+#[cfg(target_os = "dragonfly")]
#[link(name = "rt")]
extern {}
extern {}
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
#[link(name = "kvm")]
extern {}
use ebml::writer;
use {Encodable, Decodable};
- use std::io::MemWriter;
+ use std::io::{IoError, IoResult, SeekStyle};
+ use std::io;
use std::option::{None, Option, Some};
+ use std::slice;
+
+ static BUF_CAPACITY: uint = 128;
+
+ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+ // compute offset as signed and clamp to prevent overflow
+ let pos = match seek {
+ io::SeekSet => 0,
+ io::SeekEnd => end,
+ io::SeekCur => cur,
+ } as i64;
+
+ if offset + pos < 0 {
+ Err(IoError {
+ kind: io::InvalidInput,
+ desc: "invalid seek to a negative offset",
+ detail: None
+ })
+ } else {
+ Ok((offset + pos) as u64)
+ }
+ }
+
+ /// Writes to an owned, growable byte vector that supports seeking.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # #![allow(unused_must_use)]
+ /// use std::io::SeekableMemWriter;
+ ///
+ /// let mut w = SeekableMemWriter::new();
+ /// w.write([0, 1, 2]);
+ ///
+ /// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+ /// ```
+ pub struct SeekableMemWriter {
+ buf: Vec<u8>,
+ pos: uint,
+ }
+
+ impl SeekableMemWriter {
+ /// Create a new `SeekableMemWriter`.
+ #[inline]
+ pub fn new() -> SeekableMemWriter {
+ SeekableMemWriter::with_capacity(BUF_CAPACITY)
+ }
+ /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ #[inline]
+ pub fn with_capacity(n: uint) -> SeekableMemWriter {
+ SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ }
+
+ /// Acquires an immutable reference to the underlying buffer of this
+ /// `SeekableMemWriter`.
+ ///
+ /// No method is exposed for acquiring a mutable reference to the buffer
+ /// because it could corrupt the state of this `MemWriter`.
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+ /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+ #[inline]
+ pub fn unwrap(self) -> Vec<u8> { self.buf }
+ }
+
+ impl Writer for SeekableMemWriter {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ if self.pos == self.buf.len() {
+ self.buf.push_all(buf)
+ } else {
+ // Make sure the internal buffer is as least as big as where we
+ // currently are
+ let difference = self.pos as i64 - self.buf.len() as i64;
+ if difference > 0 {
+ self.buf.grow(difference as uint, &0);
+ }
+
+ // Figure out what bytes will be used to overwrite what's currently
+ // there (left), and what will be appended on the end (right)
+ let cap = self.buf.len() - self.pos;
+ let (left, right) = if cap <= buf.len() {
+ (buf.slice_to(cap), buf.slice_from(cap))
+ } else {
+ (buf, &[])
+ };
+
+ // Do the necessary writes
+ if left.len() > 0 {
+ slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+ }
+ if right.len() > 0 {
+ self.buf.push_all(right);
+ }
+ }
+
+ // Bump us forward
+ self.pos += buf.len();
+ Ok(())
+ }
+ }
+
+ impl Seek for SeekableMemWriter {
+ #[inline]
+ fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+ #[inline]
+ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+ let new = try!(combine(style, self.pos, self.buf.len(), pos));
+ self.pos = new as uint;
+ Ok(())
+ }
+ }
#[test]
fn test_vuint_at() {
fn test_option_int() {
fn test_v(v: Option<int>) {
debug!("v == {}", v);
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
{
let mut ebml_w = writer::Encoder::new(&mut wr);
let _ = v.encode(&mut ebml_w);
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);
}
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 }
}
}
+
/// Extension methods for ASCII-subset only operations on owned strings
-pub trait OwnedStrAsciiExt {
+pub trait OwnedAsciiExt {
/// Convert the string to ASCII upper case:
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
- fn into_ascii_upper(self) -> String;
+ fn into_ascii_upper(self) -> Self;
/// Convert the string to ASCII lower case:
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
- fn into_ascii_lower(self) -> String;
+ fn into_ascii_lower(self) -> Self;
}
/// Extension methods for ASCII-subset only operations on string slices
-pub trait StrAsciiExt {
+pub trait AsciiExt<T> {
/// Makes a copy of the string in ASCII upper case:
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
- fn to_ascii_upper(&self) -> String;
+ fn to_ascii_upper(&self) -> T;
/// Makes a copy of the string in ASCII lower case:
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
- fn to_ascii_lower(&self) -> String;
+ fn to_ascii_lower(&self) -> T;
/// Check that two strings are an ASCII case-insensitive match.
/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
/// but without allocating and copying temporary strings.
- fn eq_ignore_ascii_case(&self, other: &str) -> bool;
+ fn eq_ignore_ascii_case(&self, other: Self) -> bool;
}
-impl<'a> StrAsciiExt for &'a str {
+impl<'a> AsciiExt<String> for &'a str {
#[inline]
fn to_ascii_upper(&self) -> String {
- unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
+ // Vec<u8>::to_ascii_upper() preserves the UTF-8 invariant.
+ unsafe { str::raw::from_utf8_owned(self.as_bytes().to_ascii_upper()) }
}
#[inline]
fn to_ascii_lower(&self) -> String {
- unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }
+ // Vec<u8>::to_ascii_lower() preserves the UTF-8 invariant.
+ unsafe { str::raw::from_utf8_owned(self.as_bytes().to_ascii_lower()) }
}
#[inline]
fn eq_ignore_ascii_case(&self, other: &str) -> bool {
- self.len() == other.len() &&
- self.as_bytes().iter().zip(other.as_bytes().iter()).all(
- |(byte_self, byte_other)| {
- ASCII_LOWER_MAP[*byte_self as uint] ==
- ASCII_LOWER_MAP[*byte_other as uint]
- })
+ self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
}
}
-impl OwnedStrAsciiExt for String {
+impl OwnedAsciiExt for String {
#[inline]
fn into_ascii_upper(self) -> String {
- unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
+ // Vec<u8>::into_ascii_upper() preserves the UTF-8 invariant.
+ unsafe { str::raw::from_utf8_owned(self.into_bytes().into_ascii_upper()) }
}
#[inline]
fn into_ascii_lower(self) -> String {
- unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }
+ // Vec<u8>::into_ascii_lower() preserves the UTF-8 invariant.
+ unsafe { str::raw::from_utf8_owned(self.into_bytes().into_ascii_lower()) }
}
}
-#[inline]
-unsafe fn str_map_bytes(string: String, map: &'static [u8]) -> String {
- let mut bytes = string.into_bytes();
+impl<'a> AsciiExt<Vec<u8>> for &'a [u8] {
+ #[inline]
+ fn to_ascii_upper(&self) -> Vec<u8> {
+ self.iter().map(|&byte| ASCII_UPPER_MAP[byte as uint]).collect()
+ }
- for b in bytes.mut_iter() {
- *b = map[*b as uint];
+ #[inline]
+ fn to_ascii_lower(&self) -> Vec<u8> {
+ self.iter().map(|&byte| ASCII_LOWER_MAP[byte as uint]).collect()
}
- String::from_utf8(bytes).unwrap()
+ #[inline]
+ fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
+ self.len() == other.len() &&
+ self.iter().zip(other.iter()).all(
+ |(byte_self, byte_other)| {
+ ASCII_LOWER_MAP[*byte_self as uint] ==
+ ASCII_LOWER_MAP[*byte_other as uint]
+ })
+ }
}
-#[inline]
-unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String {
- let mut s = String::from_str(string);
- for b in s.as_mut_bytes().mut_iter() {
- *b = map[*b as uint];
+impl OwnedAsciiExt for Vec<u8> {
+ #[inline]
+ fn into_ascii_upper(mut self) -> Vec<u8> {
+ for byte in self.mut_iter() {
+ *byte = ASCII_UPPER_MAP[*byte as uint];
+ }
+ self
+ }
+
+ #[inline]
+ fn into_ascii_lower(mut self) -> Vec<u8> {
+ for byte in self.mut_iter() {
+ *byte = ASCII_LOWER_MAP[*byte as uint];
+ }
+ self
}
- s.into_string()
}
-static ASCII_LOWER_MAP: &'static [u8] = &[
+
+pub static ASCII_LOWER_MAP: [u8, ..256] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+ b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+ b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+ b'@',
+
+ b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+ b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+ b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+ b'x', b'y', b'z',
+
+ b'[', b'\\', b']', b'^', b'_',
+ b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+ b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+ b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+ b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
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,
($(#[$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,
#[cfg(test)]
mod tests {
+ use hash;
use option::{Some, None};
use ops::{BitOr, BitAnd, Sub, Not};
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));
+ }
}
/// 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.
#[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.
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
pub mod dl {
use c_str::{CString, ToCStr};
/// `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
///
/// # 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<()> {
///
/// # Error
///
-/// This call will return an error if the user lacks the requisite permissions
-/// to perform a `stat` call on the given path or if there is no entry in the
+/// This function will return an error if the user lacks the requisite permissions
+/// to perform a `stat` call on the given `path` or if there is no entry in the
/// filesystem at the provided path.
pub fn stat(path: &Path) -> IoResult<FileStat> {
let err = match LocalIo::maybe_raise(|io| io.fs_stat(&path.to_c_str())) {
///
/// # 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())
///
/// # 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
///
/// # 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)
///
/// # 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)
///
/// # 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())
///
/// # Error
///
-/// Will return an error if the provided `from` doesn't exist, the process lacks
-/// permissions to view the contents or if the `path` points at a non-directory
-/// file
+/// This function will return an error if the provided `path` doesn't exist, if
+/// the process lacks permissions to view the contents or if the `path` points
+/// at a non-directory file
pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
let err = LocalIo::maybe_raise(|io| {
Ok(try!(io.fs_readdir(&path.to_c_str(), 0)).move_iter().map(|a| {
///
/// # 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?
///
/// # 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());
}
) )
- struct TempDir(Path);
+ pub struct TempDir(Path);
impl TempDir {
fn join(&self, path: &str) -> Path {
use slice::{Vector, ImmutableVector, MutableVector};
use vec::Vec;
+static BUF_CAPACITY: uint = 128;
+
fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
// compute offset as signed and clamp to prevent overflow
let pos = match seek {
///
/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
/// ```
+#[deriving(Clone)]
pub struct MemWriter {
buf: Vec<u8>,
- pos: uint,
}
impl MemWriter {
/// Create a new `MemWriter`.
#[inline]
pub fn new() -> MemWriter {
- MemWriter::with_capacity(128)
+ MemWriter::with_capacity(BUF_CAPACITY)
}
/// Create a new `MemWriter`, allocating at least `n` bytes for
/// the internal buffer.
#[inline]
pub fn with_capacity(n: uint) -> MemWriter {
- MemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ MemWriter { buf: Vec::with_capacity(n) }
}
/// Acquires an immutable reference to the underlying buffer of this
/// `MemWriter`.
- ///
- /// No method is exposed for acquiring a mutable reference to the buffer
- /// because it could corrupt the state of this `MemWriter`.
#[inline]
pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
impl Writer for MemWriter {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- // Make sure the internal buffer is as least as big as where we
- // currently are
- let difference = self.pos as i64 - self.buf.len() as i64;
- if difference > 0 {
- self.buf.grow(difference as uint, &0);
- }
-
- // Figure out what bytes will be used to overwrite what's currently
- // there (left), and what will be appended on the end (right)
- let cap = self.buf.len() - self.pos;
- let (left, right) = if cap <= buf.len() {
- (buf.slice_to(cap), buf.slice_from(cap))
- } else {
- (buf, &[])
- };
-
- // Do the necessary writes
- if left.len() > 0 {
- slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
- }
- if right.len() > 0 {
- self.buf.push_all(right);
- }
-
- // Bump us forward
- self.pos += buf.len();
- Ok(())
- }
-}
-
-impl Seek for MemWriter {
- #[inline]
- fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-
- #[inline]
- fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
- let new = try!(combine(style, self.pos, self.buf.len(), pos));
- self.pos = new as uint;
+ self.buf.push_all(buf);
Ok(())
}
}
#[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]
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();
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());
fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) {
let src: Vec<u8> = Vec::from_elem(len, 5);
+ b.bytes = (times * len) as u64;
b.iter(|| {
let mut wr = MemWriter::new();
for _ in range(0, times) {
use char::Char;
use collections::Collection;
+use default::Default;
use fmt;
use int;
use iter::Iterator;
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,
}
)
+impl Default for FilePermission {
+ #[inline]
+ fn default() -> FilePermission { FilePermission::empty() }
+}
+
#[cfg(test)]
mod tests {
use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput};
pub fn self_exe_name() -> Option<Path> {
#[cfg(target_os = "freebsd")]
+ #[cfg(target_os = "dragonfly")]
fn load_self() -> Option<Vec<u8>> {
unsafe {
use libc::funcs::bsd44::*;
}
}
+ #[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 {
#[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 {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
fn real_args_as_bytes() -> Vec<Vec<u8>> {
use rt;
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;
fn into_vec(self) -> Vec<u8>;
/// Returns an object that implements `Show` for printing paths
- ///
- /// This will print the equivalent of `to_display_str()` when used with a {} format parameter.
fn display<'a>(&'a self) -> Display<'a, Self> {
Display{ path: self, filename: false }
}
/// Returns an object that implements `Show` for printing filenames
///
- /// This will print the equivalent of `to_filename_display_str()` when used with a {}
- /// format parameter. If there is no filename, nothing will be printed.
+ /// If there is no filename, nothing will be printed.
fn filename_display<'a>(&'a self) -> Display<'a, Self> {
Display{ path: self, filename: true }
}
// 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
#[link(name = "pthread")]
extern {}
+#[cfg(target_os = "dragonfly")]
+#[link(name = "pthread")]
+extern {}
+
#[cfg(target_os = "macos")]
#[link(name = "System")]
extern {}
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 {
OsMacos => "macos".fmt(f),
OsiOS => "ios".fmt(f),
OsAndroid => "android".fmt(f),
- OsFreebsd => "freebsd".fmt(f)
+ OsFreebsd => "freebsd".fmt(f),
+ OsDragonfly => "dragonfly".fmt(f)
}
}
}
/// records this pattern's NodeId in an auxiliary
/// set (of "PatIdents that refer to nullary enums")
PatIdent(BindingMode, SpannedIdent, Option<Gc<Pat>>),
- PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where
- * we don't bind the fields to names */
+
+ /// "None" means a * pattern where we don't bind the fields to names.
+ PatEnum(Path, Option<Vec<Gc<Pat>>>),
+
PatStruct(Path, Vec<FieldPat>, bool),
PatTup(Vec<Gc<Pat>>),
PatBox(Gc<Pat>),
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));
subpats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat>;
fn pat_struct(&self, span: Span,
path: ast::Path, field_pats: Vec<ast::FieldPat> ) -> Gc<ast::Pat>;
+ fn pat_tuple(&self, span: Span, pats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat>;
+
+ fn pat_some(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat>;
+ fn pat_none(&self, span: Span) -> Gc<ast::Pat>;
+
+ fn pat_ok(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat>;
+ fn pat_err(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat>;
fn arm(&self, span: Span, pats: Vec<Gc<ast::Pat>> , expr: Gc<ast::Expr>) -> ast::Arm;
fn arm_unreachable(&self, span: Span) -> ast::Arm;
fn expr_if(&self, span: Span,
cond: Gc<ast::Expr>, then: Gc<ast::Expr>,
els: Option<Gc<ast::Expr>>) -> Gc<ast::Expr>;
+ fn expr_loop(&self, span: Span, block: P<ast::Block>) -> Gc<ast::Expr>;
fn lambda_fn_decl(&self, span: Span,
fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr>;
let pat = ast::PatStruct(path, field_pats, false);
self.pat(span, pat)
}
+ fn pat_tuple(&self, span: Span, pats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat> {
+ let pat = ast::PatTup(pats);
+ self.pat(span, pat)
+ }
+
+ fn pat_some(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+ let some = vec!(
+ self.ident_of("std"),
+ self.ident_of("option"),
+ self.ident_of("Some"));
+ let path = self.path_global(span, some);
+ self.pat_enum(span, path, vec!(pat))
+ }
+
+ fn pat_none(&self, span: Span) -> Gc<ast::Pat> {
+ let some = vec!(
+ self.ident_of("std"),
+ self.ident_of("option"),
+ self.ident_of("None"));
+ let path = self.path_global(span, some);
+ self.pat_enum(span, path, vec!())
+ }
+
+ fn pat_ok(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+ let some = vec!(
+ self.ident_of("std"),
+ self.ident_of("result"),
+ self.ident_of("Ok"));
+ let path = self.path_global(span, some);
+ self.pat_enum(span, path, vec!(pat))
+ }
+
+ fn pat_err(&self, span: Span, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+ let some = vec!(
+ self.ident_of("std"),
+ self.ident_of("result"),
+ self.ident_of("Err"));
+ let path = self.path_global(span, some);
+ self.pat_enum(span, path, vec!(pat))
+ }
fn arm(&self, _span: Span, pats: Vec<Gc<ast::Pat>> , expr: Gc<ast::Expr>) -> ast::Arm {
ast::Arm {
self.expr(span, ast::ExprIf(cond, self.block_expr(then), els))
}
+ fn expr_loop(&self, span: Span, block: P<ast::Block>) -> Gc<ast::Expr> {
+ self.expr(span, ast::ExprLoop(block, None))
+ }
+
fn lambda_fn_decl(&self, span: Span,
fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr> {
self.expr(span, ast::ExprFnBlock(fn_decl, blk))
} => {
// 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:
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,
impl_to_source!(Generics, generics_to_string)
impl_to_source!(Gc<ast::Item>, item_to_string)
impl_to_source!(Gc<ast::Method>, method_to_string)
+ impl_to_source!(Gc<ast::Stmt>, stmt_to_string)
impl_to_source!(Gc<ast::Expr>, expr_to_string)
impl_to_source!(Gc<ast::Pat>, pat_to_string)
+ impl_to_source!(ast::Arm, arm_to_string)
impl_to_source_slice!(ast::Ty, ", ")
impl_to_source_slice!(Gc<ast::Item>, "\n\n")
impl_to_tokens!(ast::Ident)
impl_to_tokens!(Gc<ast::Item>)
impl_to_tokens!(Gc<ast::Pat>)
+ impl_to_tokens!(ast::Arm)
impl_to_tokens!(Gc<ast::Method>)
impl_to_tokens_lifetime!(&'a [Gc<ast::Item>])
impl_to_tokens!(ast::Ty)
impl_to_tokens_lifetime!(&'a [ast::Ty])
impl_to_tokens!(Generics)
+ impl_to_tokens!(Gc<ast::Stmt>)
impl_to_tokens!(Gc<ast::Expr>)
impl_to_tokens!(ast::Block)
impl_to_tokens!(ast::Arg)
base::MacExpr::new(expanded)
}
+pub fn expand_quote_arm(cx: &mut ExtCtxt,
+ sp: Span,
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
+ let expanded = expand_parse_call(cx, sp, "parse_arm", vec!(), tts);
+ base::MacExpr::new(expanded)
+}
+
pub fn expand_quote_ty(cx: &mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree])
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{
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();
}
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);
+ }
}
}
}
};
}
- 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()
}
self.commit_expr_expecting(discriminant, token::LBRACE);
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::RBRACE {
- let attrs = self.parse_outer_attributes();
- let pats = self.parse_pats();
- let mut guard = None;
- if self.eat_keyword(keywords::If) {
- guard = Some(self.parse_expr());
- }
- self.expect(&token::FAT_ARROW);
- let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
-
- let require_comma =
- !classify::expr_is_simple_block(expr)
- && self.token != token::RBRACE;
-
- if require_comma {
- self.commit_expr(expr, &[token::COMMA], &[token::RBRACE]);
- } else {
- self.eat(&token::COMMA);
- }
-
- arms.push(ast::Arm {
- attrs: attrs,
- pats: pats,
- guard: guard,
- body: expr
- });
+ arms.push(self.parse_arm());
}
let hi = self.span.hi;
self.bump();
return self.mk_expr(lo, hi, ExprMatch(discriminant, arms));
}
+ pub fn parse_arm(&mut self) -> Arm {
+ let attrs = self.parse_outer_attributes();
+ let pats = self.parse_pats();
+ let mut guard = None;
+ if self.eat_keyword(keywords::If) {
+ guard = Some(self.parse_expr());
+ }
+ self.expect(&token::FAT_ARROW);
+ let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
+
+ let require_comma =
+ !classify::expr_is_simple_block(expr)
+ && self.token != token::RBRACE;
+
+ if require_comma {
+ self.commit_expr(expr, &[token::COMMA], &[token::RBRACE]);
+ } else {
+ self.eat(&token::COMMA);
+ }
+
+ ast::Arm {
+ attrs: attrs,
+ pats: pats,
+ guard: guard,
+ body: expr,
+ }
+ }
+
/// Parse an expression
pub fn parse_expr(&mut self) -> Gc<Expr> {
return self.parse_expr_res(UNRESTRICTED);
}
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.
// 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);
use codemap::{CodeMap, BytePos};
use codemap;
use diagnostic;
-use parse::classify::expr_is_simple_block;
use parse::token;
use parse::lexer::comments;
use parse;
// downcasts.
let (_, wr): (uint, Box<MemWriter>) = mem::transmute_copy(&s.s.out);
let result =
- String::from_utf8(Vec::from_slice(wr.get_ref())).unwrap();
+ String::from_utf8(Vec::from_slice(wr.get_ref().as_slice())).unwrap();
mem::forget(wr);
result.to_string()
}
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))
}
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));
}
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_,
//! 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"]
/// # Example
///
/// ```rust
+/// # #![allow(deprecated)]
/// use url::Url;
///
/// let raw = "https://username@example.com:8080/foo/bar?baz=qux#quz";
/// # Example
///
/// ```rust
+/// # #![allow(deprecated)]
/// use url::encode;
///
/// let url = encode("https://example.com/Rust (programming language)");
/// # Example
///
/// ```rust
+/// # #![allow(deprecated)]
/// use url::decode;
///
/// let url = decode("https://example.com/Rust%20(programming%20language)");
/// # 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())];
/// # Example
///
/// ```rust
+/// # #![allow(deprecated)]
/// use url::get_scheme;
///
/// let scheme = match get_scheme("https://example.com/") {
#[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);
}
-Subproject commit cd24b5c6633b27df2b84249a65a46a610b734494
+Subproject commit 0d999e5b315b6ff78fcea772466d985ce53fd8dc
#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__)
#endif
#endif
-#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__)
+#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || defined(__DragonFly__)
extern char **environ;
#endif
#endif
+#if defined(__DragonFly__)
+#include <errno.h>
+// In DragonFly __error() is an inline function and as such
+// no symbol exists for it.
+int *__dfly_error(void) { return __error(); }
+#endif
+
//
// Local Variables:
// mode: C++
# 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
#![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.
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() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Enum<'a> {
+ A(&'a int),
+ B(bool),
+}
+
+fn foo() -> int {
+ let mut n = 42;
+ let mut x = A(&mut n);
+ match x {
+ A(_) if { x = B(false); false } => 1,
+ //~^ ERROR cannot assign in a pattern guard
+ A(_) if { let y = &mut x; *y = B(false); false } => 1,
+ //~^ ERROR cannot mutably borrow in a pattern guard
+ //~^^ ERROR cannot assign in a pattern guard
+ A(p) => *p,
+ B(_) => 2,
+ }
+}
+
+fn main() {
+ foo();
+}
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+
+#![deny(deprecated)]
+
+extern crate url;
+
+fn main() {
+ let _ = url::Url::parse("http://example.com");
+ //~^ ERROR use of deprecated item: This is being removed. Use rust-url instead. http://servo.github.io/rust-url/
+}
--- /dev/null
+#![feature(phase)]
+#![no_std]
+#![feature(globs)]
+#[phase(plugin, link)]
+extern crate std = "std";
+extern crate rt = "native";
+use std::prelude::*;
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pretty-compare-only
+// pretty-mode:typed
+// pp-exact:issue-4264.pp
+
+// #4264 fixed-length vector types
+
+pub fn foo(_: [int, ..(3 as uint)]) { }
+
+pub fn bar() {
+ static FOO: uint = ((5u as uint) - (4u as uint) as uint);
+ let _: [(), ..(FOO as uint)] = ([(() as ())] as [(), .. 1]);
+
+ let _: [(), ..(1u as uint)] = ([(() as ())] as [(), .. 1]);
+
+ let _ =
+ (((&((([(1i as int), (2 as int), (3 as int)] as [int, .. 3])) as
+ [int, .. 3]) as &[int, .. 3]) as *const _ as
+ *const [int, .. 3]) as *const [int, ..(3u as uint)] as
+ *const [int, .. 3]);
+ (match (() as ()) {
+ () => {
+ #[inline]
+ #[allow(dead_code)]
+ static __STATIC_FMTSTR:
+ [::std::fmt::rt::Piece<'static>, ..(1u as uint)] =
+ ([((::std::fmt::rt::String as
+ fn(&'static str) -> core::fmt::rt::Piece<'static>)(("test"
+ as
+ &'static str))
+ as core::fmt::rt::Piece<'static>)] as
+ [core::fmt::rt::Piece<'static>, .. 1]);
+ let __args_vec =
+ (&([] as &'static [core::fmt::Argument<'static>]) as
+ &'static [core::fmt::Argument<'static>]);
+ let __args =
+ (unsafe {
+ ((::std::fmt::Arguments::new as
+ unsafe fn(&'static [core::fmt::rt::Piece<'static>], &'a [core::fmt::Argument<'a>]) -> core::fmt::Arguments<'a>)((__STATIC_FMTSTR
+ as
+ [core::fmt::rt::Piece<'static>, .. 1]),
+ (__args_vec
+ as
+ &'static [core::fmt::Argument<'static>]))
+ as core::fmt::Arguments<'static>)
+ } as core::fmt::Arguments<'static>);
+
+
+
+
+
+
+
+
+ ((::std::fmt::format as
+ fn(&core::fmt::Arguments<'_>) -> collections::string::String)((&(__args
+ as
+ core::fmt::Arguments<'static>)
+ as
+ &core::fmt::Arguments<'static>))
+ as collections::string::String)
+ }
+ } as collections::string::String);
+}
+pub type Foo = [int, ..(3u as uint)];
+pub struct Bar {
+ pub x: [int, ..(3u as uint)],
+}
+pub struct TupleBar([int, ..(4u as uint)]);
+pub enum Baz { BazVariant([int, ..(5u as uint)]), }
+pub fn id<T>(x: T) -> T { (x as T) }
+pub fn use_id() {
+ let _ =
+ ((id::<[int, ..(3u as uint)]> as
+ fn([int, .. 3]) -> [int, .. 3])(([(1 as int), (2 as int),
+ (3 as int)] as [int, .. 3])) as
+ [int, .. 3]);
+}
+fn main() { }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pretty-compare-only
+// pretty-mode:typed
+// pp-exact:issue-4264.pp
+
+// #4264 fixed-length vector types
+
+pub fn foo(_: [int, ..3]) {}
+
+pub fn bar() {
+ static FOO: uint = 5u - 4u;
+ let _: [(), ..FOO] = [()];
+
+ let _ : [(), ..1u] = [()];
+
+ let _ = &([1i,2,3]) as *const _ as *const [int, ..3u];
+
+ format!("test");
+}
+
+pub type Foo = [int, ..3u];
+
+pub struct Bar {
+ pub x: [int, ..3u]
+}
+
+pub struct TupleBar([int, ..4u]);
+
+pub enum Baz {
+ BazVariant([int, ..5u])
+}
+
+pub fn id<T>(x: T) -> T { x }
+
+pub fn use_id() {
+ let _ = id::<[int, ..3u]>([1,2,3]);
+}
+
+
+fn main() {}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+
+fn main() {
+ let x = match { 5i } { 1 => 5i, 2 => 6, _ => 7, };
+ assert_eq!(x , 7);
+}
"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()],
};
}
let _y =
match x {
Some(_) => "some(_)".to_string(),
- None => "none".to_string()
+ None => "none".to_string(),
};
}
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;
N11 -> N12;
N12 -> N13;
N13 -> N14;
- N14 -> N7;
- N7 -> N15;
- N15 -> N1;
+ N14 -> N15;
+ N15 -> N7;
+ N7 -> N16;
+ N16 -> N1;
}
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;
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;
}
--- /dev/null
+-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" ]
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn outer<T>() {
+ #[allow(dead_code)]
+ fn inner() -> uint {
+ 8675309
+ }
+}
+
+fn main() {
+ outer::<int>();
+ outer::<uint>();
+}
let pat = quote_pat!(cx, Some(_));
check_pp(ext_cx, pat, pprust::print_pat, "Some(_)".to_string());
+ let arm = quote_arm!(cx, (ref x, ref y) => (x, y));
+ check_pp(ext_cx, arm, pprust::print_stmt, "(ref x, ref y) = (x, y)".to_string());
}
fn check_pp<T>(cx: fake_ext_ctxt,
let _b: Option<Gc<syntax::ast::Item>> = quote_item!(cx, static foo : int = $e_toks; );
let _c: Gc<syntax::ast::Pat> = quote_pat!(cx, (x, 1 .. 4, *) );
let _d: Gc<syntax::ast::Stmt> = quote_stmt!(cx, let x = $a; );
+ let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) );
let _e: Gc<syntax::ast::Expr> = quote_expr!(cx, match foo { $p_toks => 10 } );
let _f: Gc<syntax::ast::Expr> = quote_expr!(cx, ());
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 {
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);
}
#[cfg(target_os = "freebsd")]
mod hello;
+#[cfg(target_os = "dragonfly")]
+mod hello;
+
#[cfg(target_os = "android")]
mod hello;
#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
mod m {
#[main]
#[cfg(target_arch = "x86")]
// 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";
extern crate serialize;
+use std::io;
+use std::io::{IoError, IoResult, SeekStyle};
+use std::slice;
+
use serialize::{Encodable, Encoder};
use serialize::json;
use serialize::ebml::writer;
-use std::io::MemWriter;
+
+static BUF_CAPACITY: uint = 128;
+
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+ // compute offset as signed and clamp to prevent overflow
+ let pos = match seek {
+ io::SeekSet => 0,
+ io::SeekEnd => end,
+ io::SeekCur => cur,
+ } as i64;
+
+ if offset + pos < 0 {
+ Err(IoError {
+ kind: io::InvalidInput,
+ desc: "invalid seek to a negative offset",
+ detail: None
+ })
+ } else {
+ Ok((offset + pos) as u64)
+ }
+}
+
+/// Writes to an owned, growable byte vector that supports seeking.
+///
+/// # Example
+///
+/// ```rust
+/// # #![allow(unused_must_use)]
+/// use std::io::SeekableMemWriter;
+///
+/// let mut w = SeekableMemWriter::new();
+/// w.write([0, 1, 2]);
+///
+/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// ```
+pub struct SeekableMemWriter {
+ buf: Vec<u8>,
+ pos: uint,
+}
+
+impl SeekableMemWriter {
+ /// Create a new `SeekableMemWriter`.
+ #[inline]
+ pub fn new() -> SeekableMemWriter {
+ SeekableMemWriter::with_capacity(BUF_CAPACITY)
+ }
+ /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for
+ /// the internal buffer.
+ #[inline]
+ pub fn with_capacity(n: uint) -> SeekableMemWriter {
+ SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 }
+ }
+
+ /// Acquires an immutable reference to the underlying buffer of this
+ /// `SeekableMemWriter`.
+ ///
+ /// No method is exposed for acquiring a mutable reference to the buffer
+ /// because it could corrupt the state of this `MemWriter`.
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
+
+ /// Unwraps this `SeekableMemWriter`, returning the underlying buffer
+ #[inline]
+ pub fn unwrap(self) -> Vec<u8> { self.buf }
+}
+
+impl Writer for SeekableMemWriter {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ if self.pos == self.buf.len() {
+ self.buf.push_all(buf)
+ } else {
+ // Make sure the internal buffer is as least as big as where we
+ // currently are
+ let difference = self.pos as i64 - self.buf.len() as i64;
+ if difference > 0 {
+ self.buf.grow(difference as uint, &0);
+ }
+
+ // Figure out what bytes will be used to overwrite what's currently
+ // there (left), and what will be appended on the end (right)
+ let cap = self.buf.len() - self.pos;
+ let (left, right) = if cap <= buf.len() {
+ (buf.slice_to(cap), buf.slice_from(cap))
+ } else {
+ (buf, &[])
+ };
+
+ // Do the necessary writes
+ if left.len() > 0 {
+ slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
+ }
+ if right.len() > 0 {
+ self.buf.push_all(right);
+ }
+ }
+
+ // Bump us forward
+ self.pos += buf.len();
+ Ok(())
+ }
+}
+
+impl Seek for SeekableMemWriter {
+ #[inline]
+ fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
+
+ #[inline]
+ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+ let new = try!(combine(style, self.pos, self.buf.len(), pos));
+ self.pos = new as uint;
+ Ok(())
+ }
+}
#[deriving(Encodable)]
struct Foo {
fn encode_json<'a,
T: Encodable<json::Encoder<'a>,
std::io::IoError>>(val: &T,
- wr: &'a mut MemWriter) {
+ wr: &'a mut SeekableMemWriter) {
let mut encoder = json::Encoder::new(wr);
val.encode(&mut encoder);
}
fn encode_ebml<'a,
- T: Encodable<writer::Encoder<'a, MemWriter>,
+ T: Encodable<writer::Encoder<'a, SeekableMemWriter>,
std::io::IoError>>(val: &T,
- wr: &'a mut MemWriter) {
+ wr: &'a mut SeekableMemWriter) {
let mut encoder = writer::Encoder::new(wr);
val.encode(&mut encoder);
}
pub fn main() {
let target = Foo{baz: false,};
- let mut wr = MemWriter::new();
+ let mut wr = SeekableMemWriter::new();
let proto = JSON;
match proto {
JSON => encode_json(&target, &mut wr),
#[link(name = "execinfo")]
extern {}
+#[cfg(target_os = "dragonfly")]
+#[link(name = "c")]
+extern {}
+
#[cfg(target_os = "macos")]
#[link(name = "System")]
extern {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(macro_rules)]
+
+macro_rules! four (
+ () => (4)
+)
+fn main() {
+ let _x: [u16, ..four!()];
+}
#[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 {
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-macos apparently gargantuan mmap requests are ok?
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate green;
+extern crate native;
+
+use std::task::TaskBuilder;
+use native::NativeTaskBuilder;
+
+green_start!(main)
+
+fn main() {
+ test();
+
+ let (tx, rx) = channel();
+ TaskBuilder::new().native().spawn(proc() {
+ tx.send(test());
+ });
+ rx.recv();
+}
+
+#[cfg(not(target_word_size = "64"))]
+fn test() {}
+
+#[cfg(target_word_size = "64")]
+fn test() {
+ let (tx, rx) = channel();
+ spawn(proc() {
+ TaskBuilder::new().stack_size(1024 * 1024 * 1024 * 64).spawn(proc() {
+ });
+ tx.send(());
+ });
+
+ assert!(rx.recv_opt().is_err());
+}
#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "dragonfly")]
#[cfg(target_os = "android")]
pub fn main() { }