diff --git a/README.md b/README.md index 5927fb292d8b9..a94c154b67d03 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,26 @@ documentation. When complete, `make install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the API-documentation tool. - system. 3. Read the [tutorial]. 4. Enjoy! +### Building on Windows + +To easily build on windows we can use [MSYS2](http://sourceforge.net/projects/msys2/): + +1. Grab the latest MSYS2 installer and go through the installer. +2. Now from the MSYS2 terminal we want to install the mingw64 toolchain and the other + tools we need. + + $ pacman -S mingw-w64-i686-toolchain + $ pacman -S base-devel + +3. With that now start `mingw32_shell.bat` from where you installed MSYS2 (i.e. `C:\msys`). +4. From there just navigate to where you have Rust's source code, configure and build it: + + $ ./configure --build=i686-pc-mingw32 + $ make && make install + [repo]: https://github.com/rust-lang/rust [tarball]: http://static.rust-lang.org/dist/rust-nightly.tar.gz [tutorial]: http://doc.rust-lang.org/tutorial.html diff --git a/man/rustdoc.1 b/man/rustdoc.1 index 6bde792f59c76..03414ca163ec2 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -38,6 +38,15 @@ directory to load plugins from (default: /tmp/rustdoc_ng/plugins) -L --library-path directory to add to crate search path .TP +--html-in-header +file to add to +.TP +--html-before-content +file to add in , before content +.TP +--html-after-content +file to add in , after content +.TP -h, --help Print help diff --git a/mk/dist.mk b/mk/dist.mk index 6a89897c29277..76ebfe9b49fd6 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -54,6 +54,7 @@ PKG_FILES := \ driver \ etc \ $(foreach crate,$(CRATES),lib$(crate)) \ + libcoretest \ libbacktrace \ rt \ rustllvm \ diff --git a/mk/docs.mk b/mk/docs.mk index 8098a0682a5d0..213565b09ac27 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -35,16 +35,16 @@ DOCS := index intro tutorial guide guide-ffi guide-macros guide-lifetimes \ PDF_DOCS := tutorial rust RUSTDOC_DEPS_rust := doc/full-toc.inc -RUSTDOC_FLAGS_rust := --markdown-in-header=doc/full-toc.inc +RUSTDOC_FLAGS_rust := --html-in-header=doc/full-toc.inc L10N_LANGS := ja # Generally no need to edit below here. # The options are passed to the documentation generators. -RUSTDOC_HTML_OPTS_NO_CSS = --markdown-before-content=doc/version_info.html \ - --markdown-in-header=doc/favicon.inc \ - --markdown-after-content=doc/footer.inc \ +RUSTDOC_HTML_OPTS_NO_CSS = --html-before-content=doc/version_info.html \ + --html-in-header=doc/favicon.inc \ + --html-after-content=doc/footer.inc \ --markdown-playground-url='http://play.rust-lang.org/' RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css diff --git a/mk/tests.mk b/mk/tests.mk index 1989d6ef86797..44bedde99ccff 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -14,7 +14,12 @@ ###################################################################### # The names of crates that must be tested -TEST_TARGET_CRATES = $(TARGET_CRATES) + +# libcore tests are in a separate crate +DEPS_coretest := +$(eval $(call RUST_CRATE,coretest)) + +TEST_TARGET_CRATES = $(filter-out core,$(TARGET_CRATES)) coretest TEST_DOC_CRATES = $(DOC_CRATES) TEST_HOST_CRATES = $(HOST_CRATES) TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) @@ -172,7 +177,7 @@ check-notidy: cleantmptestlogs cleantestlibs all check-stage2 $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log check-lite: cleantestlibs cleantmptestlogs \ - $(foreach crate,$(TARGET_CRATES),check-stage2-$(crate)) \ + $(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \ check-stage2-rpass \ check-stage2-rfail check-stage2-cfail check-stage2-rmake $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 4de7b89ba6f29..9eac38e4cd5b7 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -42,7 +42,7 @@ pub mod common; pub mod errors; #[start] -fn start(argc: int, argv: **u8) -> int { +fn start(argc: int, argv: *const *const u8) -> int { green::start(argc, argv, rustuv::event_loop, main) } diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index 13e44765d59eb..bba9594afeb6d 100644 --- a/src/doc/guide-ffi.md +++ b/src/doc/guide-ffi.md @@ -50,19 +50,19 @@ use libc::{c_int, size_t}; #[link(name = "snappy")] extern { - fn snappy_compress(input: *u8, + fn snappy_compress(input: *const u8, input_length: size_t, compressed: *mut u8, compressed_length: *mut size_t) -> c_int; - fn snappy_uncompress(compressed: *u8, + fn snappy_uncompress(compressed: *const u8, compressed_length: size_t, uncompressed: *mut u8, uncompressed_length: *mut size_t) -> c_int; fn snappy_max_compressed_length(source_length: size_t) -> size_t; - fn snappy_uncompressed_length(compressed: *u8, + fn snappy_uncompressed_length(compressed: *const u8, compressed_length: size_t, result: *mut size_t) -> c_int; - fn snappy_validate_compressed_buffer(compressed: *u8, + fn snappy_validate_compressed_buffer(compressed: *const u8, compressed_length: size_t) -> c_int; } # fn main() {} @@ -82,7 +82,7 @@ the allocated memory. The length is less than or equal to the capacity. ~~~~ # extern crate libc; # use libc::{c_int, size_t}; -# unsafe fn snappy_validate_compressed_buffer(_: *u8, _: size_t) -> c_int { 0 } +# unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 } # fn main() {} pub fn validate_compressed_buffer(src: &[u8]) -> bool { unsafe { @@ -106,7 +106,7 @@ the true length after compression for setting the length. ~~~~ # extern crate libc; # use libc::{size_t, c_int}; -# unsafe fn snappy_compress(a: *u8, b: size_t, c: *mut u8, +# unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8, # d: *mut size_t) -> c_int { 0 } # unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a } # fn main() {} @@ -132,11 +132,11 @@ format and `snappy_uncompressed_length` will retrieve the exact buffer size requ ~~~~ # extern crate libc; # use libc::{size_t, c_int}; -# unsafe fn snappy_uncompress(compressed: *u8, +# unsafe fn snappy_uncompress(compressed: *const u8, # compressed_length: size_t, # uncompressed: *mut u8, # uncompressed_length: *mut size_t) -> c_int { 0 } -# unsafe fn snappy_uncompressed_length(compressed: *u8, +# unsafe fn snappy_uncompressed_length(compressed: *const u8, # compressed_length: size_t, # result: *mut size_t) -> c_int { 0 } # fn main() {} @@ -418,7 +418,7 @@ Unsafe functions, on the other hand, advertise it to the world. An unsafe functi this: ~~~~ -unsafe fn kaboom(ptr: *int) -> int { *ptr } +unsafe fn kaboom(ptr: *const int) -> int { *ptr } ~~~~ This function can only be called from an `unsafe` block or another `unsafe` function. @@ -453,7 +453,7 @@ use std::ptr; #[link(name = "readline")] extern { - static mut rl_prompt: *libc::c_char; + static mut rl_prompt: *const libc::c_char; } fn main() { @@ -478,7 +478,7 @@ extern crate libc; #[link(name = "kernel32")] #[allow(non_snake_case_functions)] extern "stdcall" { - fn SetEnvironmentVariableA(n: *u8, v: *u8) -> libc::c_int; + fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int; } # fn main() { } ~~~~ diff --git a/src/doc/guide-macros.md b/src/doc/guide-macros.md index 45745c7b7bc7a..6d3825f8ecf12 100644 --- a/src/doc/guide-macros.md +++ b/src/doc/guide-macros.md @@ -355,6 +355,7 @@ macro_rules! biased_match_rec ( _ => { $err } } ); + // Produce the requested values ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) ) ) @@ -364,7 +365,7 @@ macro_rules! biased_match ( ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )* binds $bind_res:ident ) => ( - let ( $( $bind_res ),* ) = biased_match_rec!( + let $bind_res = biased_match_rec!( $( ($e) ~ ($p) else $err ; )* binds $bind_res ); diff --git a/src/doc/guide-runtime.md b/src/doc/guide-runtime.md index 0050bd2d77f8f..1367bdc07555f 100644 --- a/src/doc/guide-runtime.md +++ b/src/doc/guide-runtime.md @@ -245,7 +245,7 @@ extern crate green; extern crate rustuv; #[start] -fn start(argc: int, argv: **u8) -> int { +fn start(argc: int, argv: *const *const u8) -> int { green::start(argc, argv, rustuv::event_loop, main) } @@ -261,7 +261,9 @@ inside of an OS thread. extern crate native; #[start] -fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) } +fn start(argc: int, argv: *const *const u8) -> int { + native::start(argc, argv, main) +} fn main() {} ~~~ diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index 81d7f37d6fbcc..9021b761954d0 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -457,6 +457,8 @@ the string in response. The child terminates when it receives `0`. Here is the function that implements the child task: ~~~ +#![allow(deprecated)] + use std::comm::DuplexStream; # fn main() { fn stringifier(channel: &DuplexStream) { @@ -481,6 +483,8 @@ response itself is simply the stringified version of the received value, Here is the code for the parent task: ~~~ +#![allow(deprecated)] + use std::comm::duplex; # use std::task::spawn; # use std::comm::DuplexStream; diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index 609d8937c80c5..3852591da5ba2 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -79,7 +79,7 @@ let ref_2: &mut u8 = unsafe { mem::transmute(&mut *ref_1) }; ## Raw pointers Rust offers two additional pointer types "raw pointers", written as -`*T` and `*mut T`. They're an approximation of C's `const T*` and `T*` +`*const T` and `*mut T`. They're an approximation of C's `const T*` and `T*` respectively; indeed, one of their most common uses is for FFI, interfacing with external C libraries. @@ -100,7 +100,7 @@ offered by the Rust language and libraries. For example, they - lack any form of lifetimes, unlike `&`, and so the compiler cannot reason about dangling pointers; and - have no guarantees about aliasing or mutability other than mutation - not being allowed directly through a `*T`. + not being allowed directly through a `*const T`. Fortunately, they come with a redeeming feature: the weaker guarantees mean weaker restrictions. The missing restrictions make raw pointers @@ -131,13 +131,13 @@ unsafe, and neither is converting to an integer. At runtime, a raw pointer `*` and a reference pointing to the same piece of data have an identical representation. In fact, an `&T` -reference will implicitly coerce to an `*T` raw pointer in safe code +reference will implicitly coerce to an `*const T` raw pointer in safe code and similarly for the `mut` variants (both coercions can be performed -explicitly with, respectively, `value as *T` and `value as *mut T`). +explicitly with, respectively, `value as *const T` and `value as *mut T`). -Going the opposite direction, from `*` to a reference `&`, is not +Going the opposite direction, from `*const` to a reference `&`, is not safe. A `&T` is always valid, and so, at a minimum, the raw pointer -`*T` has to be a valid to a valid instance of type `T`. Furthermore, +`*const T` has to be a valid to a valid instance of type `T`. Furthermore, the resulting pointer must satisfy the aliasing and mutability laws of references. The compiler assumes these properties are true for any references, no matter how they are created, and so any conversion from @@ -149,7 +149,7 @@ The recommended method for the conversion is ``` let i: u32 = 1; // explicit cast -let p_imm: *u32 = &i as *u32; +let p_imm: *const u32 = &i as *const u32; let mut m: u32 = 2; // implicit coercion let p_mut: *mut u32 = &mut m; @@ -256,7 +256,7 @@ impl Drop for Unique { // Copy the object out from the pointer onto the stack, // where it is covered by normal Rust destructor semantics // and cleans itself up, if necessary - ptr::read(self.ptr as *T); + ptr::read(self.ptr as *const T); // clean-up our allocation free(self.ptr as *mut c_void) @@ -267,12 +267,12 @@ impl Drop for Unique { // A comparison between the built-in `Box` and this reimplementation fn main() { { - let mut x = box 5; + let mut x = box 5i; *x = 10; } // `x` is freed here { - let mut y = Unique::new(5); + let mut y = Unique::new(5i); *y.borrow_mut() = 10; } // `y` is freed here } @@ -457,7 +457,7 @@ extern crate libc; // Entry point for this program #[start] -fn start(_argc: int, _argv: **u8) -> int { +fn start(_argc: int, _argv: *const *const u8) -> int { 0 } @@ -482,7 +482,7 @@ compiler's name mangling too: extern crate libc; #[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(argc: int, argv: **u8) -> int { +pub extern fn main(argc: int, argv: *const *const u8) -> int { 0 } @@ -540,8 +540,8 @@ use core::mem; use core::raw::Slice; #[no_mangle] -pub extern fn dot_product(a: *u32, a_len: u32, - b: *u32, b_len: u32) -> u32 { +pub extern fn dot_product(a: *const u32, a_len: u32, + b: *const u32, b_len: u32) -> u32 { // Convert the provided arrays into Rust slices. // The core::raw module guarantees that the Slice // structure has the same memory layout as a &[T] @@ -573,7 +573,7 @@ extern fn begin_unwind(args: &core::fmt::Arguments, #[lang = "stack_exhausted"] extern fn stack_exhausted() {} #[lang = "eh_personality"] extern fn eh_personality() {} -# #[start] fn start(argc: int, argv: **u8) -> int { 0 } +# #[start] fn start(argc: int, argv: *const *const u8) -> int { 0 } # fn main() {} ``` @@ -595,7 +595,7 @@ standard library itself. > parts of the language may never be full specified and so details may > differ wildly between implementations (and even versions of `rustc` > itself). -> +> > Furthermore, this is just an overview; the best form of > documentation for specific instances of these features are their > definitions and uses in `std`. @@ -627,7 +627,7 @@ via a declaration like extern "rust-intrinsic" { fn transmute(x: T) -> U; - fn offset(dst: *T, offset: int) -> *T; + fn offset(dst: *const T, offset: int) -> *const T; } ``` @@ -677,8 +677,8 @@ unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) { } #[start] -fn main(argc: int, argv: **u8) -> int { - let x = box 1; +fn main(argc: int, argv: *const *const u8) -> int { + let x = box 1i; 0 } diff --git a/src/doc/guide.md b/src/doc/guide.md index e5a753f55d087..cadbd8ee9adf0 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -160,7 +160,7 @@ Save the file, and then type this into your terminal window: ```{bash} $ rustc hello_world.rs -$ ./hello_world # just 'hello_world' on Windows +$ ./hello_world # or hello_world.exe on Windows Hello, world ``` @@ -243,7 +243,7 @@ There are now two files: our source code, with the `.rs` extension, and the executable (`hello_world.exe` on Windows, `hello_world` everywhere else) ```{bash} -$ ./hello_world # or ./hello_world.exe on Windows +$ ./hello_world # or hello_world.exe on Windows ``` This prints out our `Hello, world!` text to our terminal. @@ -285,8 +285,9 @@ At first, your program doesn't have any dependencies, so we'll only be using the first part of its functionality. Eventually, we'll add more. Since we started off by using Cargo, it'll be easy to add later. -Let's convert Hello World to Cargo. The first thing we need to do is install -it. To do this, we need to build it from source. There are no binaries yet. +Let's convert Hello World to Cargo. The first thing we need to do to begin using Cargo +is to install Cargo. To do this, we need to build it from source. There are no binaries +yet. First, let's go back to our projects directory. We don't want Cargo to live in our project! @@ -412,23 +413,209 @@ rest of your Rust career. Next, we'll learn more about Rust itself, by starting to write a more complicated program. We hope you want to do more with Rust than just print "Hello, world!" -## If +## Guessing Game -## Functions +Let's write a bigger program in Rust. We could just go through a laundry list +of Rust features, but that's boring. Instead, we'll learn more about how to +code in Rust by writing a few example projects. -return +For our first project, we'll implement a classic beginner programming problem: +the guessing game. Here's how it works: Our program will generate a random +integer between one and a hundred. It will then prompt us to enter a guess. +Upon entering our guess, it will tell us if we're too low or too high. Once we +guess correctly, it will congratulate us, and print the number of guesses we've +taken to the screen. Sound good? It sounds easy, but it'll end up showing off a +number of basic features of Rust. -comments +### Set up -## Testing +Let's set up a new project. Go to your projects directory, and make a new +directory for the project, as well as a `src` directory for our code: -attributes +```{bash} +$ cd ~/projects +$ mkdir guessing_game +$ cd guessing_game +$ mkdir src +``` -stability markers +Great. Next, let's make a `Cargo.toml` file so Cargo knows how to build our +project: -## Crates and Modules +```{ignore} +[package] -visibility +name = "guessing_game" +version = "0.1.0" +authors = [ "someone@example.com" ] + +[[bin]] + +name = "guessing_game" +``` + +Finally, we need our source file. Let's just make it hello world for now, so we +can check that our setup works. In `src/guessing_game.rs`: + +```{rust} +fn main() { + println!("Hello world!"); +} +``` + +Let's make sure that worked: + +```{bash} +$ cargo build + Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game) +$ +``` + +Excellent! Open up your `src/guessing_game.rs` again. We'll be writing all of +our code in this file. The next section of the tutorial will show you how to +build multiple-file projects. + +## Variable bindings + +The first thing we'll learn about are 'variable bindings.' They look like this: + +```{rust} +let x = 5i; +``` + +In many languages, this is called a 'variable.' But Rust's variable bindings +have a few tricks up their sleeves. Rust has a very powerful feature called +'pattern matching' that we'll get into detail with later, but the left +hand side of a `let` expression is a full pattern, not just a variable name. +This means we can do things like: + +```{rust} +let (x, y) = (1i, 2i); +``` + +After this expression is evaluated, `x` will be one, and `y` will be two. +Patterns are really powerful, but this is about all we can do with them so far. +So let's just keep this in the back of our minds as we go forward. + +By the way, in these examples, `i` indicates that the number is an integer. + +Rust is a statically typed language, which means that we specify our types up +front. So why does our first example compile? Well, Rust has this thing called +"[Hindley-Milner type +inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)", +named after some really smart type theorists. If you clicked that link, don't +be scared: what this means for you is that Rust will attempt to infer the types +in your program, and it's pretty good at it. If it can infer the type, Rust +doesn't require you to actually type it out. + +We can add the type if we want to. Types come after a colon (`:`): + +```{rust} +let x: int = 5; +``` + +If I asked you to read this out loud to the rest of the class, you'd say "`x` +is a binding with the type `int` and the value `five`." Rust requires you to +initialize the binding with a value before you're allowed to use it. If +we try... + +```{ignore} +let x; +``` + +...we'll get an error: + +```{ignore} +src/guessing_game.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type +src/guessing_game.rs:2 let x; + ^ +``` + +Giving it a type will compile, though: + +```{ignore} +let x: int; +``` + +Let's try it out. Change your `src/guessing_game.rs` file to look like this: + +```{rust} +fn main() { + let x: int; + + println!("Hello world!"); +} +``` + +You can use `cargo build` on the command line to build it. You'll get a warning, +but it will still print "Hello, world!": + +```{ignore,notrust} + Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game) +src/guessing_game.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default +src/guessing_game.rs:2 let x: int; + ^ +``` + +Rust warns us that we never use the variable binding, but since we never use it, +no harm, no foul. Things change if we try to actually use this `x`, however. Let's +do that. Change your program to look like this: + +```{rust,ignore} +fn main() { + let x: int; + + println!("The value of x is: {}", x); +} +``` + +And try to build it. You'll get an error: + +```{bash} +$ cargo build + Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game) +src/guessing_game.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x` +src/guessing_game.rs:4 println!("The value of x is: {}", x); + ^ +note: in expansion of format_args! +:2:23: 2:77 note: expansion site +:1:1: 3:2 note: in expansion of println! +src/guessing_game.rs:4:5: 4:42 note: expansion site +error: aborting due to previous error +Could not execute process `rustc src/guessing_game.rs --crate-type bin --out-dir /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target/deps` (status=101) +``` + +Rust will not let us use a value that has not been initialized. So why let us +declare a binding without initializing it? You'd think our first example would +have errored. Well, Rust is smarter than that. Before we get to that, let's talk +about this stuff we've added to `println!`. + +If you include two curly braces (`{}`, some call them moustaches...) in your +string to print, Rust will interpret this as a request to interpolate some sort +of value. **String interpolation** is a computer science term that means "stick +in the middle of a string." We add a comma, and then `x`, to indicate that we +want `x` to be the value we're interpolating. The comma is used to separate +arguments we pass to functions and macros, if you're passing more than one. + +When you just use the double curly braces, Rust will attempt to display the +value in a meaningful way by checking out its type. If you want to specify the +format in a more detailed manner, there are a [wide number of options +available](/std/fmt/index.html). Fow now, we'll just stick to the default: +integers aren't very complicated to print. + +So, we've cleared up all of the confusion around bindings, with one exception: +why does Rust let us declare a variable binding without an initial value if we +must initialize the binding before we use it? And how does it know that we have +or have not initialized the binding? For that, we need to learn our next +concept: `if`. + +## If + +## Functions + +return + +comments ## Compound Data Types @@ -450,10 +637,35 @@ loop break/continue -iterators +## Guessing Game: complete + +At this point, you have successfully built the Guessing Game! Congratulations! +For reference, [We've placed the sample code on +GitHub](https://github.com/steveklabnik/guessing_game). + +You've now learned the basic syntax of Rust. All of this is relatively close to +various other programming languages you have used in the past. These +fundamental syntactical and semantic elements will form the foundation for the +rest of your Rust education. + +Now that you're an expert at the basics, it's time to learn about some of +Rust's more unique features. + +## iterators ## Lambdas +## Testing + +attributes + +stability markers + +## Crates and Modules + +visibility + + ## Generics ## Traits diff --git a/src/doc/intro.md b/src/doc/intro.md index 1e577a9113160..e8928cb55056c 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -133,7 +133,7 @@ Check it out: ``` fn dangling() -> Box { - let i = box 1234; + let i = box 1234i; return i; } @@ -143,8 +143,8 @@ fn add_one() -> int { } ``` -Now instead of a stack allocated `1234`, -we have a heap allocated `box 1234`. +Now instead of a stack allocated `1234i`, +we have a heap allocated `box 1234i`. Whereas `&` borrows a pointer to existing memory, creating an owned box allocates memory on the heap and places a value in it, giving you the sole pointer to that memory. @@ -152,7 +152,7 @@ You can roughly compare these two lines: ``` // Rust -let i = box 1234; +let i = box 1234i; ``` ```cpp @@ -252,7 +252,7 @@ fn main() { } ``` -This will result an error indicating that the value is no longer in scope: +The compiler will produce an error indicating that the value is no longer in scope: ```text concurrency.rs:12:20: 12:27 error: use of moved value: 'numbers' diff --git a/src/doc/rust.md b/src/doc/rust.md index 9dc5c66a08dec..58819a3cf48ee 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -442,17 +442,14 @@ of integer literal suffix: The type of an _unsuffixed_ integer literal is determined by type inference. If an integer type can be _uniquely_ determined from the surrounding program context, the unsuffixed integer literal has that type. If the program context -underconstrains the type, the unsuffixed integer literal's type is `int`; if -the program context overconstrains the type, it is considered a static type -error. +underconstrains the type, it is considered a static type error; +if the program context overconstrains the type, +it is also considered a static type error. Examples of integer literals of various forms: ~~~~ -123; 0xff00; // type determined by program context - // defaults to int in absence of type - // information - +123i; // type int 123u; // type uint 123_u; // type uint 0xff_u8; // type u8 @@ -469,8 +466,10 @@ A _floating-point literal_ has one of two forms: second decimal literal. * A single _decimal literal_ followed by an _exponent_. -By default, a floating-point literal has a generic type, but will fall back to -`f64`. A floating-point literal may be followed (immediately, without any +By default, a floating-point literal has a generic type, +and, like integer literals, the type must be uniquely determined +from the context. +A floating-point literal may be followed (immediately, without any spaces) by a _floating-point suffix_, which changes the type of the literal. There are two floating-point suffixes: `f32`, and `f64` (the 32-bit and 64-bit floating point types). @@ -478,8 +477,8 @@ floating point types). Examples of floating-point literals of various forms: ~~~~ -123.0; // type f64 -0.1; // type f64 +123.0f64; // type f64 +0.1f64; // type f64 0.1f32; // type f32 12E+99_f64; // type f64 ~~~~ @@ -1614,7 +1613,7 @@ extern crate libc; use libc::{c_char, FILE}; extern { - fn fopen(filename: *c_char, mode: *c_char) -> *FILE; + fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; } # fn main() {} ~~~~ @@ -2700,9 +2699,9 @@ must be a constant expression that can be evaluated at compile time, such as a [literal](#literals) or a [static item](#static-items). ~~~~ -[1, 2, 3, 4]; +[1i, 2, 3, 4]; ["a", "b", "c", "d"]; -[0, ..128]; // vector with 128 zeros +[0i, ..128]; // vector with 128 zeros [0u8, 0u8, 0u8, 0u8]; ~~~~ @@ -2881,7 +2880,7 @@ equals sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression. Evaluating an assignment expression [either copies or moves](#moved-and-copied-types) its right-hand operand to its left-hand operand. ~~~~ -# let mut x = 0; +# let mut x = 0i; # let y = 0; x = y; @@ -2932,7 +2931,7 @@ paren_expr : '(' expr ')' ; An example of a parenthesized expression: ~~~~ -let x = (2 + 3) * 4; +let x: int = (2 + 3) * 4; ~~~~ @@ -3016,7 +3015,7 @@ conditional expression evaluates to `false`, the `while` expression completes. An example: ~~~~ -let mut i = 0; +let mut i = 0u; while i < 10 { println!("hello"); @@ -3262,7 +3261,7 @@ Patterns can also dereference pointers by using the `&`, on `x: &int` are equivalent: ~~~~ -# let x = &3; +# let x = &3i; let y = match *x { 0 => "zero", _ => "some" }; let z = match x { &0 => "zero", _ => "some" }; @@ -3285,7 +3284,7 @@ A range of values may be specified with `..`. For example: ~~~~ -# let x = 2; +# let x = 2i; let message = match x { 0 | 1 => "not many", diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index 2287bcabff762..8199eaea82c68 100644 --- a/src/doc/rustdoc.md +++ b/src/doc/rustdoc.md @@ -103,6 +103,17 @@ rustdoc can also generate JSON, for consumption by other tools, with `rustdoc --output-format json`, and also consume already-generated JSON with `rustdoc --input-format json`. +rustdoc also supports personalizing the output from crates' documentation, +similar to markdown options. + +- `--html-in-header FILE`: includes the contents of `FILE` at the + end of the `...` section. +- `--html-before-content FILE`: includes the contents of `FILE` + directly after ``, before the rendered content (including the + search bar). +- `--html-after-content FILE`: includes the contents of `FILE` + after all the rendered content. + # Using the Documentation The web pages generated by rustdoc present the same logical hierarchy that one @@ -238,16 +249,16 @@ detected by a `.md` or `.markdown` extension. There are 4 options to modify the output that Rustdoc creates. - `--markdown-css PATH`: adds a `` tag pointing to `PATH`. -- `--markdown-in-header FILE`: includes the contents of `FILE` at the +- `--html-in-header FILE`: includes the contents of `FILE` at the end of the `...` section. -- `--markdown-before-content FILE`: includes the contents of `FILE` +- `--html-before-content FILE`: includes the contents of `FILE` directly after ``, before the rendered content (including the title). -- `--markdown-after-content FILE`: includes the contents of `FILE` +- `--html-after-content FILE`: includes the contents of `FILE` directly before ``, after all the rendered content. All of these can be specified multiple times, and they are output in -the order in which they are specified. The first line of the file must +the order in which they are specified. The first line of the file being rendered must be the title, prefixed with `%` (e.g. this page has `% Rust Documentation` on the first line). diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 456726984bc04..5fe6a5f14c2b4 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -262,7 +262,7 @@ write function, variable, and module names with lowercase letters, using underscores where they help readability, while writing types in camel case. ~~~ -let my_variable = 100; +let my_variable = 100i; type MyType = int; // primitive types are _not_ camel case ~~~ @@ -276,7 +276,7 @@ write a piece of code like this: ~~~~ # let item = "salad"; -let price; +let price: f64; if item == "salad" { price = 3.50; } else if item == "muffin" { @@ -290,7 +290,7 @@ But, in Rust, you don't have to repeat the name `price`: ~~~~ # let item = "salad"; -let price = +let price: f64 = if item == "salad" { 3.50 } else if item == "muffin" { @@ -337,11 +337,10 @@ suffix that can be used to indicate the type of a literal: `i` for `int`, In the absence of an integer literal suffix, Rust will infer the integer type based on type annotations and function signatures in the surrounding program. In the absence of any type information at all, -Rust will assume that an unsuffixed integer literal has type -`int`. +Rust will report an error and request that the type be specified explicitly. ~~~~ -let a = 1; // `a` is an `int` +let a: int = 1; // `a` is an `int` let b = 10i; // `b` is an `int`, due to the `i` suffix let c = 100u; // `c` is a `uint` let d = 1000i32; // `d` is an `i32` @@ -475,7 +474,7 @@ against each pattern in order until one matches. The matching pattern executes its corresponding arm. ~~~~ -let my_number = 1; +let my_number = 1i; match my_number { 0 => println!("zero"), 1 | 2 => println!("one or two"), @@ -501,7 +500,7 @@ matches any single value. (`..`) is a different wildcard that can match one or more fields in an `enum` variant. ~~~ -# let my_number = 1; +# let my_number = 1i; match my_number { 0 => { println!("zero") } _ => { println!("something else") } @@ -584,7 +583,7 @@ keyword `break` aborts the loop, and `continue` aborts the current iteration and continues with the next. ~~~~ -let mut cake_amount = 8; +let mut cake_amount = 8i; while cake_amount > 0 { cake_amount -= 1; } @@ -944,7 +943,7 @@ The `box` operator performs memory allocation on the heap: ~~~~ { // an integer allocated on the heap - let y = box 10; + let y = box 10i; } // the destructor frees the heap memory as soon as `y` goes out of scope ~~~~ @@ -1165,7 +1164,7 @@ let z = x; The mutability of a value may be changed by moving it to a new owner: ~~~~ -let r = box 13; +let r = box 13i; let mut s = r; // box becomes mutable *s += 1; let t = s; // box becomes immutable @@ -1285,9 +1284,9 @@ Using the generic `List` works much like before, thanks to type inference: # Cons(value, box xs) # } let mut xs = Nil; // Unknown type! This is a `List`, but `T` can be anything. -xs = prepend(xs, 10); // Here the compiler infers `xs`'s type as `List`. -xs = prepend(xs, 15); -xs = prepend(xs, 20); +xs = prepend(xs, 10i); // Here the compiler infers `xs`'s type as `List`. +xs = prepend(xs, 15i); +xs = prepend(xs, 20i); ~~~ The code sample above demonstrates type inference making most type annotations optional. It is @@ -1410,12 +1409,12 @@ Beyond the properties granted by the size, an owned box behaves as a regular value by inheriting the mutability and lifetime of the owner: ~~~~ -let x = 5; // immutable -let mut y = 5; // mutable +let x = 5i; // immutable +let mut y = 5i; // mutable y += 2; -let x = box 5; // immutable -let mut y = box 5; // mutable +let x = box 5i; // immutable +let mut y = box 5i; // mutable *y += 2; // the `*` operator is needed to access the contained value ~~~~ @@ -1507,7 +1506,7 @@ freezing enforced statically at compile-time. An example of a non-`Freeze` type is [`RefCell`][refcell]. ~~~~ -let mut x = 5; +let mut x = 5i; { let y = &x; // `x` is now frozen. It cannot be modified or re-assigned. } @@ -1523,8 +1522,8 @@ Rust uses the unary star operator (`*`) to access the contents of a box or pointer, similarly to C. ~~~ -let owned = box 10; -let borrowed = &20; +let owned = box 10i; +let borrowed = &20i; let sum = *owned + *borrowed; ~~~ @@ -1534,9 +1533,9 @@ assignments. Such an assignment modifies the value that the pointer points to. ~~~ -let mut owned = box 10; +let mut owned = box 10i; -let mut value = 20; +let mut value = 20i; let borrowed = &mut value; *owned = *borrowed + 100; @@ -1654,12 +1653,12 @@ Unicode code points, so they cannot be freely mutated without the ability to alter the length. ~~~ -let mut xs = [1, 2, 3]; +let mut xs = [1i, 2i, 3i]; let view = xs.mut_slice(0, 2); view[0] = 5; // The type of a mutable slice is written as `&mut [T]` -let ys: &mut [int] = &mut [1, 2, 3]; +let ys: &mut [int] = &mut [1i, 2i, 3i]; ~~~ Square brackets denote indexing into a slice or fixed-size vector: diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py index c2f56c6a80709..2110f19bf86d1 100644 --- a/src/etc/licenseck.py +++ b/src/etc/licenseck.py @@ -44,6 +44,7 @@ "libsync/mpsc_intrusive.rs", # BSD "test/bench/shootout-binarytrees.rs", # BSD "test/bench/shootout-fannkuch-redux.rs", # BSD + "test/bench/shootout-mandelbrot.rs", # BSD "test/bench/shootout-meteor.rs", # BSD "test/bench/shootout-pidigits.rs", # BSD "test/bench/shootout-regex-dna.rs", # BSD diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index d8f00ac6b30fa..a15bd3ca60ff1 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -77,34 +77,39 @@ syn keyword rustEnumVariant Ok Err "syn keyword rustFunction drop " Types and traits {{{3 -syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr IntoBytes +syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr +syn keyword rustTrait IntoBytes syn keyword rustTrait ToCStr syn keyword rustTrait Char syn keyword rustTrait Clone -syn keyword rustTrait Eq Ord PartialEq PartialOrd Ordering Equiv +syn keyword rustTrait PartialEq PartialOrd Eq Ord Equiv +syn keyword rustEnum Ordering syn keyword rustEnumVariant Less Equal Greater -syn keyword rustTrait Container Mutable Map MutableMap Set MutableSet -syn keyword rustTrait FromIterator Extendable -syn keyword rustTrait Iterator DoubleEndedIterator RandomAccessIterator CloneableIterator -syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize -syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul -syn keyword rustTrait Signed Unsigned -syn keyword rustTrait Primitive Int Float FloatMath ToPrimitive FromPrimitive -"syn keyword rustTrait Expect +syn keyword rustTrait Collection Mutable Map MutableMap +syn keyword rustTrait Set MutableSet +syn keyword rustTrait FromIterator Extendable ExactSize +syn keyword rustTrait Iterator DoubleEndedIterator +syn keyword rustTrait RandomAccessIterator CloneableIterator +syn keyword rustTrait OrdIterator MutableDoubleEndedIterator +syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv +syn keyword rustTrait Signed Unsigned Primitive Int Float +syn keyword rustTrait FloatMath ToPrimitive FromPrimitive syn keyword rustTrait Box syn keyword rustTrait GenericPath Path PosixPath WindowsPath syn keyword rustTrait RawPtr syn keyword rustTrait Buffer Writer Reader Seek -syn keyword rustTrait Str StrVector StrSlice OwnedStr IntoMaybeOwned -syn keyword rustTrait StrAllocating +syn keyword rustTrait Str StrVector StrSlice OwnedStr +syn keyword rustTrait IntoMaybeOwned StrAllocating syn keyword rustTrait ToStr IntoStr syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4 syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8 syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12 -syn keyword rustTrait CloneableVector ImmutableCloneableVector MutableCloneableVector +syn keyword rustTrait CloneableVector ImmutableCloneableVector +syn keyword rustTrait MutableCloneableVector MutableOrdVector syn keyword rustTrait ImmutableVector MutableVector -syn keyword rustTrait ImmutableEqVector ImmutableOrdVector MutableOrdVector -syn keyword rustTrait Vector VectorVector OwnedVector MutableVectorAllocating +syn keyword rustTrait ImmutableEqVector ImmutableOrdVector +syn keyword rustTrait Vector VectorVector +syn keyword rustTrait MutableVectorAllocating syn keyword rustTrait String syn keyword rustTrait Vec diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 6af4083edb2ce..38ed511c4589a 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -376,14 +376,14 @@ mod tests { #[test] fn test_live() { - let x = Arc::new(5); + let x = Arc::new(5i); let y = x.downgrade(); assert!(y.upgrade().is_some()); } #[test] fn test_dead() { - let x = Arc::new(5); + let x = Arc::new(5i); let y = x.downgrade(); drop(x); assert!(y.upgrade().is_none()); diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index b4d0057778a1a..dc8280e9b8361 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -99,7 +99,7 @@ pub static mut EMPTY: uint = 12345; #[inline] unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { if size == 0 { - &EMPTY as *uint as *mut u8 + &EMPTY as *const uint as *mut u8 } else { allocate(size, align) } @@ -144,9 +144,10 @@ mod imp { flags: c_int) -> size_t; fn je_dallocx(ptr: *mut c_void, flags: c_int); fn je_nallocx(size: size_t, flags: c_int) -> size_t; - fn je_malloc_stats_print(write_cb: Option, + fn je_malloc_stats_print(write_cb: Option, cbopaque: *mut c_void, - opts: *c_char); + opts: *const c_char); } // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough @@ -226,7 +227,7 @@ mod imp { // a block of memory, so we special case everything under `*uint` to // just pass it to malloc, which is guaranteed to align to at least the // size of `*uint`. - if align < mem::size_of::<*uint>() { + if align < mem::size_of::() { libc_heap::malloc_raw(size) } else { let mut out = 0 as *mut libc::c_void; @@ -244,7 +245,7 @@ mod imp { pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 { let new_ptr = allocate(size, align); - ptr::copy_memory(new_ptr, ptr as *u8, old_size); + ptr::copy_memory(new_ptr, ptr as *const u8, old_size); deallocate(ptr, old_size, align); return new_ptr; } @@ -328,7 +329,7 @@ mod bench { #[bench] fn alloc_owned_small(b: &mut Bencher) { b.iter(|| { - box 10 + box 10i }) } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 29293366e5008..26b8ccaf57371 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,7 +70,6 @@ #![no_std] #![feature(lang_items, phase, unsafe_destructor)] -#![allow(unknown_features)] // NOTE: remove after a stage0 snap #[phase(plugin, link)] extern crate core; diff --git a/src/liballoc/owned.rs b/src/liballoc/owned.rs index 6f5d329355623..addec396bbef8 100644 --- a/src/liballoc/owned.rs +++ b/src/liballoc/owned.rs @@ -16,7 +16,9 @@ use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; use core::default::Default; use core::fmt; use core::intrinsics; +use core::kinds::Send; use core::mem; +use core::option::Option; use core::raw::TraitObject; use core::result::{Ok, Err, Result}; @@ -36,7 +38,7 @@ pub static HEAP: () = (); /// A type that represents a uniquely-owned value. #[lang="owned_box"] -pub struct Box(*T); +pub struct Box(*mut T); impl Default for Box { fn default() -> Box { box Default::default() } @@ -63,6 +65,10 @@ impl PartialEq for Box { fn ne(&self, other: &Box) -> bool { *(*self) != *(*other) } } impl PartialOrd for Box { + #[inline] + fn partial_cmp(&self, other: &Box) -> Option { + (**self).partial_cmp(*other) + } #[inline] fn lt(&self, other: &Box) -> bool { *(*self) < *(*other) } #[inline] @@ -106,6 +112,34 @@ impl AnyOwnExt for Box { } } +/// Extension methods for an owning `Any+Send` trait object +pub trait AnySendOwnExt { + /// Returns the boxed value if it is of type `T`, or + /// `Err(Self)` if it isn't. + fn move_send(self) -> Result, Self>; +} + +impl AnySendOwnExt for Box { + #[inline] + fn move_send(self) -> Result, Box> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = + *mem::transmute::<&Box, &TraitObject>(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + Ok(mem::transmute(to.data)) + } + } else { + Err(self) + } + } +} + impl fmt::Show for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) @@ -117,3 +151,51 @@ impl fmt::Show for Box { f.pad("Box") } } + +#[cfg(test)] +mod test { + #[test] + fn test_owned_clone() { + let a = box 5i; + let b: Box = a.clone(); + assert!(a == b); + } + + #[test] + fn any_move() { + let a = box 8u as Box; + let b = box Test as Box; + + match a.move::() { + Ok(a) => { assert!(a == box 8u); } + Err(..) => fail!() + } + match b.move::() { + Ok(a) => { assert!(a == box Test); } + Err(..) => fail!() + } + + let a = box 8u as Box; + let b = box Test as Box; + + assert!(a.move::>().is_err()); + assert!(b.move::>().is_err()); + } + + #[test] + fn test_show() { + let a = box 8u as Box; + let b = box Test as Box; + let a_str = a.to_str(); + let b_str = b.to_str(); + assert_eq!(a_str.as_slice(), "Box"); + assert_eq!(b_str.as_slice(), "Box"); + + let a = &8u as &Any; + let b = &Test as &Any; + let s = format!("{}", a); + assert_eq!(s.as_slice(), "&Any"); + let s = format!("{}", b); + assert_eq!(s.as_slice(), "&Any"); + } +} diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a3ca72f1547ed..d97bce39c2de9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,16 +10,141 @@ /*! Task-local reference-counted boxes (`Rc` type) -The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and -will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the -overhead of atomic reference counting. +The `Rc` type provides shared ownership of an immutable value. Destruction is +deterministic, and will occur as soon as the last owner is gone. It is marked +as non-sendable because it avoids the overhead of atomic reference counting. -The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A `Weak` -pointer can be upgraded to an `Rc` pointer, but will return `None` if the value has already been -freed. +The `downgrade` method can be used to create a non-owning `Weak` pointer to the +box. A `Weak` pointer can be upgraded to an `Rc` pointer, but will return +`None` if the value has already been freed. -For example, a tree with parent pointers can be represented by putting the nodes behind `Strong` -pointers, and then storing the parent pointers as `Weak` pointers. +For example, a tree with parent pointers can be represented by putting the +nodes behind strong `Rc` pointers, and then storing the parent pointers as +`Weak` pointers. + + +## Examples + +Consider a scenario where a set of Gadgets are owned by a given Owner. We want +to have our Gadgets point to their Owner. We can't do this with unique +ownership, because more than one gadget may belong to the same Owner. Rc +allows us to share an Owner between multiple Gadgets, and have the Owner kept +alive as long as any Gadget points at it. + +```rust +use std::rc::Rc; + +struct Owner { + name: String + // ...other fields +} + +struct Gadget { + id: int, + owner: Rc + // ...other fields +} + +fn main() { + // Create a reference counted Owner. + let gadget_owner : Rc = Rc::new( + Owner { name: String::from_str("Gadget Man") } + ); + + // Create Gadgets belonging to gadget_owner. To increment the reference + // count we clone the Rc object. + let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() }; + let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() }; + + drop(gadget_owner); + + // Despite dropping gadget_owner, we're still able to print out the name of + // the Owner of the Gadgets. This is because we've only dropped the + // reference count object, not the Owner it wraps. As long as there are + // other Rc objects pointing at the same Owner, it will stay alive. Notice + // that the Rc wrapper around Gadget.owner gets automatically dereferenced + // for us. + println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); + println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); + + // At the end of the method, gadget1 and gadget2 get destroyed, and with + // them the last counted references to our Owner. Gadget Man now gets + // destroyed as well. +} +``` + +If our requirements change, and we also need to be able to traverse from +Owner->Gadget, we will run into problems: an Rc pointer from Owner->Gadget +introduces a cycle between the objects. This means that their reference counts +can never reach 0, and the objects will stay alive: a memory leak. In order to +get around this, we can use `Weak` pointers. These are reference counted +pointers that don't keep an object alive if there are no normal `Rc` (or +*strong*) pointers left. + +Rust actually makes it somewhat difficult to produce this loop in the first +place: in order to end up with two objects that point at each other, one of +them needs to be mutable. This is problematic because Rc enforces memory +safety by only giving out shared references to the object it wraps, and these +don't allow direct mutation. We need to wrap the part of the object we wish to +mutate in a `RefCell`, which provides *interior mutability*: a method to +achieve mutability through a shared reference. `RefCell` enforces Rust's +borrowing rules at runtime. Read the `Cell` documentation for more details on +interior mutability. + +```rust +use std::rc::Rc; +use std::rc::Weak; +use std::cell::RefCell; + +struct Owner { + name: String, + gadgets: RefCell>> + // ...other fields +} + +struct Gadget { + id: int, + owner: Rc + // ...other fields +} + +fn main() { + // Create a reference counted Owner. Note the fact that we've put the + // Owner's vector of Gadgets inside a RefCell so that we can mutate it + // through a shared reference. + let gadget_owner : Rc = Rc::new( + Owner { + name: "Gadget Man".to_string(), + gadgets: RefCell::new(Vec::new()) + } + ); + + // Create Gadgets belonging to gadget_owner as before. + let gadget1 = Rc::new(Gadget{id: 1, owner: gadget_owner.clone()}); + let gadget2 = Rc::new(Gadget{id: 2, owner: gadget_owner.clone()}); + + // Add the Gadgets to their Owner. To do this we mutably borrow from + // the RefCell holding the Owner's Gadgets. + gadget_owner.gadgets.borrow_mut().push(gadget1.clone().downgrade()); + gadget_owner.gadgets.borrow_mut().push(gadget2.clone().downgrade()); + + // Iterate over our Gadgets, printing their details out + for gadget_opt in gadget_owner.gadgets.borrow().iter() { + + // gadget_opt is a Weak. Since weak pointers can't guarantee + // that their object is still alive, we need to call upgrade() on them + // to turn them into a strong reference. This returns an Option, which + // contains a reference to our object if it still exists. + let gadget = gadget_opt.upgrade().unwrap(); + println!("Gadget {} owned by {}", gadget.id, gadget.owner.name); + } + + // At the end of the method, gadget_owner, gadget1 and gadget2 get + // destroyed. There are now no strong (Rc) references to the gadgets. + // Once they get destroyed, the Gadgets get destroyed. This zeroes the + // reference count on Gadget Man, so he gets destroyed as well. +} +``` */ @@ -27,6 +152,7 @@ use core::mem::transmute; use core::cell::Cell; use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; +use core::default::Default; use core::kinds::marker; use core::ops::{Deref, Drop}; use core::option::{Option, Some, None}; @@ -152,6 +278,13 @@ impl Clone for Rc { } } +impl Default for Rc { + #[inline] + fn default() -> Rc { + Rc::new(Default::default()) + } +} + impl PartialEq for Rc { #[inline(always)] fn eq(&self, other: &Rc) -> bool { **self == **other } @@ -162,6 +295,11 @@ impl PartialEq for Rc { impl Eq for Rc {} impl PartialOrd for Rc { + #[inline(always)] + fn partial_cmp(&self, other: &Rc) -> Option { + (**self).partial_cmp(&**other) + } + #[inline(always)] fn lt(&self, other: &Rc) -> bool { **self < **other } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index f7c4831b5bf94..917de94470b35 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -55,7 +55,7 @@ impl Chunk { self.data.borrow().capacity() } - unsafe fn as_ptr(&self) -> *u8 { + unsafe fn as_ptr(&self) -> *const u8 { self.data.borrow().as_ptr() } } @@ -140,22 +140,22 @@ unsafe fn destroy_chunk(chunk: &Chunk) { let fill = chunk.fill.get(); while idx < fill { - let tydesc_data: *uint = mem::transmute(buf.offset(idx as int)); + let tydesc_data: *const uint = mem::transmute(buf.offset(idx as int)); let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data); let (size, align) = ((*tydesc).size, (*tydesc).align); - let after_tydesc = idx + mem::size_of::<*TyDesc>(); + let after_tydesc = idx + mem::size_of::<*const TyDesc>(); let start = round_up(after_tydesc, align); //debug!("freeing object: idx = {}, size = {}, align = {}, done = {}", // start, size, align, is_done); if is_done { - ((*tydesc).drop_glue)(buf.offset(start as int) as *i8); + ((*tydesc).drop_glue)(buf.offset(start as int) as *const i8); } // Find where the next tydesc lives - idx = round_up(start + size, mem::align_of::<*TyDesc>()); + idx = round_up(start + size, mem::align_of::<*const TyDesc>()); } } @@ -164,12 +164,12 @@ unsafe fn destroy_chunk(chunk: &Chunk) { // is necessary in order to properly do cleanup if a failure occurs // during an initializer. #[inline] -fn bitpack_tydesc_ptr(p: *TyDesc, is_done: bool) -> uint { +fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> uint { p as uint | (is_done as uint) } #[inline] -fn un_bitpack_tydesc_ptr(p: uint) -> (*TyDesc, bool) { - ((p & !1) as *TyDesc, p & 1 == 1) +fn un_bitpack_tydesc_ptr(p: uint) -> (*const TyDesc, bool) { + ((p & !1) as *const TyDesc, p & 1 == 1) } impl Arena { @@ -178,7 +178,7 @@ impl Arena { } // Functions for the POD part of the arena - fn alloc_copy_grow(&self, n_bytes: uint, align: uint) -> *u8 { + fn alloc_copy_grow(&self, n_bytes: uint, align: uint) -> *const u8 { // Allocate a new chunk. let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size()); self.chunks.borrow_mut().push(self.copy_head.borrow().clone()); @@ -190,7 +190,7 @@ impl Arena { } #[inline] - fn alloc_copy_inner(&self, n_bytes: uint, align: uint) -> *u8 { + fn alloc_copy_inner(&self, n_bytes: uint, align: uint) -> *const u8 { let start = round_up(self.copy_head.borrow().fill.get(), align); let end = start + n_bytes; @@ -218,7 +218,8 @@ impl Arena { } // Functions for the non-POD part of the arena - fn alloc_noncopy_grow(&self, n_bytes: uint, align: uint) -> (*u8, *u8) { + fn alloc_noncopy_grow(&self, n_bytes: uint, + align: uint) -> (*const u8, *const u8) { // Allocate a new chunk. let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size()); self.chunks.borrow_mut().push(self.head.borrow().clone()); @@ -230,7 +231,8 @@ impl Arena { } #[inline] - fn alloc_noncopy_inner(&self, n_bytes: uint, align: uint) -> (*u8, *u8) { + fn alloc_noncopy_inner(&self, n_bytes: uint, + align: uint) -> (*const u8, *const u8) { // Be careful to not maintain any `head` borrows active, because // `alloc_noncopy_grow` borrows it mutably. let (start, end, tydesc_start, head_capacity) = { @@ -238,7 +240,7 @@ impl Arena { let fill = head.fill.get(); let tydesc_start = fill; - let after_tydesc = fill + mem::size_of::<*TyDesc>(); + let after_tydesc = fill + mem::size_of::<*const TyDesc>(); let start = round_up(after_tydesc, align); let end = start + n_bytes; @@ -250,7 +252,7 @@ impl Arena { } let head = self.head.borrow(); - head.fill.set(round_up(end, mem::align_of::<*TyDesc>())); + head.fill.set(round_up(end, mem::align_of::<*const TyDesc>())); unsafe { let buf = head.as_ptr(); @@ -348,11 +350,11 @@ fn test_arena_destructors_fail() { /// run again for these objects. pub struct TypedArena { /// A pointer to the next object to be allocated. - ptr: Cell<*T>, + ptr: Cell<*const T>, /// A pointer to the end of the allocated area. When this pointer is /// reached, a new chunk is allocated. - end: Cell<*T>, + end: Cell<*const T>, /// A pointer to the first arena segment. first: RefCell>, @@ -398,7 +400,7 @@ impl TypedArenaChunk { if intrinsics::needs_drop::() { let mut start = self.start(); for _ in range(0, len) { - ptr::read(start as *T); // run the destructor on the pointer + ptr::read(start as *const T); // run the destructor on the pointer start = start.offset(mem::size_of::() as int) } } @@ -417,8 +419,8 @@ impl TypedArenaChunk { // Returns a pointer to the first allocated object. #[inline] - fn start(&self) -> *u8 { - let this: *TypedArenaChunk = self; + fn start(&self) -> *const u8 { + let this: *const TypedArenaChunk = self; unsafe { mem::transmute(round_up(this.offset(1) as uint, mem::min_align_of::())) @@ -427,7 +429,7 @@ impl TypedArenaChunk { // Returns a pointer to the end of the allocated space. #[inline] - fn end(&self) -> *u8 { + fn end(&self) -> *const u8 { unsafe { let size = mem::size_of::().checked_mul(&self.capacity).unwrap(); self.start().offset(size as int) @@ -448,8 +450,8 @@ impl TypedArena { pub fn with_capacity(capacity: uint) -> TypedArena { let chunk = TypedArenaChunk::::new(None, capacity); TypedArena { - ptr: Cell::new(chunk.start() as *T), - end: Cell::new(chunk.end() as *T), + ptr: Cell::new(chunk.start() as *const T), + end: Cell::new(chunk.end() as *const T), first: RefCell::new(Some(chunk)), } } @@ -477,8 +479,8 @@ impl TypedArena { let chunk = self.first.borrow_mut().take_unwrap(); let new_capacity = chunk.capacity.checked_mul(&2).unwrap(); let chunk = TypedArenaChunk::::new(Some(chunk), new_capacity); - self.ptr.set(chunk.start() as *T); - self.end.set(chunk.end() as *T); + self.ptr.set(chunk.start() as *const T); + self.end.set(chunk.end() as *const T); *self.first.borrow_mut() = Some(chunk) } } diff --git a/src/libcollections/btree.rs b/src/libcollections/btree.rs index 64bee05a379a7..92abfaad34833 100644 --- a/src/libcollections/btree.rs +++ b/src/libcollections/btree.rs @@ -107,8 +107,8 @@ impl PartialEq for BTree { impl Eq for BTree {} impl PartialOrd for BTree { - fn lt(&self, other: &BTree) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &BTree) -> Option { + Some(self.cmp(other)) } } @@ -229,8 +229,8 @@ impl PartialEq for Node { impl Eq for Node {} impl PartialOrd for Node { - fn lt(&self, other: &Node) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &Node) -> Option { + Some(self.cmp(other)) } } @@ -408,8 +408,8 @@ impl PartialEq for Leaf { impl Eq for Leaf {} impl PartialOrd for Leaf { - fn lt(&self, other: &Leaf) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &Leaf) -> Option { + Some(self.cmp(other)) } } @@ -638,8 +638,8 @@ impl PartialEq for Branch { impl Eq for Branch {} impl PartialOrd for Branch { - fn lt(&self, other: &Branch) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &Branch) -> Option { + Some(self.cmp(other)) } } @@ -706,8 +706,8 @@ impl PartialEq for LeafElt { impl Eq for LeafElt {} impl PartialOrd for LeafElt { - fn lt(&self, other: &LeafElt) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &LeafElt) -> Option { + Some(self.cmp(other)) } } @@ -755,8 +755,8 @@ impl PartialEq for BranchElt{ impl Eq for BranchElt{} impl PartialOrd for BranchElt { - fn lt(&self, other: &BranchElt) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &BranchElt) -> Option { + Some(self.cmp(other)) } } diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 0ae0f9068931d..4114c8cb1c4dd 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -595,17 +595,8 @@ impl PartialEq for DList { } impl PartialOrd for DList { - fn lt(&self, other: &DList) -> bool { - iter::order::lt(self.iter(), other.iter()) - } - fn le(&self, other: &DList) -> bool { - iter::order::le(self.iter(), other.iter()) - } - fn gt(&self, other: &DList) -> bool { - iter::order::gt(self.iter(), other.iter()) - } - fn ge(&self, other: &DList) -> bool { - iter::order::ge(self.iter(), other.iter()) + fn partial_cmp(&self, other: &DList) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) } } @@ -652,7 +643,7 @@ mod tests { (None , None ) => {} (None , _ ) => fail!("prev link for list_head"), (Some(p), Some(pptr)) => { - assert_eq!(p as *Node, pptr as *Node); + assert_eq!(p as *const Node, pptr as *const Node); } _ => fail!("prev link is none, not good"), } diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index a0c0c9f973578..e3d1c9a3216bc 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -247,7 +247,7 @@ impl> Hash for Option { } } -impl Hash for *T { +impl Hash for *const T { #[inline] fn hash(&self, state: &mut S) { // NB: raw-pointer Hash does _not_ dereference @@ -342,12 +342,12 @@ mod tests { assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9); unsafe { - let ptr: *int = mem::transmute(5); + let ptr: *const int = mem::transmute(5i); assert_eq!(hasher.hash(&ptr), 5); } unsafe { - let ptr: *mut int = mem::transmute(5); + let ptr: *mut int = mem::transmute(5i); assert_eq!(hasher.hash(&ptr), 5); } } diff --git a/src/libcollections/hash/sip.rs b/src/libcollections/hash/sip.rs index 887b0fb0b8abe..4fd98538af7dd 100644 --- a/src/libcollections/hash/sip.rs +++ b/src/libcollections/hash/sip.rs @@ -265,8 +265,6 @@ pub fn hash_with_keys>(k0: u64, k1: u64, value: &T) -> u64 { state.result() } - - #[cfg(test)] mod tests { use test::Bencher; diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index be0d603696bec..5e19accdd6715 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -572,7 +572,7 @@ mod tests { fn bench_push_back(b: &mut test::Bencher) { let mut deq = RingBuf::new(); b.iter(|| { - deq.push_back(0); + deq.push_back(0i); }) } @@ -580,7 +580,7 @@ mod tests { fn bench_push_front(b: &mut test::Bencher) { let mut deq = RingBuf::new(); b.iter(|| { - deq.push_front(0); + deq.push_front(0i); }) } @@ -589,7 +589,7 @@ mod tests { let mut deq = RingBuf::new(); b.iter(|| { for _ in range(0i, 65) { - deq.push_front(1); + deq.push_front(1i); } }) } @@ -651,10 +651,10 @@ mod tests { #[test] fn test_with_capacity() { let mut d = RingBuf::with_capacity(0); - d.push_back(1); + d.push_back(1i); assert_eq!(d.len(), 1); let mut d = RingBuf::with_capacity(50); - d.push_back(1); + d.push_back(1i); assert_eq!(d.len(), 1); } diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ac8ac6102f323..40cf8495a4059 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -17,7 +17,7 @@ Vectors are Rust's list type. Vectors contain zero or more values of homogeneous types: ```rust -let int_vector = [1,2,3]; +let int_vector = [1i, 2i, 3i]; let str_vector = ["one", "two", "three"]; ``` @@ -41,9 +41,9 @@ An example is the method `.slice(a, b)` that returns an immutable "view" into a vector or a vector slice from the index interval `[a, b)`: ```rust -let numbers = [0, 1, 2]; +let numbers = [0i, 1i, 2i]; let last_numbers = numbers.slice(1, 3); -// last_numbers is now &[1, 2] +// last_numbers is now &[1i, 2i] ``` Traits defined for the `~[T]` type, like `OwnedVector`, can only be called @@ -54,9 +54,9 @@ An example is the method `.push(element)` that will add an element at the end of the vector: ```rust -let mut numbers = vec![0, 1, 2]; +let mut numbers = vec![0i, 1i, 2i]; numbers.push(7); -// numbers is now vec![0, 1, 2, 7]; +// numbers is now vec![0i, 1i, 2i, 7i]; ``` ## Implementations of other traits @@ -341,7 +341,7 @@ fn insertion_sort(v: &mut [T], compare: |&T, &T| -> Ordering) { let mut j = i; unsafe { // `i` is in bounds. - let read_ptr = buf_v.offset(i) as *T; + let read_ptr = buf_v.offset(i) as *const T; // find where to insert, we need to do strict <, // rather than <=, to maintain stability. @@ -365,7 +365,7 @@ fn insertion_sort(v: &mut [T], compare: |&T, &T| -> Ordering) { &*buf_v.offset(j), (i - j) as uint); ptr::copy_nonoverlapping_memory(buf_v.offset(j), - &tmp as *T, + &tmp as *const T, 1); mem::forget(tmp); } @@ -779,7 +779,7 @@ mod tests { fn test_is_empty() { let xs: [int, ..0] = []; assert!(xs.is_empty()); - assert!(![0].is_empty()); + assert!(![0i].is_empty()); } #[test] @@ -1528,7 +1528,7 @@ mod tests { fn test_permute_fail() { let v = [(box 0i, Rc::new(0i)), (box 0i, Rc::new(0i)), (box 0i, Rc::new(0i)), (box 0i, Rc::new(0i))]; - let mut i = 0; + let mut i = 0u; for _ in v.permutations() { if i == 2 { fail!() @@ -1870,16 +1870,16 @@ mod tests { fn test_overflow_does_not_cause_segfault() { let mut v = vec![]; v.reserve_exact(-1); - v.push(1); + v.push(1i); v.push(2); } #[test] #[should_fail] fn test_overflow_does_not_cause_segfault_managed() { - let mut v = vec![Rc::new(1)]; + let mut v = vec![Rc::new(1i)]; v.reserve_exact(-1); - v.push(Rc::new(2)); + v.push(Rc::new(2i)); } #[test] @@ -2279,7 +2279,7 @@ mod bench { v.set_len(1024); } for x in v.mut_iter() { - *x = 0; + *x = 0i; } v }); diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 642e7cfc9a36f..fd8ce11d0b5a4 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -97,6 +97,15 @@ Section: Creating a string /// /// Returns `Err` with the original vector if the vector contains invalid /// UTF-8. +/// +/// # Example +/// +/// ```rust +/// use std::str; +/// let hello_vec = vec![104, 101, 108, 108, 111]; +/// let string = str::from_utf8_owned(hello_vec); +/// assert_eq!(string, Ok("hello".to_string())); +/// ``` pub fn from_utf8_owned(vv: Vec) -> Result> { String::from_utf8(vv) } @@ -106,12 +115,28 @@ pub fn from_utf8_owned(vv: Vec) -> Result> { /// # Failure /// /// Fails if invalid UTF-8 +/// +/// # Example +/// +/// ```rust +/// use std::str; +/// let string = str::from_byte(104); +/// assert_eq!(string.as_slice(), "h"); +/// ``` pub fn from_byte(b: u8) -> String { assert!(b < 128u8); String::from_char(1, b as char) } /// Convert a char to a string +/// +/// # Example +/// +/// ```rust +/// use std::str; +/// let string = str::from_char('b'); +/// assert_eq!(string.as_slice(), "b"); +/// ``` pub fn from_char(ch: char) -> String { let mut buf = String::new(); buf.push_char(ch); @@ -119,6 +144,15 @@ pub fn from_char(ch: char) -> String { } /// Convert a vector of chars to a string +/// +/// # Example +/// +/// ```rust +/// use std::str; +/// let chars = ['h', 'e', 'l', 'l', 'o']; +/// let string = str::from_chars(chars); +/// assert_eq!(string.as_slice(), "hello"); +/// ``` pub fn from_chars(chs: &[char]) -> String { chs.iter().map(|c| *c).collect() } @@ -572,8 +606,8 @@ impl<'a> Eq for MaybeOwned<'a> {} impl<'a> PartialOrd for MaybeOwned<'a> { #[inline] - fn lt(&self, other: &MaybeOwned) -> bool { - self.as_slice().lt(&other.as_slice()) + fn partial_cmp(&self, other: &MaybeOwned) -> Option { + Some(self.cmp(other)) } } @@ -661,7 +695,7 @@ pub mod raw { pub use core::str::raw::{slice_unchecked}; /// Create a Rust string from a *u8 buffer of the given length - pub unsafe fn from_buf_len(buf: *u8, len: uint) -> String { + pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> String { let mut result = String::new(); result.push_bytes(mem::transmute(Slice { data: buf, @@ -671,7 +705,7 @@ pub mod raw { } /// Create a Rust string from a null-terminated C string - pub unsafe fn from_c_str(c_string: *i8) -> String { + pub unsafe fn from_c_str(c_string: *const i8) -> String { let mut buf = String::new(); let mut len = 0; while *c_string.offset(len) != 0 { @@ -803,15 +837,9 @@ pub trait StrAllocating: Str { } /// Converts to a vector of `u16` encoded as UTF-16. + #[deprecated = "use `utf16_units` instead"] fn to_utf16(&self) -> Vec { - let me = self.as_slice(); - let mut u = Vec::new(); - for ch in me.chars() { - let mut buf = [0u16, ..2]; - let n = ch.encode_utf16(buf /* as mut slice! */); - u.push_all(buf.slice_to(n)); - } - u + self.as_slice().utf16_units().collect::>() } /// Given a string, make a new string with repeated copies of it. @@ -1103,7 +1131,7 @@ mod tests { assert_eq!("bc", unsafe {raw::slice_bytes("abc", 1, 3)}); assert_eq!("", unsafe {raw::slice_bytes("abc", 1, 1)}); fn a_million_letter_a() -> String { - let mut i = 0; + let mut i = 0u; let mut rs = String::new(); while i < 100000 { rs.push_str("aaaaaaaaaa"); @@ -1112,7 +1140,7 @@ mod tests { rs } fn half_a_million_letter_a() -> String { - let mut i = 0; + let mut i = 0u; let mut rs = String::new(); while i < 100000 { rs.push_str("aaaaa"); @@ -1220,7 +1248,7 @@ mod tests { assert_eq!("华", data.slice(30, 33)); fn a_million_letter_x() -> String { - let mut i = 0; + let mut i = 0u; let mut rs = String::new(); while i < 100000 { rs.push_str("华华华华华华华华华华"); @@ -1229,7 +1257,7 @@ mod tests { rs } fn half_a_million_letter_x() -> String { - let mut i = 0; + let mut i = 0u; let mut rs = String::new(); while i < 100000 { rs.push_str("华华华华华"); @@ -1541,8 +1569,8 @@ mod tests { let n2: uint = v.len(); assert_eq!(n1, n2); while i < n1 { - let a: u8 = s1.as_slice()[i]; - let b: u8 = s2.as_slice()[i]; + let a: u8 = s1.as_bytes()[i]; + let b: u8 = s2.as_bytes()[i]; debug!("{}", a); debug!("{}", b); assert_eq!(a, b); @@ -1619,14 +1647,17 @@ mod tests { for p in pairs.iter() { let (s, u) = (*p).clone(); + let s_as_utf16 = s.as_slice().utf16_units().collect::>(); + let u_as_string = from_utf16(u.as_slice()).unwrap(); + assert!(is_utf16(u.as_slice())); - assert_eq!(s.to_utf16(), u); + assert_eq!(s_as_utf16, u); - assert_eq!(from_utf16(u.as_slice()).unwrap(), s); + assert_eq!(u_as_string, s); assert_eq!(from_utf16_lossy(u.as_slice()), s); - assert_eq!(from_utf16(s.to_utf16().as_slice()).unwrap(), s); - assert_eq!(from_utf16(u.as_slice()).unwrap().to_utf16(), u); + assert_eq!(from_utf16(s_as_utf16.as_slice()).unwrap(), s); + assert_eq!(u_as_string.as_slice().utf16_units().collect::>(), u); } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 6d1fc43a4f1fd..936e60388a66a 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -222,7 +222,7 @@ impl String { return None } - let byte = self.as_slice()[len - 1]; + let byte = self.as_bytes()[len - 1]; self.vec.set_len(len - 1); Some(byte) } diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 78770b6db8d05..becceffe6d027 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -56,23 +56,11 @@ impl PartialEq for TreeMap { } } -// Lexicographical comparison -fn lt(a: &TreeMap, - b: &TreeMap) -> bool { - // the Zip iterator is as long as the shortest of a and b. - for ((key_a, value_a), (key_b, value_b)) in a.iter().zip(b.iter()) { - if *key_a < *key_b { return true; } - if *key_a > *key_b { return false; } - if *value_a < *value_b { return true; } - if *value_a > *value_b { return false; } - } - - a.len() < b.len() -} - -impl PartialOrd for TreeMap { +impl PartialOrd for TreeMap { #[inline] - fn lt(&self, other: &TreeMap) -> bool { lt(self, other) } + fn partial_cmp(&self, other: &TreeMap) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } } impl Show for TreeMap { @@ -287,7 +275,7 @@ pub struct Entries<'a, K, V> { // See the comment on MutEntries; this is just to allow // code-sharing (for this immutable-values iterator it *could* very // well be Option<&'a TreeNode>). - node: *TreeNode, + node: *const TreeNode, remaining_min: uint, remaining_max: uint } @@ -468,11 +456,11 @@ define_iterator! { addr_mut = mut } -fn deref<'a, K, V>(node: &'a Option>>) -> *TreeNode { +fn deref<'a, K, V>(node: &'a Option>>) -> *const TreeNode { match *node { Some(ref n) => { let n: &TreeNode = *n; - n as *TreeNode + n as *const TreeNode } None => ptr::null() } @@ -568,9 +556,11 @@ impl PartialEq for TreeSet { fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } } -impl PartialOrd for TreeSet { +impl PartialOrd for TreeSet { #[inline] - fn lt(&self, other: &TreeSet) -> bool { self.map < other.map } + fn partial_cmp(&self, other: &TreeSet) -> Option { + self.map.partial_cmp(&other.map) + } } impl Show for TreeSet { diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 350c284e1d3b4..9b6355e121bea 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -189,7 +189,9 @@ macro_rules! bound { // We like sharing code so much that even a little unsafe won't // stop us. let this = $this; - let mut node = addr!(& $($mut_)* this.root as * $($mut_)* TrieNode); + let mut node = unsafe { + mem::transmute::<_, uint>(&this.root) as *mut TrieNode + }; let key = $key; @@ -205,7 +207,10 @@ macro_rules! bound { let child_id = chunk(key, it.length); let (slice_idx, ret) = match children[child_id] { Internal(ref $($mut_)* n) => { - node = addr!(& $($mut_)* **n as * $($mut_)* TrieNode); + node = unsafe { + mem::transmute::<_, uint>(&**n) + as *mut TrieNode + }; (child_id + 1, false) } External(stored, _) => { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 0ee0c5b87aeaa..2ffc168f82c0e 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -389,8 +389,8 @@ impl PartialEq for Vec { impl PartialOrd for Vec { #[inline] - fn lt(&self, other: &Vec) -> bool { - self.as_slice() < other.as_slice() + fn partial_cmp(&self, other: &Vec) -> Option { + self.as_slice().partial_cmp(&other.as_slice()) } } @@ -615,7 +615,7 @@ impl Vec { } unsafe { - let end = (self.ptr as *T).offset(self.len as int) as *mut T; + let end = (self.ptr as *const T).offset(self.len as int) as *mut T; ptr::write(&mut *end, value); self.len += 1; } @@ -674,7 +674,10 @@ impl Vec { #[inline] pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { unsafe { - mem::transmute(Slice { data: self.as_mut_ptr() as *T, len: self.len }) + mem::transmute(Slice { + data: self.as_mut_ptr() as *const T, + len: self.len, + }) } } @@ -956,7 +959,8 @@ impl Vec { /// /// # Failure /// - /// Fails if `index` is out of bounds of the vector. + /// Fails if `index` is not between `0` and the vector's length (both + /// bounds inclusive). /// /// # Example /// @@ -964,6 +968,8 @@ impl Vec { /// let mut vec = vec!(1i, 2, 3); /// vec.insert(1, 4); /// assert_eq!(vec, vec!(1, 4, 2, 3)); + /// vec.insert(4, 5); + /// assert_eq!(vec, vec!(1, 4, 2, 3, 5)); /// ``` pub fn insert(&mut self, index: uint, element: T) { let len = self.len(); @@ -1011,7 +1017,7 @@ impl Vec { let ptr = self.as_mut_ptr().offset(index as int); // copy it out, unsafely having a copy of the value on // the stack and in the vector at the same time. - ret = Some(ptr::read(ptr as *T)); + ret = Some(ptr::read(ptr as *const T)); // Shift everything down to fill in that spot. ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1); @@ -1200,15 +1206,15 @@ impl Vec { /// Modifying the vector may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. #[inline] - pub fn as_ptr(&self) -> *T { + pub fn as_ptr(&self) -> *const T { // If we have a 0-sized vector, then the base pointer should not be NULL // because an iterator over the slice will attempt to yield the base // pointer as the first element in the vector, but this will end up // being Some(NULL) which is optimized to None. if mem::size_of::() == 0 { - 1 as *T + 1 as *const T } else { - self.ptr as *T + self.ptr as *const T } } @@ -1542,7 +1548,7 @@ pub mod raw { /// The elements of the buffer are copied into the vector without cloning, /// as if `ptr::read()` were called on them. #[inline] - pub unsafe fn from_buf(ptr: *T, elts: uint) -> Vec { + pub unsafe fn from_buf(ptr: *const T, elts: uint) -> Vec { let mut dst = Vec::with_capacity(elts); dst.set_len(elts); ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts); diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 4a35dde08eb5c..8021fa50d8f46 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -115,179 +115,3 @@ impl<'a> AnyMutRefExt<'a> for &'a mut Any { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - use super::*; - use realstd::owned::{Box, AnyOwnExt}; - use realstd::str::Str; - - #[deriving(PartialEq, Show)] - struct Test; - - static TEST: &'static str = "Test"; - - #[test] - fn any_referenced() { - let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any); - - assert!(a.is::()); - assert!(!b.is::()); - assert!(!c.is::()); - - assert!(!a.is::<&'static str>()); - assert!(b.is::<&'static str>()); - assert!(!c.is::<&'static str>()); - - assert!(!a.is::()); - assert!(!b.is::()); - assert!(c.is::()); - } - - #[test] - fn any_owning() { - let (a, b, c) = (box 5u as Box, box TEST as Box, box Test as Box); - - assert!(a.is::()); - assert!(!b.is::()); - assert!(!c.is::()); - - assert!(!a.is::<&'static str>()); - assert!(b.is::<&'static str>()); - assert!(!c.is::<&'static str>()); - - assert!(!a.is::()); - assert!(!b.is::()); - assert!(c.is::()); - } - - #[test] - fn any_as_ref() { - let a = &5u as &Any; - - match a.as_ref::() { - Some(&5) => {} - x => fail!("Unexpected value {}", x) - } - - match a.as_ref::() { - None => {} - x => fail!("Unexpected value {}", x) - } - } - - #[test] - fn any_as_mut() { - let mut a = 5u; - let mut b = box 7u; - - let a_r = &mut a as &mut Any; - let tmp: &mut uint = &mut *b; - let b_r = tmp as &mut Any; - - match a_r.as_mut::() { - Some(x) => { - assert_eq!(*x, 5u); - *x = 612; - } - x => fail!("Unexpected value {}", x) - } - - match b_r.as_mut::() { - Some(x) => { - assert_eq!(*x, 7u); - *x = 413; - } - x => fail!("Unexpected value {}", x) - } - - match a_r.as_mut::() { - None => (), - x => fail!("Unexpected value {}", x) - } - - match b_r.as_mut::() { - None => (), - x => fail!("Unexpected value {}", x) - } - - match a_r.as_mut::() { - Some(&612) => {} - x => fail!("Unexpected value {}", x) - } - - match b_r.as_mut::() { - Some(&413) => {} - x => fail!("Unexpected value {}", x) - } - } - - #[test] - fn any_move() { - use realstd::any::Any; - use realstd::result::{Ok, Err}; - let a = box 8u as Box; - let b = box Test as Box; - - match a.move::() { - Ok(a) => { assert!(a == box 8u); } - Err(..) => fail!() - } - match b.move::() { - Ok(a) => { assert!(a == box Test); } - Err(..) => fail!() - } - - let a = box 8u as Box; - let b = box Test as Box; - - assert!(a.move::>().is_err()); - assert!(b.move::>().is_err()); - } - - #[test] - fn test_show() { - use realstd::to_str::ToStr; - let a = box 8u as Box<::realstd::any::Any>; - let b = box Test as Box<::realstd::any::Any>; - let a_str = a.to_str(); - let b_str = b.to_str(); - assert_eq!(a_str.as_slice(), "Box"); - assert_eq!(b_str.as_slice(), "Box"); - - let a = &8u as &Any; - let b = &Test as &Any; - let s = format!("{}", a); - assert_eq!(s.as_slice(), "&Any"); - let s = format!("{}", b); - assert_eq!(s.as_slice(), "&Any"); - } - - #[test] - fn any_fixed_vec() { - let test = [0u, ..8]; - let test = &test as &Any; - assert!(test.is::<[uint, ..8]>()); - assert!(!test.is::<[uint, ..10]>()); - } -} - -#[cfg(test)] -mod bench { - extern crate test; - - use any::{Any, AnyRefExt}; - use option::Some; - use self::test::Bencher; - - #[bench] - fn bench_as_ref(b: &mut Bencher) { - b.iter(|| { - let mut x = 0i; - let mut y = &mut x as &mut Any; - test::black_box(&mut y); - test::black_box(y.as_ref::() == Some(&0)); - }); - } -} diff --git a/src/libcore/atomics.rs b/src/libcore/atomics.rs index 65ba11f89adc6..971799acc7862 100644 --- a/src/libcore/atomics.rs +++ b/src/libcore/atomics.rs @@ -94,7 +94,7 @@ impl AtomicBool { /// Load the value #[inline] pub fn load(&self, order: Ordering) -> bool { - unsafe { atomic_load(self.v.get() as *uint, order) > 0 } + unsafe { atomic_load(self.v.get() as *const uint, order) > 0 } } /// Store the value @@ -295,7 +295,7 @@ impl AtomicInt { /// Load the value #[inline] pub fn load(&self, order: Ordering) -> int { - unsafe { atomic_load(self.v.get() as *int, order) } + unsafe { atomic_load(self.v.get() as *const int, order) } } /// Store the value @@ -407,7 +407,7 @@ impl AtomicUint { /// Load the value #[inline] pub fn load(&self, order: Ordering) -> uint { - unsafe { atomic_load(self.v.get() as *uint, order) } + unsafe { atomic_load(self.v.get() as *const uint, order) } } /// Store the value @@ -520,7 +520,7 @@ impl AtomicPtr { #[inline] pub fn load(&self, order: Ordering) -> *mut T { unsafe { - atomic_load(self.p.get() as **mut T, order) as *mut T + atomic_load(self.p.get() as *const *mut T, order) as *mut T } } @@ -560,7 +560,7 @@ unsafe fn atomic_store(dst: *mut T, val: T, order:Ordering) { } #[inline] -unsafe fn atomic_load(dst: *T, order:Ordering) -> T { +unsafe fn atomic_load(dst: *const T, order:Ordering) -> T { match order { Acquire => intrinsics::atomic_load_acq(dst), Relaxed => intrinsics::atomic_load_relaxed(dst), @@ -693,97 +693,3 @@ pub fn fence(order: Ordering) { } } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn bool_() { - let a = AtomicBool::new(false); - assert_eq!(a.compare_and_swap(false, true, SeqCst), false); - assert_eq!(a.compare_and_swap(false, true, SeqCst), true); - - a.store(false, SeqCst); - assert_eq!(a.compare_and_swap(false, true, SeqCst), false); - } - - #[test] - fn bool_and() { - let a = AtomicBool::new(true); - assert_eq!(a.fetch_and(false, SeqCst),true); - assert_eq!(a.load(SeqCst),false); - } - - #[test] - fn uint_and() { - let x = AtomicUint::new(0xf731); - assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731); - assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); - } - - #[test] - fn uint_or() { - let x = AtomicUint::new(0xf731); - assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731); - assert_eq!(x.load(SeqCst), 0xf731 | 0x137f); - } - - #[test] - fn uint_xor() { - let x = AtomicUint::new(0xf731); - assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731); - assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); - } - - #[test] - fn int_and() { - let x = AtomicInt::new(0xf731); - assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731); - assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); - } - - #[test] - fn int_or() { - let x = AtomicInt::new(0xf731); - assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731); - assert_eq!(x.load(SeqCst), 0xf731 | 0x137f); - } - - #[test] - fn int_xor() { - let x = AtomicInt::new(0xf731); - assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731); - assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); - } - - static mut S_BOOL : AtomicBool = INIT_ATOMIC_BOOL; - static mut S_INT : AtomicInt = INIT_ATOMIC_INT; - static mut S_UINT : AtomicUint = INIT_ATOMIC_UINT; - - #[test] - fn static_init() { - unsafe { - assert!(!S_BOOL.load(SeqCst)); - assert!(S_INT.load(SeqCst) == 0); - assert!(S_UINT.load(SeqCst) == 0); - } - } - - #[test] - fn different_sizes() { - unsafe { - let mut slot = 0u16; - assert_eq!(super::atomic_swap(&mut slot, 1, SeqCst), 0); - - let mut slot = 0u8; - assert_eq!(super::atomic_compare_and_swap(&mut slot, 1, 2, SeqCst), 0); - - let slot = 0u32; - assert_eq!(super::atomic_load(&slot, SeqCst), 0); - - let mut slot = 0u64; - super::atomic_store(&mut slot, 2, SeqCst); - } - } -} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index ab701b76026f4..355ee7c7a16f0 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -67,10 +67,10 @@ //! //! fn main() { //! let shared_map: Rc> = Rc::new(RefCell::new(HashMap::new())); -//! shared_map.borrow_mut().insert("africa", 92388); -//! shared_map.borrow_mut().insert("kyoto", 11837); -//! shared_map.borrow_mut().insert("piccadilly", 11826); -//! shared_map.borrow_mut().insert("marbles", 38); +//! shared_map.borrow_mut().insert("africa", 92388i); +//! shared_map.borrow_mut().insert("kyoto", 11837i); +//! shared_map.borrow_mut().insert("piccadilly", 11826i); +//! shared_map.borrow_mut().insert("marbles", 38i); //! } //! ``` //! @@ -383,132 +383,3 @@ impl<'b, T> DerefMut for RefMut<'b, T> { unsafe { &mut *self._parent.value.get() } } } - -#[cfg(test)] -mod test { - use super::*; - use mem::drop; - - #[test] - fn smoketest_cell() { - let x = Cell::new(10i); - assert!(x == Cell::new(10)); - assert!(x.get() == 10); - x.set(20); - assert!(x == Cell::new(20)); - assert!(x.get() == 20); - - let y = Cell::new((30i, 40i)); - assert!(y == Cell::new((30, 40))); - assert!(y.get() == (30, 40)); - } - - #[test] - fn cell_has_sensible_show() { - use str::StrSlice; - use realstd::str::Str; - - let x = Cell::new("foo bar"); - assert!(format!("{}", x).as_slice().contains(x.get())); - - x.set("baz qux"); - assert!(format!("{}", x).as_slice().contains(x.get())); - } - - #[test] - fn ref_and_refmut_have_sensible_show() { - use str::StrSlice; - use realstd::str::Str; - - let refcell = RefCell::new("foo"); - - let refcell_refmut = refcell.borrow_mut(); - assert!(format!("{}", refcell_refmut).as_slice().contains("foo")); - drop(refcell_refmut); - - let refcell_ref = refcell.borrow(); - assert!(format!("{}", refcell_ref).as_slice().contains("foo")); - drop(refcell_ref); - } - - #[test] - fn double_imm_borrow() { - let x = RefCell::new(0); - let _b1 = x.borrow(); - x.borrow(); - } - - #[test] - fn no_mut_then_imm_borrow() { - let x = RefCell::new(0); - let _b1 = x.borrow_mut(); - assert!(x.try_borrow().is_none()); - } - - #[test] - fn no_imm_then_borrow_mut() { - let x = RefCell::new(0); - let _b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn no_double_borrow_mut() { - let x = RefCell::new(0); - let _b1 = x.borrow_mut(); - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn imm_release_borrow_mut() { - let x = RefCell::new(0); - { - let _b1 = x.borrow(); - } - x.borrow_mut(); - } - - #[test] - fn mut_release_borrow_mut() { - let x = RefCell::new(0); - { - let _b1 = x.borrow_mut(); - } - x.borrow(); - } - - #[test] - fn double_borrow_single_release_no_borrow_mut() { - let x = RefCell::new(0); - let _b1 = x.borrow(); - { - let _b2 = x.borrow(); - } - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - #[should_fail] - fn discard_doesnt_unborrow() { - let x = RefCell::new(0); - let _b = x.borrow(); - let _ = _b; - let _b = x.borrow_mut(); - } - - #[test] - #[allow(experimental)] - fn clone_ref_updates_flag() { - let x = RefCell::new(0); - { - let b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); - { - let _b2 = clone_ref(&b1); - assert!(x.try_borrow_mut().is_none()); - } - assert!(x.try_borrow_mut().is_none()); - } - assert!(x.try_borrow_mut().is_some()); - } -} diff --git a/src/libcore/char.rs b/src/libcore/char.rs index c188ec75ddd09..da67772d0f122 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -602,205 +602,3 @@ impl Char for char { } -#[cfg(test)] -mod test { - use super::{escape_unicode, escape_default}; - - use char::Char; - use slice::ImmutableVector; - use option::{Some, None}; - use realstd::string::String; - use realstd::str::Str; - - #[test] - fn test_is_lowercase() { - assert!('a'.is_lowercase()); - assert!('ö'.is_lowercase()); - assert!('ß'.is_lowercase()); - assert!(!'Ü'.is_lowercase()); - assert!(!'P'.is_lowercase()); - } - - #[test] - fn test_is_uppercase() { - assert!(!'h'.is_uppercase()); - assert!(!'ä'.is_uppercase()); - assert!(!'ß'.is_uppercase()); - assert!('Ö'.is_uppercase()); - assert!('T'.is_uppercase()); - } - - #[test] - fn test_is_whitespace() { - assert!(' '.is_whitespace()); - assert!('\u2007'.is_whitespace()); - assert!('\t'.is_whitespace()); - assert!('\n'.is_whitespace()); - assert!(!'a'.is_whitespace()); - assert!(!'_'.is_whitespace()); - assert!(!'\u0000'.is_whitespace()); - } - - #[test] - fn test_to_digit() { - assert_eq!('0'.to_digit(10u), Some(0u)); - assert_eq!('1'.to_digit(2u), Some(1u)); - assert_eq!('2'.to_digit(3u), Some(2u)); - assert_eq!('9'.to_digit(10u), Some(9u)); - assert_eq!('a'.to_digit(16u), Some(10u)); - assert_eq!('A'.to_digit(16u), Some(10u)); - assert_eq!('b'.to_digit(16u), Some(11u)); - assert_eq!('B'.to_digit(16u), Some(11u)); - assert_eq!('z'.to_digit(36u), Some(35u)); - assert_eq!('Z'.to_digit(36u), Some(35u)); - assert_eq!(' '.to_digit(10u), None); - assert_eq!('$'.to_digit(36u), None); - } - - #[test] - fn test_to_lowercase() { - assert_eq!('A'.to_lowercase(), 'a'); - assert_eq!('Ö'.to_lowercase(), 'ö'); - assert_eq!('ß'.to_lowercase(), 'ß'); - assert_eq!('Ü'.to_lowercase(), 'ü'); - assert_eq!('💩'.to_lowercase(), '💩'); - assert_eq!('Σ'.to_lowercase(), 'σ'); - assert_eq!('Τ'.to_lowercase(), 'τ'); - assert_eq!('Ι'.to_lowercase(), 'ι'); - assert_eq!('Γ'.to_lowercase(), 'γ'); - assert_eq!('Μ'.to_lowercase(), 'μ'); - assert_eq!('Α'.to_lowercase(), 'α'); - assert_eq!('Σ'.to_lowercase(), 'σ'); - } - - #[test] - fn test_to_uppercase() { - assert_eq!('a'.to_uppercase(), 'A'); - assert_eq!('ö'.to_uppercase(), 'Ö'); - assert_eq!('ß'.to_uppercase(), 'ß'); // not ẞ: Latin capital letter sharp s - assert_eq!('ü'.to_uppercase(), 'Ü'); - assert_eq!('💩'.to_uppercase(), '💩'); - - assert_eq!('σ'.to_uppercase(), 'Σ'); - assert_eq!('τ'.to_uppercase(), 'Τ'); - assert_eq!('ι'.to_uppercase(), 'Ι'); - assert_eq!('γ'.to_uppercase(), 'Γ'); - assert_eq!('μ'.to_uppercase(), 'Μ'); - assert_eq!('α'.to_uppercase(), 'Α'); - assert_eq!('ς'.to_uppercase(), 'Σ'); - } - - #[test] - fn test_is_control() { - assert!('\u0000'.is_control()); - assert!('\u0003'.is_control()); - assert!('\u0006'.is_control()); - assert!('\u0009'.is_control()); - assert!('\u007f'.is_control()); - assert!('\u0092'.is_control()); - assert!(!'\u0020'.is_control()); - assert!(!'\u0055'.is_control()); - assert!(!'\u0068'.is_control()); - } - - #[test] - fn test_is_digit() { - assert!('2'.is_digit()); - assert!('7'.is_digit()); - assert!(!'c'.is_digit()); - assert!(!'i'.is_digit()); - assert!(!'z'.is_digit()); - assert!(!'Q'.is_digit()); - } - - #[test] - fn test_escape_default() { - fn string(c: char) -> String { - let mut result = String::new(); - escape_default(c, |c| { result.push_char(c); }); - return result; - } - let s = string('\n'); - assert_eq!(s.as_slice(), "\\n"); - let s = string('\r'); - assert_eq!(s.as_slice(), "\\r"); - let s = string('\''); - assert_eq!(s.as_slice(), "\\'"); - let s = string('"'); - assert_eq!(s.as_slice(), "\\\""); - let s = string(' '); - assert_eq!(s.as_slice(), " "); - let s = string('a'); - assert_eq!(s.as_slice(), "a"); - let s = string('~'); - assert_eq!(s.as_slice(), "~"); - let s = string('\x00'); - assert_eq!(s.as_slice(), "\\x00"); - let s = string('\x1f'); - assert_eq!(s.as_slice(), "\\x1f"); - let s = string('\x7f'); - assert_eq!(s.as_slice(), "\\x7f"); - let s = string('\xff'); - assert_eq!(s.as_slice(), "\\xff"); - let s = string('\u011b'); - assert_eq!(s.as_slice(), "\\u011b"); - let s = string('\U0001d4b6'); - assert_eq!(s.as_slice(), "\\U0001d4b6"); - } - - #[test] - fn test_escape_unicode() { - fn string(c: char) -> String { - let mut result = String::new(); - escape_unicode(c, |c| { result.push_char(c); }); - return result; - } - let s = string('\x00'); - assert_eq!(s.as_slice(), "\\x00"); - let s = string('\n'); - assert_eq!(s.as_slice(), "\\x0a"); - let s = string(' '); - assert_eq!(s.as_slice(), "\\x20"); - let s = string('a'); - assert_eq!(s.as_slice(), "\\x61"); - let s = string('\u011b'); - assert_eq!(s.as_slice(), "\\u011b"); - let s = string('\U0001d4b6'); - assert_eq!(s.as_slice(), "\\U0001d4b6"); - } - - #[test] - fn test_to_str() { - use realstd::to_str::ToStr; - let s = 't'.to_str(); - assert_eq!(s.as_slice(), "t"); - } - - #[test] - fn test_encode_utf8() { - fn check(input: char, expect: &[u8]) { - let mut buf = [0u8, ..4]; - let n = input.encode_utf8(buf /* as mut slice! */); - assert_eq!(buf.slice_to(n), expect); - } - - check('x', [0x78]); - check('\u00e9', [0xc3, 0xa9]); - check('\ua66e', [0xea, 0x99, 0xae]); - check('\U0001f4a9', [0xf0, 0x9f, 0x92, 0xa9]); - } - - #[test] - fn test_encode_utf16() { - fn check(input: char, expect: &[u16]) { - let mut buf = [0u16, ..2]; - let n = input.encode_utf16(buf /* as mut slice! */); - assert_eq!(buf.slice_to(n), expect); - } - - check('x', [0x0078]); - check('\u00e9', [0x00e9]); - check('\ua66e', [0xa66e]); - check('\U0001f4a9', [0xd83d, 0xdca9]); - } -} diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 04f01db314797..247f63115a783 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -110,63 +110,3 @@ extern_fn_clone!(A, B, C, D, E, F) extern_fn_clone!(A, B, C, D, E, F, G) extern_fn_clone!(A, B, C, D, E, F, G, H) -#[cfg(test)] -mod test { - use prelude::*; - use realstd::owned::Box; - use realstd::gc::{Gc, GC}; - - fn realclone(t: &T) -> T { - use realstd::clone::Clone; - t.clone() - } - - fn realclone_from(t1: &mut T, t2: &T) { - use realstd::clone::Clone; - t1.clone_from(t2) - } - - #[test] - fn test_owned_clone() { - let a = box 5i; - let b: Box = realclone(&a); - assert!(a == b); - } - - #[test] - fn test_managed_clone() { - let a = box(GC) 5i; - let b: Gc = realclone(&a); - assert!(a == b); - } - - #[test] - fn test_borrowed_clone() { - let x = 5i; - let y: &int = &x; - let z: &int = (&y).clone(); - assert_eq!(*z, 5); - } - - #[test] - fn test_clone_from() { - let a = box 5i; - let mut b = box 10i; - realclone_from(&mut b, &a); - assert_eq!(*b, 5); - } - - #[test] - fn test_extern_fn_clone() { - trait Empty {} - impl Empty for int {} - - fn test_fn_a() -> f64 { 1.0 } - fn test_fn_b(x: T) -> T { x } - fn test_fn_c(_: int, _: f64, _: int, _: int, _: int) {} - - let _ = test_fn_a.clone(); - let _ = test_fn_b::.clone(); - let _ = test_fn_c.clone(); - } -} diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index d7a3edccfd822..8696d385c4488 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -37,6 +37,10 @@ //! assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); //! ``` +use option::{Option, Some}; +#[cfg(stage0)] +use option::None; + /// Trait for values that can be compared for equality and inequality. /// /// This trait allows for partial equality, for types that do not have an @@ -86,11 +90,11 @@ pub trait Eq: PartialEq { #[deriving(Clone, PartialEq, Show)] pub enum Ordering { /// An ordering where a compared value is less [than another]. - Less = -1, + Less = -1i, /// An ordering where a compared value is equal [to another]. - Equal = 0, + Equal = 0i, /// An ordering where a compared value is greater [than another]. - Greater = 1 + Greater = 1i, } /// Trait for types that form a [total order]( @@ -127,7 +131,9 @@ impl Ord for Ordering { impl PartialOrd for Ordering { #[inline] - fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } + fn partial_cmp(&self, other: &Ordering) -> Option { + (*self as int).partial_cmp(&(*other as int)) + } } /// Combine orderings, lexically. @@ -145,7 +151,7 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { /// Trait for values that can be compared for a sort-order. /// -/// PartialOrd only requires implementation of the `lt` method, +/// PartialOrd only requires implementation of the `partial_cmp` method, /// with the others generated from default implementations. /// /// However it remains possible to implement the others separately for types @@ -154,20 +160,57 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { /// 5.11). #[lang="ord"] pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values + /// if one exists. + #[cfg(stage0)] + fn partial_cmp(&self, other: &Self) -> Option { + match (!self.lt(other), !other.lt(self)) { + (false, false) => None, + (false, true) => Some(Less), + (true, false) => Some(Greater), + (true, true) => Some(Equal), + } + } + + /// This method returns an ordering between `self` and `other` values + /// if one exists. + #[cfg(not(stage0))] + fn partial_cmp(&self, other: &Self) -> Option; + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. - fn lt(&self, other: &Self) -> bool; + fn lt(&self, other: &Self) -> bool { + match self.partial_cmp(other) { + Some(Less) => true, + _ => false, + } + } /// This method tests less than or equal to (`<=`). #[inline] - fn le(&self, other: &Self) -> bool { !other.lt(self) } + fn le(&self, other: &Self) -> bool { + match self.partial_cmp(other) { + Some(Less) | Some(Equal) => true, + _ => false, + } + } /// This method tests greater than (`>`). #[inline] - fn gt(&self, other: &Self) -> bool { other.lt(self) } + fn gt(&self, other: &Self) -> bool { + match self.partial_cmp(other) { + Some(Greater) => true, + _ => false, + } + } /// This method tests greater than or equal to (`>=`). #[inline] - fn ge(&self, other: &Self) -> bool { !self.lt(other) } + fn ge(&self, other: &Self) -> bool { + match self.partial_cmp(other) { + Some(Greater) | Some(Equal) => true, + _ => false, + } + } } /// The equivalence relation. Two values may be equivalent even if they are @@ -192,10 +235,10 @@ pub fn max(v1: T, v2: T) -> T { } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types -#[cfg(not(test))] mod impls { use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering, Less, Greater, Equal}; + use option::{Option, Some, None}; macro_rules! eq_impl( ($($t:ty)*) => ($( @@ -228,6 +271,15 @@ mod impls { macro_rules! ord_impl( ($($t:ty)*) => ($( impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &$t) -> Option { + match (self <= other, self >= other) { + (false, false) => None, + (false, true) => Some(Greater), + (true, false) => Some(Less), + (true, true) => Some(Equal), + } + } #[inline] fn lt(&self, other: &$t) -> bool { (*self) < (*other) } #[inline] @@ -242,13 +294,15 @@ mod impls { impl PartialOrd for () { #[inline] - fn lt(&self, _other: &()) -> bool { false } + fn partial_cmp(&self, _: &()) -> Option { + Some(Equal) + } } impl PartialOrd for bool { #[inline] - fn lt(&self, other: &bool) -> bool { - (*self as u8) < (*other as u8) + fn partial_cmp(&self, other: &bool) -> Option { + (*self as u8).partial_cmp(&(*other as u8)) } } @@ -289,6 +343,10 @@ mod impls { fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) } } impl<'a, T: PartialOrd> PartialOrd for &'a T { + #[inline] + fn partial_cmp(&self, other: &&'a T) -> Option { + (**self).partial_cmp(*other) + } #[inline] fn lt(&self, other: & &'a T) -> bool { *(*self) < *(*other) } #[inline] @@ -312,6 +370,10 @@ mod impls { fn ne(&self, other: &&'a mut T) -> bool { **self != *(*other) } } impl<'a, T: PartialOrd> PartialOrd for &'a mut T { + #[inline] + fn partial_cmp(&self, other: &&'a mut T) -> Option { + (**self).partial_cmp(*other) + } #[inline] fn lt(&self, other: &&'a mut T) -> bool { **self < **other } #[inline] @@ -327,66 +389,3 @@ mod impls { } impl<'a, T: Eq> Eq for &'a mut T {} } - -#[cfg(test)] -mod test { - use super::lexical_ordering; - - #[test] - fn test_int_totalord() { - assert_eq!(5u.cmp(&10), Less); - assert_eq!(10u.cmp(&5), Greater); - assert_eq!(5u.cmp(&5), Equal); - assert_eq!((-5u).cmp(&12), Less); - assert_eq!(12u.cmp(-5), Greater); - } - - #[test] - fn test_mut_int_totalord() { - assert_eq!((&mut 5u).cmp(&10), Less); - assert_eq!((&mut 10u).cmp(&5), Greater); - assert_eq!((&mut 5u).cmp(&5), Equal); - assert_eq!((&mut -5u).cmp(&12), Less); - assert_eq!((&mut 12u).cmp(-5), Greater); - } - - #[test] - fn test_ordering_order() { - assert!(Less < Equal); - assert_eq!(Greater.cmp(&Less), Greater); - } - - #[test] - fn test_lexical_ordering() { - fn t(o1: Ordering, o2: Ordering, e: Ordering) { - assert_eq!(lexical_ordering(o1, o2), e); - } - - let xs = [Less, Equal, Greater]; - for &o in xs.iter() { - t(Less, o, Less); - t(Equal, o, o); - t(Greater, o, Greater); - } - } - - #[test] - fn test_user_defined_eq() { - // Our type. - struct SketchyNum { - num : int - } - - // Our implementation of `PartialEq` to support `==` and `!=`. - impl PartialEq for SketchyNum { - // Our custom eq allows numbers which are near each other to be equal! :D - fn eq(&self, other: &SketchyNum) -> bool { - (self.num - other.num).abs() < 5 - } - } - - // Now these binary operators will work when applied! - assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); - assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); - } -} diff --git a/src/libcore/failure.rs b/src/libcore/failure.rs index c64bd6201faf3..4bc39db8ecf09 100644 --- a/src/libcore/failure.rs +++ b/src/libcore/failure.rs @@ -31,11 +31,10 @@ #![allow(dead_code, missing_doc)] use fmt; -#[cfg(not(test))] use intrinsics; +use intrinsics; #[cold] #[inline(never)] // this is the slow path, always #[lang="fail_"] -#[cfg(not(test))] fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! { format_args!(|args| -> () { begin_unwind(args, file, line); @@ -46,7 +45,6 @@ fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! { #[cold] #[lang="fail_bounds_check"] -#[cfg(not(test))] fn fail_bounds_check(file: &'static str, line: uint, index: uint, len: uint) -> ! { format_args!(|args| -> () { diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs index ab151460537af..514b3f90df7c0 100644 --- a/src/libcore/finally.rs +++ b/src/libcore/finally.rs @@ -115,55 +115,3 @@ impl<'a,A> Drop for Finallyalizer<'a,A> { } } -#[cfg(test)] -mod test { - use super::{try_finally, Finally}; - use realstd::task::failing; - - #[test] - fn test_success() { - let mut i = 0i; - try_finally( - &mut i, (), - |i, ()| { - *i = 10; - }, - |i| { - assert!(!failing()); - assert_eq!(*i, 10); - *i = 20; - }); - assert_eq!(i, 20); - } - - #[test] - #[should_fail] - fn test_fail() { - let mut i = 0i; - try_finally( - &mut i, (), - |i, ()| { - *i = 10; - fail!(); - }, - |i| { - assert!(failing()); - assert_eq!(*i, 10); - }) - } - - #[test] - fn test_retval() { - let mut closure: || -> int = || 10; - let i = closure.finally(|| { }); - assert_eq!(i, 10); - } - - #[test] - fn test_compact() { - fn do_some_fallible_work() {} - fn but_always_run_this_function() { } - let mut f = do_some_fallible_work; - f.finally(but_always_run_this_function); - } -} diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index d778f3b47a170..7b84c005db548 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -314,11 +314,11 @@ impl<'a> Formatter<'a> { rt::CountImplied => { None } rt::CountIsParam(i) => { let v = self.args[i].value; - unsafe { Some(*(v as *any::Void as *uint)) } + unsafe { Some(*(v as *const _ as *const uint)) } } rt::CountIsNextParam => { let v = self.curarg.next().unwrap().value; - unsafe { Some(*(v as *any::Void as *uint)) } + unsafe { Some(*(v as *const _ as *const uint)) } } } } @@ -496,31 +496,6 @@ pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter) -> Result, } } -#[cfg(test)] -pub fn format(args: &Arguments) -> ::realstd::string::String { - use str; - use realstd::io::MemWriter; - - fn mywrite(t: &mut T, b: &[u8]) { - use realstd::io::Writer; - let _ = t.write(b); - } - - impl FormatWriter for MemWriter { - fn write(&mut self, bytes: &[u8]) -> Result { - mywrite(self, bytes); - Ok(()) - } - } - - let mut i = MemWriter::new(); - let _ = write(&mut i, args); - - let mut result = ::realstd::string::String::new(); - result.push_str(str::from_utf8(i.get_ref()).unwrap()); - result -} - /// When the compiler determines that the type of an argument *must* be a string /// (such as for select), then it invokes this method. #[doc(hidden)] #[inline] @@ -543,6 +518,9 @@ impl<'a, T: Show> Show for &'a T { impl<'a, T: Show> Show for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) } } +impl<'a> Show for &'a Show { + fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) } +} impl Bool for bool { fn fmt(&self, f: &mut Formatter) -> Result { @@ -565,7 +543,7 @@ impl Char for char { } } -impl Pointer for *T { +impl Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { f.flags |= 1 << (rt::FlagAlternate as uint); secret_lower_hex::(&(*self as uint), f) @@ -573,17 +551,17 @@ impl Pointer for *T { } impl Pointer for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { - secret_pointer::<*T>(&(*self as *T), f) + secret_pointer::<*const T>(&(*self as *const T), f) } } impl<'a, T> Pointer for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { - secret_pointer::<*T>(&(&**self as *T), f) + secret_pointer::<*const T>(&(&**self as *const T), f) } } impl<'a, T> Pointer for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { - secret_pointer::<*T>(&(&**self as *T), f) + secret_pointer::<*const T>(&(&**self as *const T), f) } } @@ -669,7 +647,7 @@ delegate!(char to char) delegate!(f32 to float) delegate!(f64 to float) -impl Show for *T { +impl Show for *const T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } } impl Show for *mut T { @@ -686,7 +664,7 @@ macro_rules! tuple ( fn fmt(&self, f: &mut Formatter) -> Result { try!(write!(f, "(")); let ($(ref $name,)*) = *self; - let mut n = 0; + let mut n = 0i; $( if n > 0 { try!(write!(f, ", ")); diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 56d0817dd00be..d52791f6b0ea2 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -188,283 +188,3 @@ integer!(i8, u8) integer!(i16, u16) integer!(i32, u32) integer!(i64, u64) - -#[cfg(test)] -mod tests { - use fmt::radix; - use super::{Binary, Octal, Decimal, LowerHex, UpperHex}; - use super::{GenericRadix, Radix}; - use realstd::str::Str; - - #[test] - fn test_radix_base() { - assert_eq!(Binary.base(), 2); - assert_eq!(Octal.base(), 8); - assert_eq!(Decimal.base(), 10); - assert_eq!(LowerHex.base(), 16); - assert_eq!(UpperHex.base(), 16); - assert_eq!(Radix { base: 36 }.base(), 36); - } - - #[test] - fn test_radix_prefix() { - assert_eq!(Binary.prefix(), "0b"); - assert_eq!(Octal.prefix(), "0o"); - assert_eq!(Decimal.prefix(), ""); - assert_eq!(LowerHex.prefix(), "0x"); - assert_eq!(UpperHex.prefix(), "0x"); - assert_eq!(Radix { base: 36 }.prefix(), ""); - } - - #[test] - fn test_radix_digit() { - assert_eq!(Binary.digit(0), '0' as u8); - assert_eq!(Binary.digit(2), '2' as u8); - assert_eq!(Octal.digit(0), '0' as u8); - assert_eq!(Octal.digit(7), '7' as u8); - assert_eq!(Decimal.digit(0), '0' as u8); - assert_eq!(Decimal.digit(9), '9' as u8); - assert_eq!(LowerHex.digit(0), '0' as u8); - assert_eq!(LowerHex.digit(10), 'a' as u8); - assert_eq!(LowerHex.digit(15), 'f' as u8); - assert_eq!(UpperHex.digit(0), '0' as u8); - assert_eq!(UpperHex.digit(10), 'A' as u8); - assert_eq!(UpperHex.digit(15), 'F' as u8); - assert_eq!(Radix { base: 36 }.digit(0), '0' as u8); - assert_eq!(Radix { base: 36 }.digit(15), 'f' as u8); - assert_eq!(Radix { base: 36 }.digit(35), 'z' as u8); - } - - #[test] - #[should_fail] - fn test_hex_radix_digit_overflow() { - let _ = LowerHex.digit(16); - } - - #[test] - fn test_format_int() { - // Formatting integers should select the right implementation based off - // the type of the argument. Also, hex/octal/binary should be defined - // for integers, but they shouldn't emit the negative sign. - assert!(format!("{}", 1i).as_slice() == "1"); - assert!(format!("{}", 1i8).as_slice() == "1"); - assert!(format!("{}", 1i16).as_slice() == "1"); - assert!(format!("{}", 1i32).as_slice() == "1"); - assert!(format!("{}", 1i64).as_slice() == "1"); - assert!(format!("{:d}", -1i).as_slice() == "-1"); - assert!(format!("{:d}", -1i8).as_slice() == "-1"); - assert!(format!("{:d}", -1i16).as_slice() == "-1"); - assert!(format!("{:d}", -1i32).as_slice() == "-1"); - assert!(format!("{:d}", -1i64).as_slice() == "-1"); - assert!(format!("{:t}", 1i).as_slice() == "1"); - assert!(format!("{:t}", 1i8).as_slice() == "1"); - assert!(format!("{:t}", 1i16).as_slice() == "1"); - assert!(format!("{:t}", 1i32).as_slice() == "1"); - assert!(format!("{:t}", 1i64).as_slice() == "1"); - assert!(format!("{:x}", 1i).as_slice() == "1"); - assert!(format!("{:x}", 1i8).as_slice() == "1"); - assert!(format!("{:x}", 1i16).as_slice() == "1"); - assert!(format!("{:x}", 1i32).as_slice() == "1"); - assert!(format!("{:x}", 1i64).as_slice() == "1"); - assert!(format!("{:X}", 1i).as_slice() == "1"); - assert!(format!("{:X}", 1i8).as_slice() == "1"); - assert!(format!("{:X}", 1i16).as_slice() == "1"); - assert!(format!("{:X}", 1i32).as_slice() == "1"); - assert!(format!("{:X}", 1i64).as_slice() == "1"); - assert!(format!("{:o}", 1i).as_slice() == "1"); - assert!(format!("{:o}", 1i8).as_slice() == "1"); - assert!(format!("{:o}", 1i16).as_slice() == "1"); - assert!(format!("{:o}", 1i32).as_slice() == "1"); - assert!(format!("{:o}", 1i64).as_slice() == "1"); - - assert!(format!("{}", 1u).as_slice() == "1"); - assert!(format!("{}", 1u8).as_slice() == "1"); - assert!(format!("{}", 1u16).as_slice() == "1"); - assert!(format!("{}", 1u32).as_slice() == "1"); - assert!(format!("{}", 1u64).as_slice() == "1"); - assert!(format!("{:u}", 1u).as_slice() == "1"); - assert!(format!("{:u}", 1u8).as_slice() == "1"); - assert!(format!("{:u}", 1u16).as_slice() == "1"); - assert!(format!("{:u}", 1u32).as_slice() == "1"); - assert!(format!("{:u}", 1u64).as_slice() == "1"); - assert!(format!("{:t}", 1u).as_slice() == "1"); - assert!(format!("{:t}", 1u8).as_slice() == "1"); - assert!(format!("{:t}", 1u16).as_slice() == "1"); - assert!(format!("{:t}", 1u32).as_slice() == "1"); - assert!(format!("{:t}", 1u64).as_slice() == "1"); - assert!(format!("{:x}", 1u).as_slice() == "1"); - assert!(format!("{:x}", 1u8).as_slice() == "1"); - assert!(format!("{:x}", 1u16).as_slice() == "1"); - assert!(format!("{:x}", 1u32).as_slice() == "1"); - assert!(format!("{:x}", 1u64).as_slice() == "1"); - assert!(format!("{:X}", 1u).as_slice() == "1"); - assert!(format!("{:X}", 1u8).as_slice() == "1"); - assert!(format!("{:X}", 1u16).as_slice() == "1"); - assert!(format!("{:X}", 1u32).as_slice() == "1"); - assert!(format!("{:X}", 1u64).as_slice() == "1"); - assert!(format!("{:o}", 1u).as_slice() == "1"); - assert!(format!("{:o}", 1u8).as_slice() == "1"); - assert!(format!("{:o}", 1u16).as_slice() == "1"); - assert!(format!("{:o}", 1u32).as_slice() == "1"); - assert!(format!("{:o}", 1u64).as_slice() == "1"); - - // Test a larger number - assert!(format!("{:t}", 55i).as_slice() == "110111"); - assert!(format!("{:o}", 55i).as_slice() == "67"); - assert!(format!("{:d}", 55i).as_slice() == "55"); - assert!(format!("{:x}", 55i).as_slice() == "37"); - assert!(format!("{:X}", 55i).as_slice() == "37"); - } - - #[test] - fn test_format_int_zero() { - assert!(format!("{}", 0i).as_slice() == "0"); - assert!(format!("{:d}", 0i).as_slice() == "0"); - assert!(format!("{:t}", 0i).as_slice() == "0"); - assert!(format!("{:o}", 0i).as_slice() == "0"); - assert!(format!("{:x}", 0i).as_slice() == "0"); - assert!(format!("{:X}", 0i).as_slice() == "0"); - - assert!(format!("{}", 0u).as_slice() == "0"); - assert!(format!("{:u}", 0u).as_slice() == "0"); - assert!(format!("{:t}", 0u).as_slice() == "0"); - assert!(format!("{:o}", 0u).as_slice() == "0"); - assert!(format!("{:x}", 0u).as_slice() == "0"); - assert!(format!("{:X}", 0u).as_slice() == "0"); - } - - #[test] - fn test_format_int_flags() { - assert!(format!("{:3d}", 1i).as_slice() == " 1"); - assert!(format!("{:>3d}", 1i).as_slice() == " 1"); - assert!(format!("{:>+3d}", 1i).as_slice() == " +1"); - assert!(format!("{:<3d}", 1i).as_slice() == "1 "); - assert!(format!("{:#d}", 1i).as_slice() == "1"); - assert!(format!("{:#x}", 10i).as_slice() == "0xa"); - assert!(format!("{:#X}", 10i).as_slice() == "0xA"); - assert!(format!("{:#5x}", 10i).as_slice() == " 0xa"); - assert!(format!("{:#o}", 10i).as_slice() == "0o12"); - assert!(format!("{:08x}", 10i).as_slice() == "0000000a"); - assert!(format!("{:8x}", 10i).as_slice() == " a"); - assert!(format!("{:<8x}", 10i).as_slice() == "a "); - assert!(format!("{:>8x}", 10i).as_slice() == " a"); - assert!(format!("{:#08x}", 10i).as_slice() == "0x00000a"); - assert!(format!("{:08d}", -10i).as_slice() == "-0000010"); - assert!(format!("{:x}", -1u8).as_slice() == "ff"); - assert!(format!("{:X}", -1u8).as_slice() == "FF"); - assert!(format!("{:t}", -1u8).as_slice() == "11111111"); - assert!(format!("{:o}", -1u8).as_slice() == "377"); - assert!(format!("{:#x}", -1u8).as_slice() == "0xff"); - assert!(format!("{:#X}", -1u8).as_slice() == "0xFF"); - assert!(format!("{:#t}", -1u8).as_slice() == "0b11111111"); - assert!(format!("{:#o}", -1u8).as_slice() == "0o377"); - } - - #[test] - fn test_format_int_sign_padding() { - assert!(format!("{:+5d}", 1i).as_slice() == " +1"); - assert!(format!("{:+5d}", -1i).as_slice() == " -1"); - assert!(format!("{:05d}", 1i).as_slice() == "00001"); - assert!(format!("{:05d}", -1i).as_slice() == "-0001"); - assert!(format!("{:+05d}", 1i).as_slice() == "+0001"); - assert!(format!("{:+05d}", -1i).as_slice() == "-0001"); - } - - #[test] - fn test_format_int_twos_complement() { - use {i8, i16, i32, i64}; - assert!(format!("{}", i8::MIN).as_slice() == "-128"); - assert!(format!("{}", i16::MIN).as_slice() == "-32768"); - assert!(format!("{}", i32::MIN).as_slice() == "-2147483648"); - assert!(format!("{}", i64::MIN).as_slice() == "-9223372036854775808"); - } - - #[test] - fn test_format_radix() { - assert!(format!("{:04}", radix(3i, 2)).as_slice() == "0011"); - assert!(format!("{}", radix(55i, 36)).as_slice() == "1j"); - } - - #[test] - #[should_fail] - fn test_radix_base_too_large() { - let _ = radix(55, 37); - } -} - -#[cfg(test)] -mod bench { - extern crate test; - - mod uint { - use super::test::Bencher; - use fmt::radix; - use realstd::rand::{weak_rng, Rng}; - - #[bench] - fn format_bin(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:t}", rng.gen::()); }) - } - - #[bench] - fn format_oct(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:o}", rng.gen::()); }) - } - - #[bench] - fn format_dec(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:u}", rng.gen::()); }) - } - - #[bench] - fn format_hex(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:x}", rng.gen::()); }) - } - - #[bench] - fn format_base_36(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) - } - } - - mod int { - use super::test::Bencher; - use fmt::radix; - use realstd::rand::{weak_rng, Rng}; - - #[bench] - fn format_bin(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:t}", rng.gen::()); }) - } - - #[bench] - fn format_oct(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:o}", rng.gen::()); }) - } - - #[bench] - fn format_dec(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:d}", rng.gen::()); }) - } - - #[bench] - fn format_hex(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{:x}", rng.gen::()); }) - } - - #[bench] - fn format_base_36(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) - } - } -} diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 6519d3b749de4..161dd7cef7e13 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -44,14 +44,9 @@ A quick refresher on memory ordering: #![experimental] #![allow(missing_doc)] -// This is needed to prevent duplicate lang item definitions. -#[cfg(test)] -pub use realcore::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId}; - -pub type GlueFn = extern "Rust" fn(*i8); +pub type GlueFn = extern "Rust" fn(*const i8); #[lang="ty_desc"] -#[cfg(not(test))] pub struct TyDesc { // sizeof(T) pub size: uint, @@ -70,13 +65,11 @@ pub struct TyDesc { } #[lang="opaque"] -#[cfg(not(test))] pub enum Opaque { } pub type Disr = u64; #[lang="ty_visitor"] -#[cfg(not(test))] pub trait TyVisitor { fn visit_bot(&mut self) -> bool; fn visit_nil(&mut self) -> bool; @@ -102,55 +95,58 @@ pub trait TyVisitor { fn visit_estr_slice(&mut self) -> bool; fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool; - fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool; - fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool; - fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool; - fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool; + fn visit_uniq(&mut self, mtbl: uint, inner: *const TyDesc) -> bool; + fn visit_ptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool; + fn visit_rptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool; - fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool; fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, - mtbl: uint, inner: *TyDesc) -> bool; + mtbl: uint, inner: *const TyDesc) -> bool; fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool; fn visit_rec_field(&mut self, i: uint, name: &str, - mtbl: uint, inner: *TyDesc) -> bool; + mtbl: uint, inner: *const TyDesc) -> bool; fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool; fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, sz: uint, align: uint) -> bool; fn visit_class_field(&mut self, i: uint, name: &str, named: bool, - mtbl: uint, inner: *TyDesc) -> bool; + mtbl: uint, inner: *const TyDesc) -> bool; fn visit_leave_class(&mut self, name: &str, named_fields: bool, n_fields: uint, sz: uint, align: uint) -> bool; fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool; - fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool; + fn visit_tup_field(&mut self, i: uint, inner: *const TyDesc) -> bool; fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool; fn visit_enter_enum(&mut self, n_variants: uint, - get_disr: unsafe extern fn(ptr: *Opaque) -> Disr, + get_disr: unsafe extern fn(ptr: *const Opaque) -> Disr, sz: uint, align: uint) -> bool; fn visit_enter_enum_variant(&mut self, variant: uint, disr_val: Disr, n_fields: uint, name: &str) -> bool; - fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool; + fn visit_enum_variant_field(&mut self, i: uint, offset: uint, + inner: *const TyDesc) -> bool; fn visit_leave_enum_variant(&mut self, variant: uint, disr_val: Disr, n_fields: uint, name: &str) -> bool; fn visit_leave_enum(&mut self, n_variants: uint, - get_disr: unsafe extern fn(ptr: *Opaque) -> Disr, + get_disr: unsafe extern fn(ptr: *const Opaque) -> Disr, sz: uint, align: uint) -> bool; fn visit_enter_fn(&mut self, purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool; - fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool; - fn visit_fn_output(&mut self, retstyle: uint, variadic: bool, inner: *TyDesc) -> bool; + fn visit_fn_input(&mut self, i: uint, mode: uint, + inner: *const TyDesc) -> bool; + fn visit_fn_output(&mut self, retstyle: uint, variadic: bool, + inner: *const TyDesc) -> bool; fn visit_leave_fn(&mut self, purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool; @@ -170,9 +166,9 @@ extern "rust-intrinsic" { pub fn atomic_cxchg_acqrel(dst: *mut T, old: T, src: T) -> T; pub fn atomic_cxchg_relaxed(dst: *mut T, old: T, src: T) -> T; - pub fn atomic_load(src: *T) -> T; - pub fn atomic_load_acq(src: *T) -> T; - pub fn atomic_load_relaxed(src: *T) -> T; + pub fn atomic_load(src: *const T) -> T; + pub fn atomic_load_acq(src: *const T) -> T; + pub fn atomic_load_relaxed(src: *const T) -> T; pub fn atomic_store(dst: *mut T, val: T); pub fn atomic_store_rel(dst: *mut T, val: T); @@ -276,7 +272,7 @@ extern "rust-intrinsic" { pub fn pref_align_of() -> uint; /// Get a static pointer to a type descriptor. - pub fn get_tydesc() -> *TyDesc; + pub fn get_tydesc() -> *const TyDesc; /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever @@ -320,7 +316,7 @@ extern "rust-intrinsic" { /// Returns `true` if a type is managed (will be allocated on the local heap) pub fn owns_managed() -> bool; - pub fn visit_tydesc(td: *TyDesc, tv: &mut TyVisitor); + pub fn visit_tydesc(td: *const TyDesc, tv: &mut TyVisitor); /// Calculates the offset from a pointer. The offset *must* be in-bounds of /// the object, or one-byte-past-the-end. An arithmetic overflow is also @@ -328,17 +324,17 @@ extern "rust-intrinsic" { /// /// This is implemented as an intrinsic to avoid converting to and from an /// integer, since the conversion would throw away aliasing information. - pub fn offset(dst: *T, offset: int) -> *T; + pub fn offset(dst: *const T, offset: int) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::()` and an alignment of /// `min_align_of::()` - pub fn copy_nonoverlapping_memory(dst: *mut T, src: *T, count: uint); + pub fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint); /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::()` and an alignment of /// `min_align_of::()` - pub fn copy_memory(dst: *mut T, src: *T, count: uint); + pub fn copy_memory(dst: *mut T, src: *const T, count: uint); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a /// size of `count` * `size_of::()` and an alignment of @@ -350,13 +346,14 @@ extern "rust-intrinsic" { /// `min_align_of::()` /// /// The volatile parameter parameter is set to `true`, so it will not be optimized out. - pub fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *T, count: uint); + pub fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, + count: uint); /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::()` and an alignment of /// `min_align_of::()` /// /// The volatile parameter parameter is set to `true`, so it will not be optimized out. - pub fn volatile_copy_memory(dst: *mut T, src: *T, count: uint); + pub fn volatile_copy_memory(dst: *mut T, src: *const T, count: uint); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a /// size of `count` * `size_of::()` and an alignment of /// `min_align_of::()`. @@ -365,7 +362,7 @@ extern "rust-intrinsic" { pub fn volatile_set_memory(dst: *mut T, val: u8, count: uint); /// Perform a volatile load from the `src` pointer. - pub fn volatile_load(src: *T) -> T; + pub fn volatile_load(src: *const T) -> T; /// Perform a volatile store to the `dst` pointer. pub fn volatile_store(dst: *mut T, val: T); @@ -560,12 +557,10 @@ extern "rust-intrinsic" { #[lang="type_id"] // This needs to be kept in lockstep with the code in trans/intrinsic.rs and // middle/lang_items.rs #[deriving(PartialEq, Eq, Show)] -#[cfg(not(test))] pub struct TypeId { t: u64, } -#[cfg(not(test))] impl TypeId { /// Returns the `TypeId` of the type this generic function has been instantiated with pub fn of() -> TypeId { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 3f4d3020815df..5895d871dbe18 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -135,7 +135,8 @@ pub trait Iterator { /// let a = [0i]; /// let b = [1i]; /// let mut it = a.iter().zip(b.iter()); - /// assert_eq!(it.next().unwrap(), (&0, &1)); + /// let (x0, x1) = (0i, 1i); + /// assert_eq!(it.next().unwrap(), (&x0, &x1)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -202,8 +203,9 @@ pub trait Iterator { /// ```rust /// let a = [100i, 200]; /// let mut it = a.iter().enumerate(); - /// assert_eq!(it.next().unwrap(), (0, &100)); - /// assert_eq!(it.next().unwrap(), (1, &200)); + /// let (x100, x200) = (100i, 200i); + /// assert_eq!(it.next().unwrap(), (0, &x100)); + /// assert_eq!(it.next().unwrap(), (1, &x200)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -220,11 +222,11 @@ pub trait Iterator { /// ```rust /// let xs = [100i, 200, 300]; /// let mut it = xs.iter().map(|x| *x).peekable(); - /// assert_eq!(it.peek().unwrap(), &100); + /// assert_eq!(*it.peek().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 200); - /// assert_eq!(it.peek().unwrap(), &300); - /// assert_eq!(it.peek().unwrap(), &300); + /// assert_eq!(*it.peek().unwrap(), 300); + /// assert_eq!(*it.peek().unwrap(), 300); /// assert_eq!(it.next().unwrap(), 300); /// assert!(it.peek().is_none()); /// assert!(it.next().is_none()); @@ -2181,7 +2183,7 @@ impl RandomAccessIterator for Repeat { pub mod order { use cmp; use cmp::{Eq, Ord, PartialOrd, PartialEq}; - use option::{Some, None}; + use option::{Option, Some, None}; use super::Iterator; /// Compare `a` and `b` for equality using `Eq` @@ -2210,6 +2212,22 @@ pub mod order { } } + /// Order `a` and `b` lexicographically using `PartialOrd` + pub fn partial_cmp, S: Iterator>(mut a: T, mut b: S) + -> Option { + loop { + match (a.next(), b.next()) { + (None, None) => return Some(cmp::Equal), + (None, _ ) => return Some(cmp::Less), + (_ , None) => return Some(cmp::Greater), + (Some(x), Some(y)) => match x.partial_cmp(&y) { + Some(cmp::Equal) => (), + non_eq => return non_eq, + }, + } + } + } + /// Compare `a` and `b` for equality (Using partial equality, `PartialEq`) pub fn eq, S: Iterator>(mut a: T, mut b: S) -> bool { loop { @@ -2279,868 +2297,5 @@ pub mod order { } } } - - #[test] - fn test_lt() { - use slice::ImmutableVector; - - let empty: [int, ..0] = []; - let xs = [1i,2,3]; - let ys = [1i,2,0]; - - assert!(!lt(xs.iter(), ys.iter())); - assert!(!le(xs.iter(), ys.iter())); - assert!( gt(xs.iter(), ys.iter())); - assert!( ge(xs.iter(), ys.iter())); - - assert!( lt(ys.iter(), xs.iter())); - assert!( le(ys.iter(), xs.iter())); - assert!(!gt(ys.iter(), xs.iter())); - assert!(!ge(ys.iter(), xs.iter())); - - assert!( lt(empty.iter(), xs.iter())); - assert!( le(empty.iter(), xs.iter())); - assert!(!gt(empty.iter(), xs.iter())); - assert!(!ge(empty.iter(), xs.iter())); - - // Sequence with NaN - let u = [1.0f64, 2.0]; - let v = [0.0f64/0.0, 3.0]; - - assert!(!lt(u.iter(), v.iter())); - assert!(!le(u.iter(), v.iter())); - assert!(!gt(u.iter(), v.iter())); - assert!(!ge(u.iter(), v.iter())); - - let a = [0.0f64/0.0]; - let b = [1.0f64]; - let c = [2.0f64]; - - assert!(lt(a.iter(), b.iter()) == (a[0] < b[0])); - assert!(le(a.iter(), b.iter()) == (a[0] <= b[0])); - assert!(gt(a.iter(), b.iter()) == (a[0] > b[0])); - assert!(ge(a.iter(), b.iter()) == (a[0] >= b[0])); - - assert!(lt(c.iter(), b.iter()) == (c[0] < b[0])); - assert!(le(c.iter(), b.iter()) == (c[0] <= b[0])); - assert!(gt(c.iter(), b.iter()) == (c[0] > b[0])); - assert!(ge(c.iter(), b.iter()) == (c[0] >= b[0])); - } - - #[test] - fn test_multi_iter() { - use slice::ImmutableVector; - use iter::DoubleEndedIterator; - let xs = [1i,2,3,4]; - let ys = [4i,3,2,1]; - assert!(eq(xs.iter(), ys.iter().rev())); - assert!(lt(xs.iter(), xs.iter().skip(2))); - } } -#[cfg(test)] -mod tests { - use prelude::*; - use iter::*; - use num; - use realstd::vec::Vec; - use realstd::slice::Vector; - use realstd::gc::GC; - - use cmp; - use realstd::owned::Box; - use uint; - - impl FromIterator for Vec { - fn from_iter>(mut iterator: I) -> Vec { - let mut v = Vec::new(); - for e in iterator { - v.push(e); - } - return v; - } - } - - impl<'a, T> Iterator<&'a T> for ::realcore::slice::Items<'a, T> { - fn next(&mut self) -> Option<&'a T> { - use RealSome = realcore::option::Some; - use RealNone = realcore::option::None; - fn mynext>(i: &mut I) - -> ::realcore::option::Option - { - use realcore::iter::Iterator; - i.next() - } - match mynext(self) { - RealSome(t) => Some(t), - RealNone => None, - } - } - } - - #[test] - fn test_counter_from_iter() { - let it = count(0i, 5).take(10); - let xs: Vec = FromIterator::from_iter(it); - assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); - } - - #[test] - fn test_iterator_chain() { - let xs = [0u, 1, 2, 3, 4, 5]; - let ys = [30u, 40, 50, 60]; - let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; - let mut it = xs.iter().chain(ys.iter()); - let mut i = 0; - for &x in it { - assert_eq!(x, expected[i]); - i += 1; - } - assert_eq!(i, expected.len()); - - let ys = count(30u, 10).take(4); - let mut it = xs.iter().map(|&x| x).chain(ys); - let mut i = 0; - for x in it { - assert_eq!(x, expected[i]); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_filter_map() { - let mut it = count(0u, 1u).take(10) - .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); - assert!(it.collect::>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]); - } - - #[test] - fn test_iterator_enumerate() { - let xs = [0u, 1, 2, 3, 4, 5]; - let mut it = xs.iter().enumerate(); - for (i, &x) in it { - assert_eq!(i, x); - } - } - - #[test] - fn test_iterator_peekable() { - let xs = vec![0u, 1, 2, 3, 4, 5]; - let mut it = xs.iter().map(|&x|x).peekable(); - assert_eq!(it.peek().unwrap(), &0); - assert_eq!(it.next().unwrap(), 0); - assert_eq!(it.next().unwrap(), 1); - assert_eq!(it.next().unwrap(), 2); - assert_eq!(it.peek().unwrap(), &3); - assert_eq!(it.peek().unwrap(), &3); - assert_eq!(it.next().unwrap(), 3); - assert_eq!(it.next().unwrap(), 4); - assert_eq!(it.peek().unwrap(), &5); - assert_eq!(it.next().unwrap(), 5); - assert!(it.peek().is_none()); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_take_while() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5, 13]; - let mut it = xs.iter().take_while(|&x| *x < 15u); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip_while() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [15, 16, 17, 19]; - let mut it = xs.iter().skip_while(|&x| *x < 15u); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; - let ys = [13, 15, 16, 17, 19, 20, 30]; - let mut it = xs.iter().skip(5); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_take() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5]; - let mut it = xs.iter().take(5); - let mut i = 0; - for &x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_scan() { - // test the type inference - fn add(old: &mut int, new: &uint) -> Option { - *old += *new as int; - Some(*old as f64) - } - let xs = [0u, 1, 2, 3, 4]; - let ys = [0f64, 1.0, 3.0, 6.0, 10.0]; - - let mut it = xs.iter().scan(0, add); - let mut i = 0; - for x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_flat_map() { - let xs = [0u, 3, 6]; - let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8]; - let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3)); - let mut i = 0; - for x in it { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_inspect() { - let xs = [1u, 2, 3, 4]; - let mut n = 0; - - let ys = xs.iter() - .map(|&x| x) - .inspect(|_| n += 1) - .collect::>(); - - assert_eq!(n, xs.len()); - assert_eq!(xs.as_slice(), ys.as_slice()); - } - - #[test] - fn test_unfoldr() { - fn count(st: &mut uint) -> Option { - if *st < 10 { - let ret = Some(*st); - *st += 1; - ret - } else { - None - } - } - - let mut it = Unfold::new(0, count); - let mut i = 0; - for counted in it { - assert_eq!(counted, i); - i += 1; - } - assert_eq!(i, 10); - } - - #[test] - fn test_cycle() { - let cycle_len = 3; - let it = count(0u, 1).take(cycle_len).cycle(); - assert_eq!(it.size_hint(), (uint::MAX, None)); - for (i, x) in it.take(100).enumerate() { - assert_eq!(i % cycle_len, x); - } - - let mut it = count(0u, 1).take(0).cycle(); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_iterator_nth() { - let v = &[0i, 1, 2, 3, 4]; - for i in range(0u, v.len()) { - assert_eq!(v.iter().nth(i).unwrap(), &v[i]); - } - } - - #[test] - fn test_iterator_last() { - let v = &[0i, 1, 2, 3, 4]; - assert_eq!(v.iter().last().unwrap(), &4); - assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0); - } - - #[test] - fn test_iterator_len() { - let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().count(), 4); - assert_eq!(v.slice(0, 10).iter().count(), 10); - assert_eq!(v.slice(0, 0).iter().count(), 0); - } - - #[test] - fn test_iterator_sum() { - let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).sum(), 6); - assert_eq!(v.iter().map(|&x| x).sum(), 55); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).sum(), 0); - } - - #[test] - fn test_iterator_product() { - let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).product(), 0); - assert_eq!(v.slice(1, 5).iter().map(|&x| x).product(), 24); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).product(), 1); - } - - #[test] - fn test_iterator_max() { - let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).max(), Some(3)); - assert_eq!(v.iter().map(|&x| x).max(), Some(10)); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).max(), None); - } - - #[test] - fn test_iterator_min() { - let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v.slice(0, 4).iter().map(|&x| x).min(), Some(0)); - assert_eq!(v.iter().map(|&x| x).min(), Some(0)); - assert_eq!(v.slice(0, 0).iter().map(|&x| x).min(), None); - } - - #[test] - fn test_iterator_size_hint() { - let c = count(0i, 1); - let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let v2 = &[10i, 11, 12]; - let vi = v.iter(); - - assert_eq!(c.size_hint(), (uint::MAX, None)); - assert_eq!(vi.size_hint(), (10, Some(10))); - - assert_eq!(c.take(5).size_hint(), (5, Some(5))); - assert_eq!(c.skip(5).size_hint().val1(), None); - assert_eq!(c.take_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.skip_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.enumerate().size_hint(), (uint::MAX, None)); - assert_eq!(c.chain(vi.map(|&i| i)).size_hint(), (uint::MAX, None)); - assert_eq!(c.zip(vi).size_hint(), (10, Some(10))); - assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None)); - assert_eq!(c.filter(|_| false).size_hint(), (0, None)); - assert_eq!(c.map(|_| 0).size_hint(), (uint::MAX, None)); - assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); - - assert_eq!(vi.take(5).size_hint(), (5, Some(5))); - assert_eq!(vi.take(12).size_hint(), (10, Some(10))); - assert_eq!(vi.skip(3).size_hint(), (7, Some(7))); - assert_eq!(vi.skip(12).size_hint(), (0, Some(0))); - assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10))); - assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10))); - assert_eq!(vi.enumerate().size_hint(), (10, Some(10))); - assert_eq!(vi.chain(v2.iter()).size_hint(), (13, Some(13))); - assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3))); - assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10))); - assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10))); - assert_eq!(vi.map(|i| i+1).size_hint(), (10, Some(10))); - assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10))); - } - - #[test] - fn test_collect() { - let a = vec![1i, 2, 3, 4, 5]; - let b: Vec = a.iter().map(|&x| x).collect(); - assert!(a == b); - } - - #[test] - fn test_all() { - let v: Box<&[int]> = box &[1i, 2, 3, 4, 5]; - assert!(v.iter().all(|&x| x < 10)); - assert!(!v.iter().all(|&x| x % 2 == 0)); - assert!(!v.iter().all(|&x| x > 100)); - assert!(v.slice(0, 0).iter().all(|_| fail!())); - } - - #[test] - fn test_any() { - let v: Box<&[int]> = box &[1i, 2, 3, 4, 5]; - assert!(v.iter().any(|&x| x < 10)); - assert!(v.iter().any(|&x| x % 2 == 0)); - assert!(!v.iter().any(|&x| x > 100)); - assert!(!v.slice(0, 0).iter().any(|_| fail!())); - } - - #[test] - fn test_find() { - let v: &[int] = &[1i, 3, 9, 27, 103, 14, 11]; - assert_eq!(*v.iter().find(|x| *x & 1 == 0).unwrap(), 14); - assert_eq!(*v.iter().find(|x| *x % 3 == 0).unwrap(), 3); - assert!(v.iter().find(|x| *x % 12 == 0).is_none()); - } - - #[test] - fn test_position() { - let v = &[1i, 3, 9, 27, 103, 14, 11]; - assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5); - assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1); - assert!(v.iter().position(|x| *x % 12 == 0).is_none()); - } - - #[test] - fn test_count() { - let xs = &[1i, 2, 2, 1, 5, 9, 0, 2]; - assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3); - assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1); - assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0); - } - - #[test] - fn test_max_by() { - let xs: &[int] = &[-3i, 0, 1, 5, -10]; - assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); - } - - #[test] - fn test_min_by() { - let xs: &[int] = &[-3i, 0, 1, 5, -10]; - assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); - } - - #[test] - fn test_by_ref() { - let mut xs = range(0i, 10); - // sum the first five values - let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); - assert_eq!(partial_sum, 10); - assert_eq!(xs.next(), Some(5)); - } - - #[test] - fn test_rev() { - let xs = [2i, 4, 6, 8, 10, 12, 14, 16]; - let mut it = xs.iter(); - it.next(); - it.next(); - assert!(it.rev().map(|&x| x).collect::>() == - vec![16, 14, 12, 10, 8, 6]); - } - - #[test] - fn test_double_ended_map() { - let xs = [1i, 2, 3, 4, 5, 6]; - let mut it = xs.iter().map(|&x| x * -1); - assert_eq!(it.next(), Some(-1)); - assert_eq!(it.next(), Some(-2)); - assert_eq!(it.next_back(), Some(-6)); - assert_eq!(it.next_back(), Some(-5)); - assert_eq!(it.next(), Some(-3)); - assert_eq!(it.next_back(), Some(-4)); - assert_eq!(it.next(), None); - } - - #[test] - fn test_double_ended_enumerate() { - let xs = [1i, 2, 3, 4, 5, 6]; - let mut it = xs.iter().map(|&x| x).enumerate(); - assert_eq!(it.next(), Some((0, 1))); - assert_eq!(it.next(), Some((1, 2))); - assert_eq!(it.next_back(), Some((5, 6))); - assert_eq!(it.next_back(), Some((4, 5))); - assert_eq!(it.next_back(), Some((3, 4))); - assert_eq!(it.next_back(), Some((2, 3))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_double_ended_zip() { - let xs = [1i, 2, 3, 4, 5, 6]; - let ys = [1i, 2, 3, 7]; - let a = xs.iter().map(|&x| x); - let b = ys.iter().map(|&x| x); - let mut it = a.zip(b); - assert_eq!(it.next(), Some((1, 1))); - assert_eq!(it.next(), Some((2, 2))); - assert_eq!(it.next_back(), Some((4, 7))); - assert_eq!(it.next_back(), Some((3, 3))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_double_ended_filter() { - let xs = [1i, 2, 3, 4, 5, 6]; - let mut it = xs.iter().filter(|&x| *x & 1 == 0); - assert_eq!(it.next_back().unwrap(), &6); - assert_eq!(it.next_back().unwrap(), &4); - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.next_back(), None); - } - - #[test] - fn test_double_ended_filter_map() { - let xs = [1i, 2, 3, 4, 5, 6]; - let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None }); - assert_eq!(it.next_back().unwrap(), 12); - assert_eq!(it.next_back().unwrap(), 8); - assert_eq!(it.next().unwrap(), 4); - assert_eq!(it.next_back(), None); - } - - #[test] - fn test_double_ended_chain() { - let xs = [1i, 2, 3, 4, 5]; - let ys = [7i, 9, 11]; - let mut it = xs.iter().chain(ys.iter()).rev(); - assert_eq!(it.next().unwrap(), &11) - assert_eq!(it.next().unwrap(), &9) - assert_eq!(it.next_back().unwrap(), &1) - assert_eq!(it.next_back().unwrap(), &2) - assert_eq!(it.next_back().unwrap(), &3) - assert_eq!(it.next_back().unwrap(), &4) - assert_eq!(it.next_back().unwrap(), &5) - assert_eq!(it.next_back().unwrap(), &7) - assert_eq!(it.next_back(), None) - } - - #[test] - fn test_rposition() { - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } - let v = [(0i, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - - assert_eq!(v.iter().rposition(f), Some(3u)); - assert!(v.iter().rposition(g).is_none()); - } - - #[test] - #[should_fail] - fn test_rposition_fail() { - let v = [(box 0i, box(GC) 0i), (box 0i, box(GC) 0i), - (box 0i, box(GC) 0i), (box 0i, box(GC) 0i)]; - let mut i = 0i; - v.iter().rposition(|_elt| { - if i == 2 { - fail!() - } - i += 1; - false - }); - } - - - #[cfg(test)] - fn check_randacc_iter>(a: T, len: uint) - { - let mut b = a.clone(); - assert_eq!(len, b.indexable()); - let mut n = 0u; - for (i, elt) in a.enumerate() { - assert!(Some(elt) == b.idx(i)); - n += 1; - } - assert_eq!(n, len); - assert!(None == b.idx(n)); - // call recursively to check after picking off an element - if len > 0 { - b.next(); - check_randacc_iter(b, len-1); - } - } - - - #[test] - fn test_double_ended_flat_map() { - let u = [0u,1]; - let v = [5u,6,7,8]; - let mut it = u.iter().flat_map(|x| v.slice(*x, v.len()).iter()); - assert_eq!(it.next_back().unwrap(), &8); - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.next_back().unwrap(), &7); - assert_eq!(it.next_back().unwrap(), &6); - assert_eq!(it.next_back().unwrap(), &8); - assert_eq!(it.next().unwrap(), &6); - assert_eq!(it.next_back().unwrap(), &7); - assert_eq!(it.next_back(), None); - assert_eq!(it.next(), None); - assert_eq!(it.next_back(), None); - } - - #[test] - fn test_random_access_chain() { - let xs = [1i, 2, 3, 4, 5]; - let ys = [7i, 9, 11]; - let mut it = xs.iter().chain(ys.iter()); - assert_eq!(it.idx(0).unwrap(), &1); - assert_eq!(it.idx(5).unwrap(), &7); - assert_eq!(it.idx(7).unwrap(), &11); - assert!(it.idx(8).is_none()); - - it.next(); - it.next(); - it.next_back(); - - assert_eq!(it.idx(0).unwrap(), &3); - assert_eq!(it.idx(4).unwrap(), &9); - assert!(it.idx(6).is_none()); - - check_randacc_iter(it, xs.len() + ys.len() - 3); - } - - #[test] - fn test_random_access_enumerate() { - let xs = [1i, 2, 3, 4, 5]; - check_randacc_iter(xs.iter().enumerate(), xs.len()); - } - - #[test] - fn test_random_access_rev() { - let xs = [1i, 2, 3, 4, 5]; - check_randacc_iter(xs.iter().rev(), xs.len()); - let mut it = xs.iter().rev(); - it.next(); - it.next_back(); - it.next(); - check_randacc_iter(it, xs.len() - 3); - } - - #[test] - fn test_random_access_zip() { - let xs = [1i, 2, 3, 4, 5]; - let ys = [7i, 9, 11]; - check_randacc_iter(xs.iter().zip(ys.iter()), cmp::min(xs.len(), ys.len())); - } - - #[test] - fn test_random_access_take() { - let xs = [1i, 2, 3, 4, 5]; - let empty: &[int] = []; - check_randacc_iter(xs.iter().take(3), 3); - check_randacc_iter(xs.iter().take(20), xs.len()); - check_randacc_iter(xs.iter().take(0), 0); - check_randacc_iter(empty.iter().take(2), 0); - } - - #[test] - fn test_random_access_skip() { - let xs = [1i, 2, 3, 4, 5]; - let empty: &[int] = []; - check_randacc_iter(xs.iter().skip(2), xs.len() - 2); - check_randacc_iter(empty.iter().skip(2), 0); - } - - #[test] - fn test_random_access_inspect() { - let xs = [1i, 2, 3, 4, 5]; - - // test .map and .inspect that don't implement Clone - let mut it = xs.iter().inspect(|_| {}); - assert_eq!(xs.len(), it.indexable()); - for (i, elt) in xs.iter().enumerate() { - assert_eq!(Some(elt), it.idx(i)); - } - - } - - #[test] - fn test_random_access_map() { - let xs = [1i, 2, 3, 4, 5]; - - let mut it = xs.iter().map(|x| *x); - assert_eq!(xs.len(), it.indexable()); - for (i, elt) in xs.iter().enumerate() { - assert_eq!(Some(*elt), it.idx(i)); - } - } - - #[test] - fn test_random_access_cycle() { - let xs = [1i, 2, 3, 4, 5]; - let empty: &[int] = []; - check_randacc_iter(xs.iter().cycle().take(27), 27); - check_randacc_iter(empty.iter().cycle(), 0); - } - - #[test] - fn test_double_ended_range() { - assert!(range(11i, 14).rev().collect::>() == vec![13i, 12, 11]); - for _ in range(10i, 0).rev() { - fail!("unreachable"); - } - - assert!(range(11u, 14).rev().collect::>() == vec![13u, 12, 11]); - for _ in range(10u, 0).rev() { - fail!("unreachable"); - } - } - - #[test] - fn test_range() { - /// A mock type to check Range when ToPrimitive returns None - struct Foo; - - impl ToPrimitive for Foo { - fn to_i64(&self) -> Option { None } - fn to_u64(&self) -> Option { None } - } - - impl Add for Foo { - fn add(&self, _: &Foo) -> Foo { - Foo - } - } - - impl PartialEq for Foo { - fn eq(&self, _: &Foo) -> bool { - true - } - } - - impl PartialOrd for Foo { - fn lt(&self, _: &Foo) -> bool { - false - } - } - - impl Clone for Foo { - fn clone(&self) -> Foo { - Foo - } - } - - impl Mul for Foo { - fn mul(&self, _: &Foo) -> Foo { - Foo - } - } - - impl num::One for Foo { - fn one() -> Foo { - Foo - } - } - - assert!(range(0i, 5).collect::>() == vec![0i, 1, 2, 3, 4]); - assert!(range(-10i, -1).collect::>() == - vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); - assert!(range(0i, 5).rev().collect::>() == vec![4, 3, 2, 1, 0]); - assert_eq!(range(200i, -5).count(), 0); - assert_eq!(range(200i, -5).rev().count(), 0); - assert_eq!(range(200i, 200).count(), 0); - assert_eq!(range(200i, 200).rev().count(), 0); - - assert_eq!(range(0i, 100).size_hint(), (100, Some(100))); - // this test is only meaningful when sizeof uint < sizeof u64 - assert_eq!(range(uint::MAX - 1, uint::MAX).size_hint(), (1, Some(1))); - assert_eq!(range(-10i, -1).size_hint(), (9, Some(9))); - assert_eq!(range(Foo, Foo).size_hint(), (0, None)); - } - - #[test] - fn test_range_inclusive() { - assert!(range_inclusive(0i, 5).collect::>() == - vec![0i, 1, 2, 3, 4, 5]); - assert!(range_inclusive(0i, 5).rev().collect::>() == - vec![5i, 4, 3, 2, 1, 0]); - assert_eq!(range_inclusive(200i, -5).count(), 0); - assert_eq!(range_inclusive(200i, -5).rev().count(), 0); - assert!(range_inclusive(200i, 200).collect::>() == vec![200]); - assert!(range_inclusive(200i, 200).rev().collect::>() == vec![200]); - } - - #[test] - fn test_range_step() { - assert!(range_step(0i, 20, 5).collect::>() == - vec![0, 5, 10, 15]); - assert!(range_step(20i, 0, -5).collect::>() == - vec![20, 15, 10, 5]); - assert!(range_step(20i, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(range_step(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(range_step(200i, -5, 1).collect::>() == vec![]); - assert!(range_step(200i, 200, 1).collect::>() == vec![]); - } - - #[test] - fn test_range_step_inclusive() { - assert!(range_step_inclusive(0i, 20, 5).collect::>() == - vec![0, 5, 10, 15, 20]); - assert!(range_step_inclusive(20i, 0, -5).collect::>() == - vec![20, 15, 10, 5, 0]); - assert!(range_step_inclusive(20i, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(range_step_inclusive(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(range_step_inclusive(200i, -5, 1).collect::>() == - vec![]); - assert!(range_step_inclusive(200i, 200, 1).collect::>() == - vec![200]); - } - - #[test] - fn test_reverse() { - let mut ys = [1i, 2, 3, 4, 5]; - ys.mut_iter().reverse_(); - assert!(ys == [5, 4, 3, 2, 1]); - } - - #[test] - fn test_peekable_is_empty() { - let a = [1i]; - let mut it = a.iter().peekable(); - assert!( !it.is_empty() ); - it.next(); - assert!( it.is_empty() ); - } - - #[test] - fn test_min_max() { - let v: [int, ..0] = []; - assert_eq!(v.iter().min_max(), NoElements); - - let v = [1i]; - assert!(v.iter().min_max() == OneElement(&1)); - - let v = [1i, 2, 3, 4, 5]; - assert!(v.iter().min_max() == MinMax(&1, &5)); - - let v = [1i, 2, 3, 4, 5, 6]; - assert!(v.iter().min_max() == MinMax(&1, &6)); - - let v = [1i, 1, 1, 1]; - assert!(v.iter().min_max() == MinMax(&1, &1)); - } - - #[test] - fn test_min_max_result() { - let r: MinMaxResult = NoElements; - assert_eq!(r.into_option(), None) - - let r = OneElement(1i); - assert_eq!(r.into_option(), Some((1,1))); - - let r = MinMax(1i,2); - assert_eq!(r.into_option(), Some((1,2))); - } -} diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index 40b716181e6fc..9a6cdb1c76976 100644 --- a/src/libcore/kinds.rs +++ b/src/libcore/kinds.rs @@ -155,7 +155,7 @@ pub mod marker { /// ``` /// use std::mem; /// - /// struct S { x: *() } + /// struct S { x: *const () } /// fn get(s: &S, v: T) { /// unsafe { /// let x: fn(T) = mem::transmute(s.x); diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 7d6d0d190370f..08153355e9e2d 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -43,7 +43,9 @@ //! the failure message, the file at which failure was invoked, and the line. //! It is up to consumers of this core library to define this failure //! function; it is only required to never return. -//! + +// Since libcore defines many fundamental lang items, all tests live in a +// separate crate, libcoretest, to avoid bizarre issues. #![crate_id = "core#0.11.0"] #![experimental] @@ -58,17 +60,6 @@ #![feature(globs, intrinsics, lang_items, macro_rules, managed_boxes, phase)] #![feature(simd, unsafe_destructor)] #![deny(missing_doc)] -#![allow(unknown_features)] // NOTE: remove after stage0 snapshot - -#[cfg(test)] extern crate realcore = "core"; -#[cfg(test)] extern crate libc; -#[cfg(test)] extern crate native; -#[cfg(test)] extern crate realstd = "std"; - -#[cfg(test)] pub use cmp = realcore::cmp; -#[cfg(test)] pub use kinds = realcore::kinds; -#[cfg(test)] pub use ops = realcore::ops; -#[cfg(test)] pub use ty = realcore::ty; mod macros; @@ -105,10 +96,10 @@ pub mod ptr; /* Core language traits */ -#[cfg(not(test))] pub mod kinds; -#[cfg(not(test))] pub mod ops; -#[cfg(not(test))] pub mod ty; -#[cfg(not(test))] pub mod cmp; +pub mod kinds; +pub mod ops; +pub mod ty; +pub mod cmp; pub mod clone; pub mod default; pub mod collections; @@ -145,11 +136,4 @@ mod std { pub use kinds; pub use option; pub use fmt; - - #[cfg(test)] pub use realstd::rt; // needed for fail!() - // #[cfg(test)] pub use realstd::option; // needed for fail!() - // #[cfg(test)] pub use realstd::fmt; // needed for fail!() - #[cfg(test)] pub use realstd::os; // needed for tests - #[cfg(test)] pub use realstd::slice; // needed for tests - #[cfg(test)] pub use realstd::vec; // needed for vec![] } diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index a62bc10d8abc6..93c838198c559 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -112,16 +112,6 @@ macro_rules! writeln( ) ) -#[cfg(test)] -macro_rules! vec( ($($e:expr),*) => ({ - let mut _v = ::std::vec::Vec::new(); - $(_v.push($e);)* - _v -}) ) - -#[cfg(test)] -macro_rules! format( ($($arg:tt)*) => (format_args!(::fmt::format, $($arg)*)) ) - /// Write some formatted data into a stream. /// /// Identical to the macro in `std::macros` diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index a2a3e09a93c07..06e28816c1cd5 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -363,7 +363,7 @@ pub unsafe fn forget(thing: T) { intrinsics::forget(thing) } #[inline] #[stable] pub unsafe fn transmute_copy(src: &T) -> U { - ptr::read(src as *T as *U) + ptr::read(src as *const T as *const U) } /// Transforms lifetime of the second pointer to match the first. @@ -382,182 +382,3 @@ pub unsafe fn copy_mut_lifetime<'a, S, T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T { transmute(ptr) } - -#[cfg(test)] -mod tests { - use mem::*; - use option::{Some,None}; - use realstd::str::StrAllocating; - use realstd::owned::Box; - use realstd::vec::Vec; - use raw; - - #[test] - fn size_of_basic() { - assert_eq!(size_of::(), 1u); - assert_eq!(size_of::(), 2u); - assert_eq!(size_of::(), 4u); - assert_eq!(size_of::(), 8u); - } - - #[test] - #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] - #[cfg(target_arch = "mips")] - #[cfg(target_arch = "mipsel")] - fn size_of_32() { - assert_eq!(size_of::(), 4u); - assert_eq!(size_of::<*uint>(), 4u); - } - - #[test] - #[cfg(target_arch = "x86_64")] - fn size_of_64() { - assert_eq!(size_of::(), 8u); - assert_eq!(size_of::<*uint>(), 8u); - } - - #[test] - fn size_of_val_basic() { - assert_eq!(size_of_val(&1u8), 1); - assert_eq!(size_of_val(&1u16), 2); - assert_eq!(size_of_val(&1u32), 4); - assert_eq!(size_of_val(&1u64), 8); - } - - #[test] - fn align_of_basic() { - assert_eq!(align_of::(), 1u); - assert_eq!(align_of::(), 2u); - assert_eq!(align_of::(), 4u); - } - - #[test] - #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] - #[cfg(target_arch = "mips")] - #[cfg(target_arch = "mipsel")] - fn align_of_32() { - assert_eq!(align_of::(), 4u); - assert_eq!(align_of::<*uint>(), 4u); - } - - #[test] - #[cfg(target_arch = "x86_64")] - fn align_of_64() { - assert_eq!(align_of::(), 8u); - assert_eq!(align_of::<*uint>(), 8u); - } - - #[test] - fn align_of_val_basic() { - assert_eq!(align_of_val(&1u8), 1u); - assert_eq!(align_of_val(&1u16), 2u); - assert_eq!(align_of_val(&1u32), 4u); - } - - #[test] - fn test_swap() { - let mut x = 31337i; - let mut y = 42i; - swap(&mut x, &mut y); - assert_eq!(x, 42); - assert_eq!(y, 31337); - } - - #[test] - fn test_replace() { - let mut x = Some("test".to_string()); - let y = replace(&mut x, None); - assert!(x.is_none()); - assert!(y.is_some()); - } - - #[test] - fn test_transmute_copy() { - assert_eq!(1u, unsafe { ::mem::transmute_copy(&1) }); - } - - #[test] - fn test_transmute() { - trait Foo {} - impl Foo for int {} - - let a = box 100i as Box; - unsafe { - let x: raw::TraitObject = transmute(a); - assert!(*(x.data as *int) == 100); - let _x: Box = transmute(x); - } - - unsafe { - assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); - } - } -} - -// FIXME #13642 (these benchmarks should be in another place) -/// Completely miscellaneous language-construct benchmarks. -#[cfg(test)] -mod bench { - extern crate test; - use self::test::Bencher; - use option::{Some,None}; - - // Static/dynamic method dispatch - - struct Struct { - field: int - } - - trait Trait { - fn method(&self) -> int; - } - - impl Trait for Struct { - fn method(&self) -> int { - self.field - } - } - - #[bench] - fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &Trait; - b.iter(|| { - t.method() - }); - } - - #[bench] - fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); - } - - // Overhead of various match forms - - #[bench] - fn match_option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| { - match x { - Some(y) => y, - None => 11 - } - }); - } - - #[bench] - fn match_vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; - b.iter(|| { - match x { - [1,2,3,..] => 10, - _ => 11 - } - }); - } -} diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index ef10c9abe1141..ff0494725f849 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -32,152 +32,4 @@ pub static MIN: $T = (-1 as $T) << (BITS - 1); #[unstable] pub static MAX: $T = !MIN; -#[cfg(test)] -mod tests { - use prelude::*; - use super::*; - - use int; - use num; - use num::CheckedDiv; - - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert!(MIN + MAX + 1 == 0); - } - - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); - } - - #[test] - pub fn test_abs() { - assert!((1 as $T).abs() == 1 as $T); - assert!((0 as $T).abs() == 0 as $T); - assert!((-1 as $T).abs() == 1 as $T); - } - - #[test] - fn test_abs_sub() { - assert!((-1 as $T).abs_sub(&(1 as $T)) == 0 as $T); - assert!((1 as $T).abs_sub(&(1 as $T)) == 0 as $T); - assert!((1 as $T).abs_sub(&(0 as $T)) == 1 as $T); - assert!((1 as $T).abs_sub(&(-1 as $T)) == 2 as $T); - } - - #[test] - fn test_signum() { - assert!((1 as $T).signum() == 1 as $T); - assert!((0 as $T).signum() == 0 as $T); - assert!((-0 as $T).signum() == 0 as $T); - assert!((-1 as $T).signum() == -1 as $T); - } - - #[test] - fn test_is_positive() { - assert!((1 as $T).is_positive()); - assert!(!(0 as $T).is_positive()); - assert!(!(-0 as $T).is_positive()); - assert!(!(-1 as $T).is_positive()); - } - - #[test] - fn test_is_negative() { - assert!(!(1 as $T).is_negative()); - assert!(!(0 as $T).is_negative()); - assert!(!(-0 as $T).is_negative()); - assert!((-1 as $T).is_negative()); - } - - #[test] - fn test_bitwise_operators() { - assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); - assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); - assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); - assert!(0b1110 as $T == (0b0111 as $T).shl(&(1 as $T))); - assert!(0b0111 as $T == (0b1110 as $T).shr(&(1 as $T))); - assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not()); - } - - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; - - static _0: $T = 0; - static _1: $T = !0; - - #[test] - fn test_count_ones() { - assert!(A.count_ones() == 3); - assert!(B.count_ones() == 2); - assert!(C.count_ones() == 5); - } - - #[test] - fn test_count_zeros() { - assert!(A.count_zeros() == BITS as $T - 3); - assert!(B.count_zeros() == BITS as $T - 2); - assert!(C.count_zeros() == BITS as $T - 5); - } - - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // Rotating these should make no difference - // - // We test using 124 bits because to ensure that overlong bit shifts do - // not cause undefined behaviour. See #10183. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - } - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_le() { - assert_eq!(Int::from_le(A.to_le()), A); - assert_eq!(Int::from_le(B.to_le()), B); - assert_eq!(Int::from_le(C.to_le()), C); - assert_eq!(Int::from_le(_0), _0); - assert_eq!(Int::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } - - #[test] - fn test_be() { - assert_eq!(Int::from_be(A.to_be()), A); - assert_eq!(Int::from_be(B.to_be()), B); - assert_eq!(Int::from_be(C.to_be()), C); - assert_eq!(Int::from_be(_0), _0); - assert_eq!(Int::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } - - #[test] - fn test_signed_checked_div() { - assert!(10i.checked_div(&2) == Some(5)); - assert!(5i.checked_div(&0) == None); - assert!(int::MIN.checked_div(&-1) == None); - } -} - )) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 512c107b930b6..b32e4167da1d4 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1375,22 +1375,6 @@ macro_rules! checkeddiv_uint_impl( checkeddiv_uint_impl!(uint u8 u16 u32 u64) -/// Helper function for testing numeric operations -#[cfg(test)] -pub fn test_num(ten: T, two: T) { - assert_eq!(ten.add(&two), cast(12i).unwrap()); - assert_eq!(ten.sub(&two), cast(8i).unwrap()); - assert_eq!(ten.mul(&two), cast(20i).unwrap()); - assert_eq!(ten.div(&two), cast(5i).unwrap()); - assert_eq!(ten.rem(&two), cast(0i).unwrap()); - - assert_eq!(ten.add(&two), ten + two); - assert_eq!(ten.sub(&two), ten - two); - assert_eq!(ten.mul(&two), ten * two); - assert_eq!(ten.div(&two), ten / two); - assert_eq!(ten.rem(&two), ten % two); -} - /// Used for representing the classification of floating point numbers #[deriving(PartialEq, Show)] pub enum FPCategory { diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 5828697ddad50..b0c570af04ac0 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -23,111 +23,4 @@ pub static MIN: $T = 0 as $T; #[unstable] pub static MAX: $T = 0 as $T - 1 as $T; -#[cfg(test)] -mod tests { - use prelude::*; - use super::*; - - use num; - use num::CheckedDiv; - - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert!(MIN + MAX + 1 == 0); - } - - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); - } - - #[test] - fn test_bitwise_operators() { - assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); - assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); - assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); - assert!(0b1110 as $T == (0b0111 as $T).shl(&(1 as $T))); - assert!(0b0111 as $T == (0b1110 as $T).shr(&(1 as $T))); - assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); - } - - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; - - static _0: $T = 0; - static _1: $T = !0; - - #[test] - fn test_count_ones() { - assert!(A.count_ones() == 3); - assert!(B.count_ones() == 2); - assert!(C.count_ones() == 5); - } - - #[test] - fn test_count_zeros() { - assert!(A.count_zeros() == BITS as $T - 3); - assert!(B.count_zeros() == BITS as $T - 2); - assert!(C.count_zeros() == BITS as $T - 5); - } - - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // Rotating these should make no difference - // - // We test using 124 bits because to ensure that overlong bit shifts do - // not cause undefined behaviour. See #10183. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - } - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_le() { - assert_eq!(Int::from_le(A.to_le()), A); - assert_eq!(Int::from_le(B.to_le()), B); - assert_eq!(Int::from_le(C.to_le()), C); - assert_eq!(Int::from_le(_0), _0); - assert_eq!(Int::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } - - #[test] - fn test_be() { - assert_eq!(Int::from_be(A.to_be()), A); - assert_eq!(Int::from_be(B.to_be()), B); - assert_eq!(Int::from_be(C.to_be()), C); - assert_eq!(Int::from_be(_0), _0); - assert_eq!(Int::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } - - #[test] - fn test_unsigned_checked_div() { - assert!(10u.checked_div(&2) == Some(5)); - assert!(5u.checked_div(&0) == None); - } -} - )) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 14edd7c70a8de..d42c09b8163dd 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -117,7 +117,6 @@ pub trait Add { macro_rules! add_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Add<$t, $t> for $t { #[inline] fn add(&self, other: &$t) -> $t { (*self) + (*other) } @@ -159,7 +158,6 @@ pub trait Sub { macro_rules! sub_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Sub<$t, $t> for $t { #[inline] fn sub(&self, other: &$t) -> $t { (*self) - (*other) } @@ -201,7 +199,6 @@ pub trait Mul { macro_rules! mul_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Mul<$t, $t> for $t { #[inline] fn mul(&self, other: &$t) -> $t { (*self) * (*other) } @@ -243,7 +240,6 @@ pub trait Div { macro_rules! div_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Div<$t, $t> for $t { #[inline] fn div(&self, other: &$t) -> $t { (*self) / (*other) } @@ -285,7 +281,6 @@ pub trait Rem { macro_rules! rem_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Rem<$t, $t> for $t { #[inline] fn rem(&self, other: &$t) -> $t { (*self) % (*other) } @@ -295,7 +290,6 @@ macro_rules! rem_impl( macro_rules! rem_float_impl( ($t:ty, $fmod:ident) => { - #[cfg(not(test))] impl Rem<$t, $t> for $t { #[inline] fn rem(&self, other: &$t) -> $t { @@ -342,7 +336,6 @@ pub trait Neg { macro_rules! neg_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Neg<$t> for $t { #[inline] fn neg(&self) -> $t { -*self } @@ -352,7 +345,6 @@ macro_rules! neg_impl( macro_rules! neg_uint_impl( ($t:ty, $t_signed:ty) => { - #[cfg(not(test))] impl Neg<$t> for $t { #[inline] fn neg(&self) -> $t { -(*self as $t_signed) as $t } @@ -402,7 +394,6 @@ pub trait Not { macro_rules! not_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl Not<$t> for $t { #[inline] fn not(&self) -> $t { !*self } @@ -444,7 +435,6 @@ pub trait BitAnd { macro_rules! bitand_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl BitAnd<$t, $t> for $t { #[inline] fn bitand(&self, rhs: &$t) -> $t { (*self) & (*rhs) } @@ -486,7 +476,6 @@ pub trait BitOr { macro_rules! bitor_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl BitOr<$t,$t> for $t { #[inline] fn bitor(&self, rhs: &$t) -> $t { (*self) | (*rhs) } @@ -528,7 +517,6 @@ pub trait BitXor { macro_rules! bitxor_impl( ($($t:ty)*) => ($( - #[cfg(not(test))] impl BitXor<$t, $t> for $t { #[inline] fn bitxor(&self, other: &$t) -> $t { (*self) ^ (*other) } @@ -570,12 +558,6 @@ pub trait Shl { macro_rules! shl_impl( ($($t:ty)*) => ($( - #[cfg(stage0)] - impl Shl<$t, $t> for $t { - #[inline] - fn shl(&self, other: &$t) -> $t { (*self) << (*other) } - } - #[cfg(not(stage0), not(test))] impl Shl<$t, $t> for $t { #[inline] fn shl(&self, other: &$t) -> $t { @@ -619,12 +601,6 @@ pub trait Shr { macro_rules! shr_impl( ($($t:ty)*) => ($( - #[cfg(stage0, not(test))] - impl Shr<$t, $t> for $t { - #[inline] - fn shr(&self, other: &$t) -> $t { (*self) >> (*other) } - } - #[cfg(not(stage0), not(test))] impl Shr<$t, $t> for $t { #[inline] fn shr(&self, other: &$t) -> $t { (*self) >> (*other as uint) } @@ -758,28 +734,3 @@ pub trait FnOnce { /// This is called when the call operator is used. fn call_once(self, args: Args) -> Result; } - -#[cfg(test)] -mod bench { - extern crate test; - use self::test::Bencher; - use ops::Drop; - - // Overhead of dtors - - struct HasDtor { - x: int - } - - impl Drop for HasDtor { - fn drop(&mut self) { - } - } - - #[bench] - fn alloc_obj_with_dtor(b: &mut Bencher) { - b.iter(|| { - HasDtor { x : 10 }; - }) - } -} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index e9fb7c3dae3c9..b8612ed93e02d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -587,310 +587,34 @@ impl ExactSize for Item {} /// ``` #[inline] pub fn collect>, V: FromIterator>(iter: Iter) -> Option { - // FIXME(#11084): This should be twice as fast once this bug is closed. - let mut iter = iter.scan(false, |state, x| { - match x { - Some(x) => Some(x), - None => { - *state = true; - None + // FIXME(#11084): This could be replaced with Iterator::scan when this + // performance bug is closed. + + struct Adapter { + iter: Iter, + found_none: bool, + } + + impl>> Iterator for Adapter { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Some(value)) => Some(value), + Some(None) => { + self.found_none = true; + None + } + None => None, } } - }); + } - let v: V = FromIterator::from_iter(iter.by_ref()); + let mut adapter = Adapter { iter: iter, found_none: false }; + let v: V = FromIterator::from_iter(adapter.by_ref()); - if iter.state { + if adapter.found_none { None } else { Some(v) } } - -///////////////////////////////////////////////////////////////////////////// -// Tests -///////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use realstd::vec::Vec; - use realstd::string::String; - use option::collect; - use prelude::*; - use realstd::str::{Str, StrAllocating}; - use iter::range; - - use str::StrSlice; - use kinds::marker; - use slice::ImmutableVector; - - #[test] - fn test_get_ptr() { - unsafe { - let x = box 0; - let addr_x: *int = ::mem::transmute(&*x); - let opt = Some(x); - let y = opt.unwrap(); - let addr_y: *int = ::mem::transmute(&*y); - assert_eq!(addr_x, addr_y); - } - } - - #[test] - fn test_get_str() { - let x = "test".to_string(); - let addr_x = x.as_slice().as_ptr(); - let opt = Some(x); - let y = opt.unwrap(); - let addr_y = y.as_slice().as_ptr(); - assert_eq!(addr_x, addr_y); - } - - #[test] - fn test_get_resource() { - use realstd::rc::Rc; - use cell::RefCell; - - struct R { - i: Rc>, - } - - #[unsafe_destructor] - impl ::ops::Drop for R { - fn drop(&mut self) { - let ii = &*self.i; - let i = *ii.borrow(); - *ii.borrow_mut() = i + 1; - } - } - - fn r(i: Rc>) -> R { - R { - i: i - } - } - - fn realclone(t: &T) -> T { - use realstd::clone::Clone; - t.clone() - } - - let i = Rc::new(RefCell::new(0i)); - { - let x = r(realclone(&i)); - let opt = Some(x); - let _y = opt.unwrap(); - } - assert_eq!(*i.borrow(), 1); - } - - #[test] - fn test_option_dance() { - let x = Some(()); - let mut y = Some(5i); - let mut y2 = 0; - for _x in x.iter() { - y2 = y.take_unwrap(); - } - assert_eq!(y2, 5); - assert!(y.is_none()); - } - - #[test] #[should_fail] - fn test_option_too_much_dance() { - let mut y = Some(marker::NoCopy); - let _y2 = y.take_unwrap(); - let _y3 = y.take_unwrap(); - } - - #[test] - fn test_and() { - let x: Option = Some(1i); - assert_eq!(x.and(Some(2i)), Some(2)); - assert_eq!(x.and(None::), None); - - let x: Option = None; - assert_eq!(x.and(Some(2i)), None); - assert_eq!(x.and(None::), None); - } - - #[test] - fn test_and_then() { - let x: Option = Some(1); - assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); - assert_eq!(x.and_then(|_| None::), None); - - let x: Option = None; - assert_eq!(x.and_then(|x| Some(x + 1)), None); - assert_eq!(x.and_then(|_| None::), None); - } - - #[test] - fn test_or() { - let x: Option = Some(1); - assert_eq!(x.or(Some(2)), Some(1)); - assert_eq!(x.or(None), Some(1)); - - let x: Option = None; - assert_eq!(x.or(Some(2)), Some(2)); - assert_eq!(x.or(None), None); - } - - #[test] - fn test_or_else() { - let x: Option = Some(1); - assert_eq!(x.or_else(|| Some(2)), Some(1)); - assert_eq!(x.or_else(|| None), Some(1)); - - let x: Option = None; - assert_eq!(x.or_else(|| Some(2)), Some(2)); - assert_eq!(x.or_else(|| None), None); - } - - #[test] - fn test_option_while_some() { - let mut i = 0i; - Some(10).while_some(|j| { - i += 1; - if j > 0 { - Some(j-1) - } else { - None - } - }); - assert_eq!(i, 11); - } - - #[test] - fn test_unwrap() { - assert_eq!(Some(1i).unwrap(), 1); - let s = Some("hello".to_string()).unwrap(); - assert_eq!(s.as_slice(), "hello"); - } - - #[test] - #[should_fail] - fn test_unwrap_fail1() { - let x: Option = None; - x.unwrap(); - } - - #[test] - #[should_fail] - fn test_unwrap_fail2() { - let x: Option = None; - x.unwrap(); - } - - #[test] - fn test_unwrap_or() { - let x: Option = Some(1); - assert_eq!(x.unwrap_or(2), 1); - - let x: Option = None; - assert_eq!(x.unwrap_or(2), 2); - } - - #[test] - fn test_unwrap_or_else() { - let x: Option = Some(1); - assert_eq!(x.unwrap_or_else(|| 2), 1); - - let x: Option = None; - assert_eq!(x.unwrap_or_else(|| 2), 2); - } - - #[test] - fn test_filtered() { - let some_stuff = Some(42i); - let modified_stuff = some_stuff.filtered(|&x| {x < 10}); - assert_eq!(some_stuff.unwrap(), 42); - assert!(modified_stuff.is_none()); - } - - #[test] - fn test_iter() { - let val = 5i; - - let x = Some(val); - let mut it = x.iter(); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next(), Some(&val)); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_mut_iter() { - let val = 5i; - let new_val = 11i; - - let mut x = Some(val); - { - let mut it = x.mut_iter(); - - assert_eq!(it.size_hint(), (1, Some(1))); - - match it.next() { - Some(interior) => { - assert_eq!(*interior, val); - *interior = new_val; - } - None => assert!(false), - } - - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - assert_eq!(x, Some(new_val)); - } - - #[test] - fn test_ord() { - let small = Some(1.0f64); - let big = Some(5.0f64); - let nan = Some(0.0f64/0.0); - assert!(!(nan < big)); - assert!(!(nan > big)); - assert!(small < big); - assert!(None < big); - assert!(big > None); - } - - #[test] - fn test_mutate() { - let mut x = Some(3i); - assert!(x.mutate(|i| i+1)); - assert_eq!(x, Some(4i)); - assert!(x.mutate_or_set(0, |i| i+1)); - assert_eq!(x, Some(5i)); - x = None; - assert!(!x.mutate(|i| i+1)); - assert_eq!(x, None); - assert!(!x.mutate_or_set(0i, |i| i+1)); - assert_eq!(x, Some(0i)); - } - - #[test] - fn test_collect() { - let v: Option> = collect(range(0i, 0) - .map(|_| Some(0i))); - assert!(v == Some(vec![])); - - let v: Option> = collect(range(0i, 3) - .map(|x| Some(x))); - assert!(v == Some(vec![0, 1, 2])); - - let v: Option> = collect(range(0i, 3) - .map(|x| if x > 1 { None } else { Some(x) })); - assert!(v == None); - - // test that it does not take more elements than it needs - let mut functions = [|| Some(()), || None, || fail!()]; - - let v: Option> = collect(functions.mut_iter().map(|f| (*f)())); - - assert!(v == None); - } -} diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 59d7bbfe52dc4..093591cd796d1 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -10,7 +10,7 @@ // FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory -//! Operations on unsafe pointers, `*T`, and `*mut T`. +//! Operations on unsafe pointers, `*const T`, and `*mut T`. //! //! Working with unsafe pointers in Rust is uncommon, //! typically limited to a few patterns. @@ -29,7 +29,7 @@ //! //! ``` //! let my_num: int = 10; -//! let my_num_ptr: *int = &my_num; +//! let my_num_ptr: *const int = &my_num; //! let mut my_speed: int = 88; //! let my_speed_ptr: *mut int = &mut my_speed; //! ``` @@ -42,7 +42,7 @@ //! //! The `transmute` function takes, by value, whatever it's given //! and returns it as whatever type is requested, as long as the -//! types are the same size. Because `Box` and `*T` have the same +//! types are the same size. Because `Box` and `*mut T` have the same //! representation they can be trivially, //! though unsafely, transformed from one type to the other. //! @@ -51,7 +51,7 @@ //! //! unsafe { //! let my_num: Box = box 10; -//! let my_num: *int = mem::transmute(my_num); +//! let my_num: *const int = mem::transmute(my_num); //! let my_speed: Box = box 88; //! let my_speed: *mut int = mem::transmute(my_speed); //! @@ -93,7 +93,7 @@ use intrinsics; use iter::{range, Iterator}; use option::{Some, None, Option}; -#[cfg(not(test))] use cmp::{PartialEq, Eq, PartialOrd, Equiv}; +use cmp::{PartialEq, Eq, PartialOrd, Equiv, Ordering, Less, Equal, Greater}; /// Create a null pointer. /// @@ -102,12 +102,12 @@ use option::{Some, None, Option}; /// ``` /// use std::ptr; /// -/// let p: *int = ptr::null(); +/// let p: *const int = ptr::null(); /// assert!(p.is_null()); /// ``` #[inline] #[unstable = "may need a different name after pending changes to pointer types"] -pub fn null() -> *T { 0 as *T } +pub fn null() -> *const T { 0 as *const T } /// Create an unsafe mutable null pointer. /// @@ -137,7 +137,7 @@ pub fn mut_null() -> *mut T { 0 as *mut T } /// ``` /// use std::ptr; /// -/// unsafe fn from_buf_raw(ptr: *T, elts: uint) -> Vec { +/// unsafe fn from_buf_raw(ptr: *const T, elts: uint) -> Vec { /// let mut dst = Vec::with_capacity(elts); /// dst.set_len(elts); /// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); @@ -147,7 +147,7 @@ pub fn mut_null() -> *mut T { 0 as *mut T } /// #[inline] #[unstable] -pub unsafe fn copy_memory(dst: *mut T, src: *T, count: uint) { +pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { intrinsics::copy_memory(dst, src, count) } @@ -190,7 +190,7 @@ pub unsafe fn copy_memory(dst: *mut T, src: *T, count: uint) { #[inline] #[unstable] pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, - src: *T, + src: *const T, count: uint) { intrinsics::copy_nonoverlapping_memory(dst, src, count) } @@ -242,7 +242,7 @@ pub unsafe fn replace(dest: *mut T, mut src: T) -> T { /// Reads the value from `*src` and returns it. #[inline(always)] #[unstable] -pub unsafe fn read(src: *T) -> T { +pub unsafe fn read(src: *const T) -> T { let mut tmp: T = mem::uninitialized(); copy_nonoverlapping_memory(&mut tmp, src, 1); tmp @@ -275,11 +275,12 @@ pub unsafe fn write(dst: *mut T, src: T) { intrinsics::move_val_init(&mut *dst, src) } -/// Given a **T (pointer to an array of pointers), -/// iterate through each *T, up to the provided `len`, +/// Given a *const *const T (pointer to an array of pointers), +/// iterate through each *const T, up to the provided `len`, /// passing to the provided callback function #[deprecated = "old-style iteration. use a loop and RawPtr::offset"] -pub unsafe fn array_each_with_len(arr: **T, len: uint, cb: |*T|) { +pub unsafe fn array_each_with_len(arr: *const *const T, len: uint, + cb: |*const T|) { if arr.is_null() { fail!("ptr::array_each_with_len failure: arr input is null pointer"); } @@ -290,8 +291,8 @@ pub unsafe fn array_each_with_len(arr: **T, len: uint, cb: |*T|) { } } -/// Given a null-pointer-terminated **T (pointer to -/// an array of pointers), iterate through each *T, +/// Given a null-pointer-terminated *const *const T (pointer to +/// an array of pointers), iterate through each *const T, /// passing to the provided callback function /// /// # Safety Note @@ -300,7 +301,7 @@ pub unsafe fn array_each_with_len(arr: **T, len: uint, cb: |*T|) { /// pointer array. #[deprecated = "old-style iteration. use a loop and RawPtr::offset"] #[allow(deprecated)] -pub unsafe fn array_each(arr: **T, cb: |*T|) { +pub unsafe fn array_each(arr: *const *const T, cb: |*const T|) { if arr.is_null() { fail!("ptr::array_each_with_len failure: arr input is null pointer"); } @@ -312,14 +313,14 @@ pub unsafe fn array_each(arr: **T, cb: |*T|) { #[inline] #[deprecated = "use a loop and RawPtr::offset"] #[allow(deprecated)] -pub unsafe fn buf_len(buf: **T) -> uint { +pub unsafe fn buf_len(buf: *const *const T) -> uint { position(buf, |i| *i == null()) } /// Return the first offset `i` such that `f(buf[i]) == true`. #[inline] #[deprecated = "old-style iteration. use a loop and RawPtr::offset"] -pub unsafe fn position(buf: *T, f: |&T| -> bool) -> uint { +pub unsafe fn position(buf: *const T, f: |&T| -> bool) -> uint { let mut i = 0; loop { if f(&(*buf.offset(i as int))) { return i; } @@ -352,9 +353,9 @@ pub trait RawPtr { unsafe fn offset(self, count: int) -> Self; } -impl RawPtr for *T { +impl RawPtr for *const T { #[inline] - fn null() -> *T { null() } + fn null() -> *const T { null() } #[inline] fn is_null(&self) -> bool { *self == RawPtr::null() } @@ -363,7 +364,9 @@ impl RawPtr for *T { fn to_uint(&self) -> uint { *self as uint } #[inline] - unsafe fn offset(self, count: int) -> *T { intrinsics::offset(self, count) } + unsafe fn offset(self, count: int) -> *const T { + intrinsics::offset(self, count) + } #[inline] unsafe fn to_option(&self) -> Option<&T> { @@ -387,7 +390,7 @@ impl RawPtr for *mut T { #[inline] unsafe fn offset(self, count: int) -> *mut T { - intrinsics::offset(self as *T, count) as *mut T + intrinsics::offset(self as *const T, count) as *mut T } #[inline] @@ -401,20 +404,17 @@ impl RawPtr for *mut T { } // Equality for pointers -#[cfg(not(test))] -impl PartialEq for *T { +impl PartialEq for *const T { #[inline] - fn eq(&self, other: &*T) -> bool { + fn eq(&self, other: &*const T) -> bool { *self == *other } #[inline] - fn ne(&self, other: &*T) -> bool { !self.eq(other) } + fn ne(&self, other: &*const T) -> bool { !self.eq(other) } } -#[cfg(not(test))] -impl Eq for *T {} +impl Eq for *const T {} -#[cfg(not(test))] impl PartialEq for *mut T { #[inline] fn eq(&self, other: &*mut T) -> bool { @@ -424,27 +424,24 @@ impl PartialEq for *mut T { fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } } -#[cfg(not(test))] impl Eq for *mut T {} // Equivalence for pointers -#[cfg(not(test))] -impl Equiv<*mut T> for *T { +impl Equiv<*mut T> for *const T { fn equiv(&self, other: &*mut T) -> bool { self.to_uint() == other.to_uint() } } -#[cfg(not(test))] -impl Equiv<*T> for *mut T { - fn equiv(&self, other: &*T) -> bool { +impl Equiv<*const T> for *mut T { + fn equiv(&self, other: &*const T) -> bool { self.to_uint() == other.to_uint() } } -impl Clone for *T { +impl Clone for *const T { #[inline] - fn clone(&self) -> *T { + fn clone(&self) -> *const T { *self } } @@ -457,7 +454,6 @@ impl Clone for *mut T { } // Equality for extern "C" fn pointers -#[cfg(not(test))] mod externfnpointers { use mem; use cmp::PartialEq; @@ -465,8 +461,8 @@ mod externfnpointers { impl<_R> PartialEq for extern "C" fn() -> _R { #[inline] fn eq(&self, other: &extern "C" fn() -> _R) -> bool { - let self_: *() = unsafe { mem::transmute(*self) }; - let other_: *() = unsafe { mem::transmute(*other) }; + let self_: *const () = unsafe { mem::transmute(*self) }; + let other_: *const () = unsafe { mem::transmute(*other) }; self_ == other_ } } @@ -475,8 +471,9 @@ mod externfnpointers { impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R { #[inline] fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool { - let self_: *() = unsafe { mem::transmute(*self) }; - let other_: *() = unsafe { mem::transmute(*other) }; + let self_: *const () = unsafe { mem::transmute(*self) }; + + let other_: *const () = unsafe { mem::transmute(*other) }; self_ == other_ } } @@ -490,274 +487,52 @@ mod externfnpointers { } // Comparison for pointers -#[cfg(not(test))] -impl PartialOrd for *T { - #[inline] - fn lt(&self, other: &*T) -> bool { *self < *other } -} - -#[cfg(not(test))] -impl PartialOrd for *mut T { +impl PartialOrd for *const T { #[inline] - fn lt(&self, other: &*mut T) -> bool { *self < *other } -} - -#[cfg(test)] -#[allow(deprecated, experimental)] -pub mod test { - use super::*; - use prelude::*; - - use realstd::c_str::ToCStr; - use mem; - use libc; - use realstd::str; - use realstd::str::Str; - use realstd::vec::Vec; - use realstd::collections::Collection; - use slice::{ImmutableVector, MutableVector}; - - #[test] - fn test() { - unsafe { - struct Pair { - fst: int, - snd: int - }; - let mut p = Pair {fst: 10, snd: 20}; - let pptr: *mut Pair = &mut p; - let iptr: *mut int = mem::transmute(pptr); - assert_eq!(*iptr, 10); - *iptr = 30; - assert_eq!(*iptr, 30); - assert_eq!(p.fst, 30); - - *pptr = Pair {fst: 50, snd: 60}; - assert_eq!(*iptr, 50); - assert_eq!(p.fst, 50); - assert_eq!(p.snd, 60); - - let v0 = vec![32000u16, 32001u16, 32002u16]; - let mut v1 = vec![0u16, 0u16, 0u16]; - - copy_memory(v1.as_mut_ptr().offset(1), - v0.as_ptr().offset(1), 1); - assert!((*v1.get(0) == 0u16 && - *v1.get(1) == 32001u16 && - *v1.get(2) == 0u16)); - copy_memory(v1.as_mut_ptr(), - v0.as_ptr().offset(2), 1); - assert!((*v1.get(0) == 32002u16 && - *v1.get(1) == 32001u16 && - *v1.get(2) == 0u16)); - copy_memory(v1.as_mut_ptr().offset(2), - v0.as_ptr(), 1u); - assert!((*v1.get(0) == 32002u16 && - *v1.get(1) == 32001u16 && - *v1.get(2) == 32000u16)); - } - } - - #[test] - fn test_position() { - use libc::c_char; - - "hello".with_c_str(|p| { - unsafe { - assert!(2u == position(p, |c| *c == 'l' as c_char)); - assert!(4u == position(p, |c| *c == 'o' as c_char)); - assert!(5u == position(p, |c| *c == 0 as c_char)); - } - }) - } - - #[test] - fn test_buf_len() { - "hello".with_c_str(|p0| { - "there".with_c_str(|p1| { - "thing".with_c_str(|p2| { - let v = vec![p0, p1, p2, null()]; - unsafe { - assert_eq!(buf_len(v.as_ptr()), 3u); - } - }) - }) - }) - } - - #[test] - fn test_is_null() { - let p: *int = null(); - assert!(p.is_null()); - assert!(!p.is_not_null()); - - let q = unsafe { p.offset(1) }; - assert!(!q.is_null()); - assert!(q.is_not_null()); - - let mp: *mut int = mut_null(); - assert!(mp.is_null()); - assert!(!mp.is_not_null()); - - let mq = unsafe { mp.offset(1) }; - assert!(!mq.is_null()); - assert!(mq.is_not_null()); - } - - #[test] - fn test_to_option() { - unsafe { - let p: *int = null(); - assert_eq!(p.to_option(), None); - - let q: *int = &2; - assert_eq!(q.to_option().unwrap(), &2); - - let p: *mut int = mut_null(); - assert_eq!(p.to_option(), None); - - let q: *mut int = &mut 2; - assert_eq!(q.to_option().unwrap(), &2); - } - } - - #[test] - fn test_ptr_addition() { - unsafe { - let xs = Vec::from_elem(16, 5i); - let mut ptr = xs.as_ptr(); - let end = ptr.offset(16); - - while ptr < end { - assert_eq!(*ptr, 5); - ptr = ptr.offset(1); - } - - let mut xs_mut = xs; - let mut m_ptr = xs_mut.as_mut_ptr(); - let m_end = m_ptr.offset(16); - - while m_ptr < m_end { - *m_ptr += 5; - m_ptr = m_ptr.offset(1); - } - - assert!(xs_mut == Vec::from_elem(16, 10i)); + fn partial_cmp(&self, other: &*const T) -> Option { + if self < other { + Some(Less) + } else if self == other { + Some(Equal) + } else { + Some(Greater) } } - #[test] - fn test_ptr_subtraction() { - unsafe { - let xs = vec![0,1,2,3,4,5,6,7,8,9]; - let mut idx = 9i8; - let ptr = xs.as_ptr(); + #[inline] + fn lt(&self, other: &*const T) -> bool { *self < *other } - while idx >= 0i8 { - assert_eq!(*(ptr.offset(idx as int)), idx as int); - idx = idx - 1i8; - } + #[inline] + fn le(&self, other: &*const T) -> bool { *self <= *other } - let mut xs_mut = xs; - let m_start = xs_mut.as_mut_ptr(); - let mut m_ptr = m_start.offset(9); + #[inline] + fn gt(&self, other: &*const T) -> bool { *self > *other } - while m_ptr >= m_start { - *m_ptr += *m_ptr; - m_ptr = m_ptr.offset(-1); - } + #[inline] + fn ge(&self, other: &*const T) -> bool { *self >= *other } +} - assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]); +impl PartialOrd for *mut T { + #[inline] + fn partial_cmp(&self, other: &*mut T) -> Option { + if self < other { + Some(Less) + } else if self == other { + Some(Equal) + } else { + Some(Greater) } } - #[test] - fn test_ptr_array_each_with_len() { - unsafe { - let one = "oneOne".to_c_str(); - let two = "twoTwo".to_c_str(); - let three = "threeThree".to_c_str(); - let arr = vec![ - one.with_ref(|buf| buf), - two.with_ref(|buf| buf), - three.with_ref(|buf| buf) - ]; - let expected_arr = [ - one, two, three - ]; - - let mut ctr = 0; - let mut iteration_count = 0; - array_each_with_len(arr.as_ptr(), arr.len(), |e| { - let actual = str::raw::from_c_str(e); - let expected = expected_arr[ctr].with_ref(|buf| { - str::raw::from_c_str(buf) - }); - assert_eq!(actual.as_slice(), expected.as_slice()); - ctr += 1; - iteration_count += 1; - }); - assert_eq!(iteration_count, 3u); - } - } + #[inline] + fn lt(&self, other: &*mut T) -> bool { *self < *other } - #[test] - fn test_ptr_array_each() { - unsafe { - let one = "oneOne".to_c_str(); - let two = "twoTwo".to_c_str(); - let three = "threeThree".to_c_str(); - let arr = vec![ - one.with_ref(|buf| buf), - two.with_ref(|buf| buf), - three.with_ref(|buf| buf), - // fake a null terminator - null() - ]; - let expected_arr = [ - one, two, three - ]; - - let arr_ptr = arr.as_ptr(); - let mut ctr = 0u; - let mut iteration_count = 0u; - array_each(arr_ptr, |e| { - let actual = str::raw::from_c_str(e); - let expected = expected_arr[ctr].with_ref(|buf| { - str::raw::from_c_str(buf) - }); - assert_eq!(actual.as_slice(), expected.as_slice()); - ctr += 1; - iteration_count += 1; - }); - assert_eq!(iteration_count, 3); - } - } + #[inline] + fn le(&self, other: &*mut T) -> bool { *self <= *other } - #[test] - #[should_fail] - fn test_ptr_array_each_with_len_null_ptr() { - unsafe { - array_each_with_len(0 as **libc::c_char, 1, |e| { - str::raw::from_c_str(e); - }); - } - } - #[test] - #[should_fail] - fn test_ptr_array_each_null_ptr() { - unsafe { - array_each(0 as **libc::c_char, |e| { - str::raw::from_c_str(e); - }); - } - } + #[inline] + fn gt(&self, other: &*mut T) -> bool { *self > *other } - #[test] - fn test_set_memory() { - let mut xs = [0u8, ..20]; - let ptr = xs.as_mut_ptr(); - unsafe { set_memory(ptr, 5u8, xs.len()); } - assert!(xs == [5u8, ..20]); - } + #[inline] + fn ge(&self, other: &*mut T) -> bool { *self >= *other } } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 0a2a756c6b1c2..da9fab0fc6f50 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -31,20 +31,20 @@ pub struct Box { /// The representation of a Rust slice pub struct Slice { - pub data: *T, + pub data: *const T, pub len: uint, } /// The representation of a Rust closure pub struct Closure { - pub code: *(), - pub env: *(), + pub code: *mut (), + pub env: *mut (), } /// The representation of a Rust procedure (`proc()`) pub struct Procedure { - pub code: *(), - pub env: *(), + pub code: *mut (), + pub env: *mut (), } /// The representation of a Rust trait object. @@ -52,8 +52,8 @@ pub struct Procedure { /// This struct does not have a `Repr` implementation /// because there is no way to refer to all trait objects generically. pub struct TraitObject { - pub vtable: *(), - pub data: *(), + pub vtable: *mut (), + pub data: *mut (), } /// This trait is meant to map equivalences between raw structs and their @@ -70,32 +70,3 @@ pub trait Repr { impl<'a, T> Repr> for &'a [T] {} impl<'a> Repr> for &'a str {} -#[cfg(test)] -mod tests { - use super::*; - - use mem; - - #[test] - fn synthesize_closure() { - unsafe { - let x = 10; - let f: |int| -> int = |y| x + y; - - assert_eq!(f(20), 30); - - let original_closure: Closure = mem::transmute(f); - - let actual_function_pointer = original_closure.code; - let environment = original_closure.env; - - let new_closure = Closure { - code: actual_function_pointer, - env: environment - }; - - let new_f: |int| -> int = mem::transmute(new_closure); - assert_eq!(new_f(20), 30); - } - } -} diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 6c163b7919920..5cbbf30cd3607 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -585,20 +585,32 @@ impl Result { /// ``` #[inline] pub fn collect>, V: FromIterator>(iter: Iter) -> Result { - // FIXME(#11084): This should be twice as fast once this bug is closed. - let mut iter = iter.scan(None, |state, x| { - match x { - Ok(x) => Some(x), - Err(err) => { - *state = Some(err); - None + // FIXME(#11084): This could be replaced with Iterator::scan when this + // performance bug is closed. + + struct Adapter { + iter: Iter, + err: Option, + } + + impl>> Iterator for Adapter { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Ok(value)) => Some(value), + Some(Err(err)) => { + self.err = Some(err); + None + } + None => None, } } - }); + } - let v: V = FromIterator::from_iter(iter.by_ref()); + let mut adapter = Adapter { iter: iter, err: None }; + let v: V = FromIterator::from_iter(adapter.by_ref()); - match iter.state { + match adapter.err { Some(err) => Err(err), None => Ok(v), } @@ -635,166 +647,3 @@ pub fn fold>>(iterator: Iter) -> Result<(),E> { fold(iterator, (), |_, _| ()) } - -///////////////////////////////////////////////////////////////////////////// -// Tests -///////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use realstd::vec::Vec; - - use result::{collect, fold, fold_}; - use prelude::*; - use realstd::str::Str; - use iter::range; - - pub fn op1() -> Result { Ok(666) } - pub fn op2() -> Result { Err("sadface") } - - #[test] - pub fn test_and() { - assert_eq!(op1().and(Ok(667i)).unwrap(), 667); - assert_eq!(op1().and(Err::<(), &'static str>("bad")).unwrap_err(), - "bad"); - - assert_eq!(op2().and(Ok(667i)).unwrap_err(), "sadface"); - assert_eq!(op2().and(Err::<(),&'static str>("bad")).unwrap_err(), - "sadface"); - } - - #[test] - pub fn test_and_then() { - assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); - assert_eq!(op1().and_then(|_| Err::("bad")).unwrap_err(), - "bad"); - - assert_eq!(op2().and_then(|i| Ok::(i + 1)).unwrap_err(), - "sadface"); - assert_eq!(op2().and_then(|_| Err::("bad")).unwrap_err(), - "sadface"); - } - - #[test] - pub fn test_or() { - assert_eq!(op1().or(Ok(667)).unwrap(), 666); - assert_eq!(op1().or(Err("bad")).unwrap(), 666); - - assert_eq!(op2().or(Ok(667)).unwrap(), 667); - assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad"); - } - - #[test] - pub fn test_or_else() { - assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), 666); - assert_eq!(op1().or_else(|e| Err::(e)).unwrap(), 666); - - assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), 667); - assert_eq!(op2().or_else(|e| Err::(e)).unwrap_err(), - "sadface"); - } - - #[test] - pub fn test_impl_map() { - assert!(Ok::(1).map(|x| x + 1) == Ok(2)); - assert!(Err::(1).map(|x| x + 1) == Err(1)); - } - - #[test] - pub fn test_impl_map_err() { - assert!(Ok::(1).map_err(|x| x + 1) == Ok(1)); - assert!(Err::(1).map_err(|x| x + 1) == Err(2)); - } - - #[test] - fn test_collect() { - let v: Result, ()> = collect(range(0i, 0).map(|_| Ok::(0))); - assert!(v == Ok(vec![])); - - let v: Result, ()> = collect(range(0i, 3).map(|x| Ok::(x))); - assert!(v == Ok(vec![0, 1, 2])); - - let v: Result, int> = collect(range(0i, 3) - .map(|x| if x > 1 { Err(x) } else { Ok(x) })); - assert!(v == Err(2)); - - // test that it does not take more elements than it needs - let mut functions = [|| Ok(()), || Err(1i), || fail!()]; - - let v: Result, int> = collect(functions.mut_iter().map(|f| (*f)())); - assert!(v == Err(1)); - } - - #[test] - fn test_fold() { - assert_eq!(fold_(range(0i, 0) - .map(|_| Ok::<(), ()>(()))), - Ok(())); - assert_eq!(fold(range(0i, 3) - .map(|x| Ok::(x)), - 0, |a, b| a + b), - Ok(3)); - assert_eq!(fold_(range(0i, 3) - .map(|x| if x > 1 { Err(x) } else { Ok(()) })), - Err(2)); - - // test that it does not take more elements than it needs - let mut functions = [|| Ok(()), || Err(1i), || fail!()]; - - assert_eq!(fold_(functions.mut_iter() - .map(|f| (*f)())), - Err(1)); - } - - #[test] - pub fn test_fmt_default() { - let ok: Result = Ok(100); - let err: Result = Err("Err"); - - let s = format!("{}", ok); - assert_eq!(s.as_slice(), "Ok(100)"); - let s = format!("{}", err); - assert_eq!(s.as_slice(), "Err(Err)"); - } - - #[test] - pub fn test_unwrap_or() { - let ok: Result = Ok(100i); - let ok_err: Result = Err("Err"); - - assert_eq!(ok.unwrap_or(50), 100); - assert_eq!(ok_err.unwrap_or(50), 50); - } - - #[test] - pub fn test_unwrap_or_else() { - fn handler(msg: &'static str) -> int { - if msg == "I got this." { - 50i - } else { - fail!("BadBad") - } - } - - let ok: Result = Ok(100); - let ok_err: Result = Err("I got this."); - - assert_eq!(ok.unwrap_or_else(handler), 100); - assert_eq!(ok_err.unwrap_or_else(handler), 50); - } - - #[test] - #[should_fail] - pub fn test_unwrap_or_else_failure() { - fn handler(msg: &'static str) -> int { - if msg == "I got this." { - 50i - } else { - fail!("BadBad") - } - } - - let bad_err: Result = Err("Unrecoverable mess."); - let _ : int = bad_err.unwrap_or_else(handler); - } -} diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 14b5f7a6d60e2..0178c0318b81c 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -14,10 +14,29 @@ #![doc(primitive = "slice")] +// How this module is organized. +// +// The library infrastructure for slices is fairly messy. There's +// a lot of stuff defined here. Let's keep it clean. +// +// Since slices don't support inherent methods; all operations +// on them are defined on traits, which are then reexported from +// the prelude for convenience. So there are a lot of traits here. +// +// The layout of this file is thus: +// +// * Slice-specific 'extension' traits and their implementations. This +// is where most of the slice API resides. +// * Implementations of a few common traits with important slice ops. +// * Definitions of a bunch of iterators. +// * Free functions. +// * The `raw` and `bytes` submodules. +// * Boilerplate trait implementations. + use mem::transmute; use clone::Clone; use collections::Collection; -use cmp::{PartialEq, Ord, Ordering, Less, Equal, Greater}; +use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Less, Equal, Greater, Equiv}; use cmp; use default::Default; use iter::*; @@ -30,450 +49,411 @@ use mem::size_of; use kinds::marker; use raw::{Repr, Slice}; -/** - * Converts a pointer to A into a slice of length 1 (without copying). - */ -pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { - unsafe { - transmute(Slice { data: s, len: 1 }) - } -} +// +// Extension traits +// -/** - * Converts a pointer to A into a slice of length 1 (without copying). - */ -pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { - unsafe { - let ptr: *A = transmute(s); - transmute(Slice { data: ptr, len: 1 }) - } -} +/// Extension methods for vectors +pub trait ImmutableVector<'a, T> { + /** + * Returns a slice of self spanning the interval [`start`, `end`). + * + * Fails when the slice (or part of it) is outside the bounds of self, + * or when `start` > `end`. + */ + fn slice(&self, start: uint, end: uint) -> &'a [T]; -/// An iterator over the slices of a vector separated by elements that -/// match a predicate function. -pub struct Splits<'a, T> { - v: &'a [T], - pred: |t: &T|: 'a -> bool, - finished: bool + /** + * Returns a slice of self from `start` to the end of the vec. + * + * Fails when `start` points outside the bounds of self. + */ + fn slice_from(&self, start: uint) -> &'a [T]; + + /** + * Returns a slice of self from the start of the vec to `end`. + * + * Fails when `end` points outside the bounds of self. + */ + fn slice_to(&self, end: uint) -> &'a [T]; + /// Returns an iterator over the vector + fn iter(self) -> Items<'a, T>; + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred`. The matched element + /// is not contained in the subslices. + fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>; + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred`, limited to splitting + /// at most `n` times. The matched element is not contained in + /// the subslices. + fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>; + /// Returns an iterator over the subslices of the vector which are + /// separated by elements that match `pred` limited to splitting + /// at most `n` times. This starts at the end of the vector and + /// works backwards. The matched element is not contained in the + /// subslices. + fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>; + + /** + * Returns an iterator over all contiguous windows of length + * `size`. The windows overlap. If the vector is shorter than + * `size`, the iterator returns no values. + * + * # Failure + * + * Fails if `size` is 0. + * + * # Example + * + * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, + * `[3,4]`): + * + * ```rust + * let v = &[1i, 2, 3, 4]; + * for win in v.windows(2) { + * println!("{}", win); + * } + * ``` + * + */ + fn windows(self, size: uint) -> Windows<'a, T>; + /** + * + * Returns an iterator over `size` elements of the vector at a + * time. The chunks do not overlap. If `size` does not divide the + * length of the vector, then the last chunk will not have length + * `size`. + * + * # Failure + * + * Fails if `size` is 0. + * + * # Example + * + * Print the vector two elements at a time (i.e. `[1,2]`, + * `[3,4]`, `[5]`): + * + * ```rust + * let v = &[1i, 2, 3, 4, 5]; + * for win in v.chunks(2) { + * println!("{}", win); + * } + * ``` + * + */ + fn chunks(self, size: uint) -> Chunks<'a, T>; + + /// Returns the element of a vector at the given index, or `None` if the + /// index is out of bounds + fn get(&self, index: uint) -> Option<&'a T>; + /// Returns the first element of a vector, or `None` if it is empty + fn head(&self) -> Option<&'a T>; + /// Returns all but the first element of a vector + fn tail(&self) -> &'a [T]; + /// Returns all but the first `n' elements of a vector + fn tailn(&self, n: uint) -> &'a [T]; + /// Returns all but the last element of a vector + fn init(&self) -> &'a [T]; + /// Returns all but the last `n' elements of a vector + fn initn(&self, n: uint) -> &'a [T]; + /// Returns the last element of a vector, or `None` if it is empty. + fn last(&self) -> Option<&'a T>; + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + unsafe fn unsafe_ref(self, index: uint) -> &'a T; + + /** + * Returns an unsafe pointer to the vector's buffer + * + * The caller must ensure that the vector outlives the pointer this + * function returns, or else it will end up pointing to garbage. + * + * Modifying the vector may cause its buffer to be reallocated, which + * would also make any pointers to it invalid. + */ + fn as_ptr(&self) -> *const T; + + /** + * Binary search a sorted vector with a comparator function. + * + * The comparator function should implement an order consistent + * with the sort order of the underlying vector, returning an + * order code that indicates whether its argument is `Less`, + * `Equal` or `Greater` the desired target. + * + * Returns the index where the comparator returned `Equal`, or `None` if + * not found. + */ + fn bsearch(&self, f: |&T| -> Ordering) -> Option; + + /** + * Returns an immutable reference to the first element in this slice + * and adjusts the slice in place so that it no longer contains + * that element. O(1). + * + * Equivalent to: + * + * ```ignore + * if self.len() == 0 { return None } + * let head = &self[0]; + * *self = self.slice_from(1); + * Some(head) + * ``` + * + * Returns `None` if vector is empty + */ + fn shift_ref(&mut self) -> Option<&'a T>; + + /** + * Returns an immutable reference to the last element in this slice + * and adjusts the slice in place so that it no longer contains + * that element. O(1). + * + * Equivalent to: + * + * ```ignore + * if self.len() == 0 { return None; } + * let tail = &self[self.len() - 1]; + * *self = self.slice_to(self.len() - 1); + * Some(tail) + * ``` + * + * Returns `None` if slice is empty. + */ + fn pop_ref(&mut self) -> Option<&'a T>; } -impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { +impl<'a,T> ImmutableVector<'a, T> for &'a [T] { #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.finished { return None; } - - match self.v.iter().position(|x| (self.pred)(x)) { - None => { - self.finished = true; - Some(self.v) - } - Some(idx) => { - let ret = Some(self.v.slice(0, idx)); - self.v = self.v.slice(idx + 1, self.v.len()); - ret - } + fn slice(&self, start: uint, end: uint) -> &'a [T] { + assert!(start <= end); + assert!(end <= self.len()); + unsafe { + transmute(Slice { + data: self.as_ptr().offset(start as int), + len: (end - start) + }) } } #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.finished { - (0, Some(0)) - } else { - (1, Some(self.v.len() + 1)) - } + fn slice_from(&self, start: uint) -> &'a [T] { + self.slice(start, self.len()) } -} -impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> { #[inline] - fn next_back(&mut self) -> Option<&'a [T]> { - if self.finished { return None; } + fn slice_to(&self, end: uint) -> &'a [T] { + self.slice(0, end) + } - match self.v.iter().rposition(|x| (self.pred)(x)) { - None => { - self.finished = true; - Some(self.v) - } - Some(idx) => { - let ret = Some(self.v.slice(idx + 1, self.v.len())); - self.v = self.v.slice(0, idx); - ret + #[inline] + fn iter(self) -> Items<'a, T> { + unsafe { + let p = self.as_ptr(); + if mem::size_of::() == 0 { + Items{ptr: p, + end: (p as uint + self.len()) as *const T, + marker: marker::ContravariantLifetime::<'a>} + } else { + Items{ptr: p, + end: p.offset(self.len() as int), + marker: marker::ContravariantLifetime::<'a>} } } } -} -/// An iterator over the slices of a vector separated by elements that -/// match a predicate function, splitting at most a fixed number of times. -pub struct SplitsN<'a, T> { - iter: Splits<'a, T>, - count: uint, - invert: bool -} - -impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> { #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.count == 0 { - if self.iter.finished { - None - } else { - self.iter.finished = true; - Some(self.iter.v) - } - } else { - self.count -= 1; - if self.invert { self.iter.next_back() } else { self.iter.next() } + fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T> { + Splits { + v: self, + pred: pred, + finished: false } } #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.iter.finished { - (0, Some(0)) - } else { - (1, Some(cmp::min(self.count, self.iter.v.len()) + 1)) + fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> { + SplitsN { + iter: self.split(pred), + count: n, + invert: false } } -} - -// Functional utilities - -/// An iterator over the (overlapping) slices of length `size` within -/// a vector. -#[deriving(Clone)] -pub struct Windows<'a, T> { - v: &'a [T], - size: uint -} -impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> { #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.size > self.v.len() { - None - } else { - let ret = Some(self.v.slice(0, self.size)); - self.v = self.v.slice(1, self.v.len()); - ret + fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> { + SplitsN { + iter: self.split(pred), + count: n, + invert: true } } #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.size > self.v.len() { - (0, Some(0)) - } else { - let x = self.v.len() - self.size; - (x.saturating_add(1), x.checked_add(&1u)) - } + fn windows(self, size: uint) -> Windows<'a, T> { + assert!(size != 0); + Windows { v: self, size: size } } -} - -/// An iterator over a vector in (non-overlapping) chunks (`size` -/// elements at a time). -/// -/// When the vector len is not evenly divided by the chunk size, -/// the last slice of the iteration will be the remainder. -#[deriving(Clone)] -pub struct Chunks<'a, T> { - v: &'a [T], - size: uint -} -impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> { #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.v.len() == 0 { - None - } else { - let chunksz = cmp::min(self.v.len(), self.size); - let (fst, snd) = (self.v.slice_to(chunksz), - self.v.slice_from(chunksz)); - self.v = snd; - Some(fst) - } + fn chunks(self, size: uint) -> Chunks<'a, T> { + assert!(size != 0); + Chunks { v: self, size: size } } #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.v.len() == 0 { - (0, Some(0)) - } else { - let (n, rem) = div_rem(self.v.len(), self.size); - let n = if rem > 0 { n+1 } else { n }; - (n, Some(n)) - } + fn get(&self, index: uint) -> Option<&'a T> { + if index < self.len() { Some(&self[index]) } else { None } } -} -impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> { #[inline] - fn next_back(&mut self) -> Option<&'a [T]> { - if self.v.len() == 0 { - None - } else { - let remainder = self.v.len() % self.size; - let chunksz = if remainder != 0 { remainder } else { self.size }; - let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz), - self.v.slice_from(self.v.len() - chunksz)); - self.v = fst; - Some(snd) - } + fn head(&self) -> Option<&'a T> { + if self.len() == 0 { None } else { Some(&self[0]) } } -} -impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> { #[inline] - fn indexable(&self) -> uint { - self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 } - } + fn tail(&self) -> &'a [T] { self.slice(1, self.len()) } #[inline] - fn idx(&mut self, index: uint) -> Option<&'a [T]> { - if index < self.indexable() { - let lo = index * self.size; - let mut hi = lo + self.size; - if hi < lo || hi > self.v.len() { hi = self.v.len(); } + fn tailn(&self, n: uint) -> &'a [T] { self.slice(n, self.len()) } - Some(self.v.slice(lo, hi)) - } else { - None - } + #[inline] + fn init(&self) -> &'a [T] { + self.slice(0, self.len() - 1) } -} -// Equality + #[inline] + fn initn(&self, n: uint) -> &'a [T] { + self.slice(0, self.len() - n) + } -#[cfg(not(test))] -#[allow(missing_doc)] -pub mod traits { - use super::*; + #[inline] + fn last(&self) -> Option<&'a T> { + if self.len() == 0 { None } else { Some(&self[self.len() - 1]) } + } - use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv}; - use iter::order; - use collections::Collection; + #[inline] + unsafe fn unsafe_ref(self, index: uint) -> &'a T { + transmute(self.repr().data.offset(index as int)) + } - impl<'a,T:PartialEq> PartialEq for &'a [T] { - fn eq(&self, other: & &'a [T]) -> bool { - self.len() == other.len() && - order::eq(self.iter(), other.iter()) - } - fn ne(&self, other: & &'a [T]) -> bool { - self.len() != other.len() || - order::ne(self.iter(), other.iter()) - } + #[inline] + fn as_ptr(&self) -> *const T { + self.repr().data } - impl<'a,T:Eq> Eq for &'a [T] {} - impl<'a,T:PartialEq, V: Vector> Equiv for &'a [T] { - #[inline] - fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } - } + fn bsearch(&self, f: |&T| -> Ordering) -> Option { + let mut base : uint = 0; + let mut lim : uint = self.len(); - impl<'a,T:Ord> Ord for &'a [T] { - fn cmp(&self, other: & &'a [T]) -> Ordering { - order::cmp(self.iter(), other.iter()) + while lim != 0 { + let ix = base + (lim >> 1); + match f(&self[ix]) { + Equal => return Some(ix), + Less => { + base = ix + 1; + lim -= 1; + } + Greater => () + } + lim >>= 1; } + return None; } - impl<'a, T: PartialOrd> PartialOrd for &'a [T] { - fn lt(&self, other: & &'a [T]) -> bool { - order::lt(self.iter(), other.iter()) - } - #[inline] - fn le(&self, other: & &'a [T]) -> bool { - order::le(self.iter(), other.iter()) - } - #[inline] - fn ge(&self, other: & &'a [T]) -> bool { - order::ge(self.iter(), other.iter()) - } - #[inline] - fn gt(&self, other: & &'a [T]) -> bool { - order::gt(self.iter(), other.iter()) + fn shift_ref(&mut self) -> Option<&'a T> { + unsafe { + let s: &mut Slice = transmute(self); + match raw::shift_ptr(s) { + Some(p) => Some(&*p), + None => None + } } } -} - -#[cfg(test)] -pub mod traits {} - -/// Any vector that can be represented as a slice. -pub trait Vector { - /// Work with `self` as a slice. - fn as_slice<'a>(&'a self) -> &'a [T]; -} - -impl<'a,T> Vector for &'a [T] { - #[inline(always)] - fn as_slice<'a>(&'a self) -> &'a [T] { *self } -} -impl<'a, T> Collection for &'a [T] { - /// Returns the length of a vector - #[inline] - fn len(&self) -> uint { - self.repr().len + fn pop_ref(&mut self) -> Option<&'a T> { + unsafe { + let s: &mut Slice = transmute(self); + match raw::pop_ptr(s) { + Some(p) => Some(&*p), + None => None + } + } } } -/// Extension methods for vectors -pub trait ImmutableVector<'a, T> { - /** - * Returns a slice of self spanning the interval [`start`, `end`). - * - * Fails when the slice (or part of it) is outside the bounds of self, - * or when `start` > `end`. - */ - fn slice(&self, start: uint, end: uint) -> &'a [T]; +/// Extension methods for vectors such that their elements are +/// mutable. +pub trait MutableVector<'a, T> { + /// Returns a mutable reference to the element at the given index, + /// or `None` if the index is out of bounds + fn get_mut(self, index: uint) -> Option<&'a mut T>; + /// Work with `self` as a mut slice. + /// Primarily intended for getting a &mut [T] from a [T, ..N]. + fn as_mut_slice(self) -> &'a mut [T]; + + /// Return a slice that points into another slice. + fn mut_slice(self, start: uint, end: uint) -> &'a mut [T]; /** * Returns a slice of self from `start` to the end of the vec. * * Fails when `start` points outside the bounds of self. */ - fn slice_from(&self, start: uint) -> &'a [T]; + fn mut_slice_from(self, start: uint) -> &'a mut [T]; /** * Returns a slice of self from the start of the vec to `end`. * * Fails when `end` points outside the bounds of self. */ - fn slice_to(&self, end: uint) -> &'a [T]; - /// Returns an iterator over the vector - fn iter(self) -> Items<'a, T>; - /// Returns an iterator over the subslices of the vector which are - /// separated by elements that match `pred`. The matched element - /// is not contained in the subslices. - fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>; - /// Returns an iterator over the subslices of the vector which are - /// separated by elements that match `pred`, limited to splitting - /// at most `n` times. The matched element is not contained in - /// the subslices. - fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>; - /// Returns an iterator over the subslices of the vector which are - /// separated by elements that match `pred` limited to splitting - /// at most `n` times. This starts at the end of the vector and - /// works backwards. The matched element is not contained in the - /// subslices. - fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>; + fn mut_slice_to(self, end: uint) -> &'a mut [T]; + + /// Returns an iterator that allows modifying each value + fn mut_iter(self) -> MutItems<'a, T>; + + /// Returns a mutable pointer to the last item in the vector. + fn mut_last(self) -> Option<&'a mut T>; + + /// Returns an iterator over the mutable subslices of the vector + /// which are separated by elements that match `pred`. The + /// matched element is not contained in the subslices. + fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>; /** - * Returns an iterator over all contiguous windows of length - * `size`. The windows overlap. If the vector is shorter than - * `size`, the iterator returns no values. - * - * # Failure - * - * Fails if `size` is 0. - * - * # Example - * - * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, - * `[3,4]`): - * - * ```rust - * let v = &[1i, 2, 3, 4]; - * for win in v.windows(2) { - * println!("{}", win); - * } - * ``` - * - */ - fn windows(self, size: uint) -> Windows<'a, T>; - /** - * - * Returns an iterator over `size` elements of the vector at a - * time. The chunks do not overlap. If `size` does not divide the + * Returns an iterator over `size` elements of the vector at a time. + * The chunks are mutable and do not overlap. If `size` does not divide the * length of the vector, then the last chunk will not have length * `size`. * * # Failure * * Fails if `size` is 0. - * - * # Example - * - * Print the vector two elements at a time (i.e. `[1,2]`, - * `[3,4]`, `[5]`): - * - * ```rust - * let v = &[1i, 2, 3, 4, 5]; - * for win in v.chunks(2) { - * println!("{}", win); - * } - * ``` - * - */ - fn chunks(self, size: uint) -> Chunks<'a, T>; - - /// Returns the element of a vector at the given index, or `None` if the - /// index is out of bounds - fn get(&self, index: uint) -> Option<&'a T>; - /// Returns the first element of a vector, or `None` if it is empty - fn head(&self) -> Option<&'a T>; - /// Returns all but the first element of a vector - fn tail(&self) -> &'a [T]; - /// Returns all but the first `n' elements of a vector - fn tailn(&self, n: uint) -> &'a [T]; - /// Returns all but the last element of a vector - fn init(&self) -> &'a [T]; - /// Returns all but the last `n' elements of a vector - fn initn(&self, n: uint) -> &'a [T]; - /// Returns the last element of a vector, or `None` if it is empty. - fn last(&self) -> Option<&'a T>; - - /// Returns a pointer to the element at the given index, without doing - /// bounds checking. - unsafe fn unsafe_ref(self, index: uint) -> &'a T; - - /** - * Returns an unsafe pointer to the vector's buffer - * - * The caller must ensure that the vector outlives the pointer this - * function returns, or else it will end up pointing to garbage. - * - * Modifying the vector may cause its buffer to be reallocated, which - * would also make any pointers to it invalid. */ - fn as_ptr(&self) -> *T; - - /** - * Binary search a sorted vector with a comparator function. - * - * The comparator function should implement an order consistent - * with the sort order of the underlying vector, returning an - * order code that indicates whether its argument is `Less`, - * `Equal` or `Greater` the desired target. - * - * Returns the index where the comparator returned `Equal`, or `None` if - * not found. - */ - fn bsearch(&self, f: |&T| -> Ordering) -> Option; + fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T>; /** - * Returns an immutable reference to the first element in this slice + * Returns a mutable reference to the first element in this slice * and adjusts the slice in place so that it no longer contains * that element. O(1). * * Equivalent to: * * ```ignore - * if self.len() == 0 { return None } - * let head = &self[0]; - * *self = self.slice_from(1); + * if self.len() == 0 { return None; } + * let head = &mut self[0]; + * *self = self.mut_slice_from(1); * Some(head) * ``` * - * Returns `None` if vector is empty + * Returns `None` if slice is empty */ - fn shift_ref(&mut self) -> Option<&'a T>; + fn mut_shift_ref(&mut self) -> Option<&'a mut T>; /** - * Returns an immutable reference to the last element in this slice + * Returns a mutable reference to the last element in this slice * and adjusts the slice in place so that it no longer contains * that element. O(1). * @@ -481,173 +461,281 @@ pub trait ImmutableVector<'a, T> { * * ```ignore * if self.len() == 0 { return None; } - * let tail = &self[self.len() - 1]; - * *self = self.slice_to(self.len() - 1); + * let tail = &mut self[self.len() - 1]; + * *self = self.mut_slice_to(self.len() - 1); * Some(tail) * ``` * * Returns `None` if slice is empty. */ - fn pop_ref(&mut self) -> Option<&'a T>; + fn mut_pop_ref(&mut self) -> Option<&'a mut T>; + + /// Swaps two elements in a vector. + /// + /// Fails if `a` or `b` are out of bounds. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Example + /// + /// ```rust + /// let mut v = ["a", "b", "c", "d"]; + /// v.swap(1, 3); + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + fn swap(self, a: uint, b: uint); + + + /// Divides one `&mut` into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// Fails if `mid > len`. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1i, 2, 3, 4, 5, 6]; + /// + /// // scoped to restrict the lifetime of the borrows + /// { + /// let (left, right) = v.mut_split_at(0); + /// assert!(left == &mut []); + /// assert!(right == &mut [1i, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.mut_split_at(2); + /// assert!(left == &mut [1i, 2]); + /// assert!(right == &mut [3i, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.mut_split_at(6); + /// assert!(left == &mut [1i, 2, 3, 4, 5, 6]); + /// assert!(right == &mut []); + /// } + /// ``` + fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]); + + /// Reverse the order of elements in a vector, in place. + /// + /// # Example + /// + /// ```rust + /// let mut v = [1i, 2, 3]; + /// v.reverse(); + /// assert!(v == [3i, 2, 1]); + /// ``` + fn reverse(self); + + /// Returns an unsafe mutable pointer to the element in index + unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T; + + /// Return an unsafe mutable pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// + /// Modifying the vector may cause its buffer to be reallocated, which + /// would also make any pointers to it invalid. + #[inline] + fn as_mut_ptr(self) -> *mut T; + + /// Unsafely sets the element in index to the value. + /// + /// This performs no bounds checks, and it is undefined behaviour + /// if `index` is larger than the length of `self`. However, it + /// does run the destructor at `index`. It is equivalent to + /// `self[index] = val`. + /// + /// # Example + /// + /// ```rust + /// let mut v = ["foo".to_string(), "bar".to_string(), "baz".to_string()]; + /// + /// unsafe { + /// // `"baz".to_string()` is deallocated. + /// v.unsafe_set(2, "qux".to_string()); + /// + /// // Out of bounds: could cause a crash, or overwriting + /// // other data, or something else. + /// // v.unsafe_set(10, "oops".to_string()); + /// } + /// ``` + unsafe fn unsafe_set(self, index: uint, val: T); + + /// Unchecked vector index assignment. Does not drop the + /// old value and hence is only suitable when the vector + /// is newly allocated. + /// + /// # Example + /// + /// ```rust + /// let mut v = ["foo".to_string(), "bar".to_string()]; + /// + /// // memory leak! `"bar".to_string()` is not deallocated. + /// unsafe { v.init_elem(1, "baz".to_string()); } + /// ``` + unsafe fn init_elem(self, i: uint, val: T); + + /// Copies raw bytes from `src` to `self`. + /// + /// This does not run destructors on the overwritten elements, and + /// ignores move semantics. `self` and `src` must not + /// overlap. Fails if `self` is shorter than `src`. + unsafe fn copy_memory(self, src: &[T]); } -impl<'a,T> ImmutableVector<'a, T> for &'a [T] { +impl<'a,T> MutableVector<'a, T> for &'a mut [T] { #[inline] - fn slice(&self, start: uint, end: uint) -> &'a [T] { + fn get_mut(self, index: uint) -> Option<&'a mut T> { + if index < self.len() { Some(&mut self[index]) } else { None } + } + + #[inline] + fn as_mut_slice(self) -> &'a mut [T] { self } + + fn mut_slice(self, start: uint, end: uint) -> &'a mut [T] { assert!(start <= end); assert!(end <= self.len()); unsafe { transmute(Slice { - data: self.as_ptr().offset(start as int), + data: self.as_mut_ptr().offset(start as int) as *const T, len: (end - start) }) } } #[inline] - fn slice_from(&self, start: uint) -> &'a [T] { - self.slice(start, self.len()) + fn mut_slice_from(self, start: uint) -> &'a mut [T] { + let len = self.len(); + self.mut_slice(start, len) } #[inline] - fn slice_to(&self, end: uint) -> &'a [T] { - self.slice(0, end) + fn mut_slice_to(self, end: uint) -> &'a mut [T] { + self.mut_slice(0, end) } #[inline] - fn iter(self) -> Items<'a, T> { + fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]) { unsafe { - let p = self.as_ptr(); - if mem::size_of::() == 0 { - Items{ptr: p, - end: (p as uint + self.len()) as *T, - marker: marker::ContravariantLifetime::<'a>} - } else { - Items{ptr: p, - end: p.offset(self.len() as int), - marker: marker::ContravariantLifetime::<'a>} - } + let len = self.len(); + let self2: &'a mut [T] = mem::transmute_copy(&self); + (self.mut_slice(0, mid), self2.mut_slice(mid, len)) } } #[inline] - fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T> { - Splits { - v: self, - pred: pred, - finished: false + fn mut_iter(self) -> MutItems<'a, T> { + unsafe { + let p = self.as_mut_ptr(); + if mem::size_of::() == 0 { + MutItems{ptr: p, + end: (p as uint + self.len()) as *mut T, + marker: marker::ContravariantLifetime::<'a>, + marker2: marker::NoCopy} + } else { + MutItems{ptr: p, + end: p.offset(self.len() as int), + marker: marker::ContravariantLifetime::<'a>, + marker2: marker::NoCopy} + } } } #[inline] - fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> { - SplitsN { - iter: self.split(pred), - count: n, - invert: false - } + fn mut_last(self) -> Option<&'a mut T> { + let len = self.len(); + if len == 0 { return None; } + Some(&mut self[len - 1]) } #[inline] - fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> { - SplitsN { - iter: self.split(pred), - count: n, - invert: true - } + fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T> { + MutSplits { v: self, pred: pred, finished: false } } #[inline] - fn windows(self, size: uint) -> Windows<'a, T> { - assert!(size != 0); - Windows { v: self, size: size } + fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T> { + assert!(chunk_size > 0); + MutChunks { v: self, chunk_size: chunk_size } } - #[inline] - fn chunks(self, size: uint) -> Chunks<'a, T> { - assert!(size != 0); - Chunks { v: self, size: size } + fn mut_shift_ref(&mut self) -> Option<&'a mut T> { + unsafe { + let s: &mut Slice = transmute(self); + match raw::shift_ptr(s) { + // FIXME #13933: this `&` -> `&mut` cast is a little + // dubious + Some(p) => Some(&mut *(p as *mut _)), + None => None, + } + } } - #[inline] - fn get(&self, index: uint) -> Option<&'a T> { - if index < self.len() { Some(&self[index]) } else { None } + fn mut_pop_ref(&mut self) -> Option<&'a mut T> { + unsafe { + let s: &mut Slice = transmute(self); + match raw::pop_ptr(s) { + // FIXME #13933: this `&` -> `&mut` cast is a little + // dubious + Some(p) => Some(&mut *(p as *mut _)), + None => None, + } + } } - #[inline] - fn head(&self) -> Option<&'a T> { - if self.len() == 0 { None } else { Some(&self[0]) } + fn swap(self, a: uint, b: uint) { + unsafe { + // Can't take two mutable loans from one vector, so instead just cast + // them to their raw pointers to do the swap + let pa: *mut T = &mut self[a]; + let pb: *mut T = &mut self[b]; + ptr::swap(pa, pb); + } } - #[inline] - fn tail(&self) -> &'a [T] { self.slice(1, self.len()) } - - #[inline] - fn tailn(&self, n: uint) -> &'a [T] { self.slice(n, self.len()) } - - #[inline] - fn init(&self) -> &'a [T] { - self.slice(0, self.len() - 1) + fn reverse(self) { + let mut i: uint = 0; + let ln = self.len(); + while i < ln / 2 { + self.swap(i, ln - i - 1); + i += 1; + } } #[inline] - fn initn(&self, n: uint) -> &'a [T] { - self.slice(0, self.len() - n) + unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T { + transmute((self.repr().data as *mut T).offset(index as int)) } #[inline] - fn last(&self) -> Option<&'a T> { - if self.len() == 0 { None } else { Some(&self[self.len() - 1]) } + fn as_mut_ptr(self) -> *mut T { + self.repr().data as *mut T } #[inline] - unsafe fn unsafe_ref(self, index: uint) -> &'a T { - transmute(self.repr().data.offset(index as int)) + unsafe fn unsafe_set(self, index: uint, val: T) { + *self.unsafe_mut_ref(index) = val; } #[inline] - fn as_ptr(&self) -> *T { - self.repr().data - } - - - fn bsearch(&self, f: |&T| -> Ordering) -> Option { - let mut base : uint = 0; - let mut lim : uint = self.len(); - - while lim != 0 { - let ix = base + (lim >> 1); - match f(&self[ix]) { - Equal => return Some(ix), - Less => { - base = ix + 1; - lim -= 1; - } - Greater => () - } - lim >>= 1; - } - return None; - } - - fn shift_ref(&mut self) -> Option<&'a T> { - unsafe { - let s: &mut Slice = transmute(self); - match raw::shift_ptr(s) { - Some(p) => Some(&*p), - None => None - } - } + unsafe fn init_elem(self, i: uint, val: T) { + ptr::write(&mut (*self.as_mut_ptr().offset(i as int)), val); } - fn pop_ref(&mut self) -> Option<&'a T> { - unsafe { - let s: &mut Slice = transmute(self); - match raw::pop_ptr(s) { - Some(p) => Some(&*p), - None => None - } - } + #[inline] + unsafe fn copy_memory(self, src: &[T]) { + let len_src = src.len(); + assert!(self.len() >= len_src); + ptr::copy_nonoverlapping_memory(self.as_mut_ptr(), src.as_ptr(), len_src) } } @@ -714,395 +802,523 @@ impl<'a, T: Ord> ImmutableOrdVector for &'a [T] { } } -/// Extension methods for vectors such that their elements are -/// mutable. -pub trait MutableVector<'a, T> { - /// Returns a mutable reference to the element at the given index, - /// or `None` if the index is out of bounds - fn get_mut(self, index: uint) -> Option<&'a mut T>; - /// Work with `self` as a mut slice. - /// Primarily intended for getting a &mut [T] from a [T, ..N]. - fn as_mut_slice(self) -> &'a mut [T]; +/// Trait for &[T] where T is Cloneable +pub trait MutableCloneableVector { + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// use std::slice::MutableCloneableVector; + /// + /// let mut dst = [0i, 0, 0]; + /// let src = [1i, 2]; + /// + /// assert!(dst.copy_from(src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3i, 4, 5, 6]; + /// assert!(dst.copy_from(src2) == 3); + /// assert!(dst == [3i, 4, 5]); + /// ``` + fn copy_from(self, &[T]) -> uint; +} - /// Return a slice that points into another slice. - fn mut_slice(self, start: uint, end: uint) -> &'a mut [T]; +impl<'a, T:Clone> MutableCloneableVector for &'a mut [T] { + #[inline] + fn copy_from(self, src: &[T]) -> uint { + for (a, b) in self.mut_iter().zip(src.iter()) { + a.clone_from(b); + } + cmp::min(self.len(), src.len()) + } +} - /** - * Returns a slice of self from `start` to the end of the vec. - * - * Fails when `start` points outside the bounds of self. - */ - fn mut_slice_from(self, start: uint) -> &'a mut [T]; - /** - * Returns a slice of self from the start of the vec to `end`. - * - * Fails when `end` points outside the bounds of self. - */ - fn mut_slice_to(self, end: uint) -> &'a mut [T]; - /// Returns an iterator that allows modifying each value - fn mut_iter(self) -> MutItems<'a, T>; - /// Returns a mutable pointer to the last item in the vector. - fn mut_last(self) -> Option<&'a mut T>; +// +// Common traits +// - /// Returns an iterator over the mutable subslices of the vector - /// which are separated by elements that match `pred`. The - /// matched element is not contained in the subslices. - fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>; +/// Any vector that can be represented as a slice. +pub trait Vector { + /// Work with `self` as a slice. + fn as_slice<'a>(&'a self) -> &'a [T]; +} - /** - * Returns an iterator over `size` elements of the vector at a time. - * The chunks are mutable and do not overlap. If `size` does not divide the - * length of the vector, then the last chunk will not have length - * `size`. - * - * # Failure - * - * Fails if `size` is 0. - */ - fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T>; +impl<'a,T> Vector for &'a [T] { + #[inline(always)] + fn as_slice<'a>(&'a self) -> &'a [T] { *self } +} - /** - * Returns a mutable reference to the first element in this slice - * and adjusts the slice in place so that it no longer contains - * that element. O(1). - * - * Equivalent to: - * - * ```ignore - * if self.len() == 0 { return None; } - * let head = &mut self[0]; - * *self = self.mut_slice_from(1); - * Some(head) - * ``` - * - * Returns `None` if slice is empty - */ - fn mut_shift_ref(&mut self) -> Option<&'a mut T>; +impl<'a, T> Collection for &'a [T] { + /// Returns the length of a vector + #[inline] + fn len(&self) -> uint { + self.repr().len + } +} - /** - * Returns a mutable reference to the last element in this slice - * and adjusts the slice in place so that it no longer contains - * that element. O(1). - * - * Equivalent to: - * - * ```ignore - * if self.len() == 0 { return None; } - * let tail = &mut self[self.len() - 1]; - * *self = self.mut_slice_to(self.len() - 1); - * Some(tail) - * ``` - * - * Returns `None` if slice is empty. - */ - fn mut_pop_ref(&mut self) -> Option<&'a mut T>; +impl<'a, T> Default for &'a [T] { + fn default() -> &'a [T] { &[] } +} - /// Swaps two elements in a vector. - /// - /// Fails if `a` or `b` are out of bounds. - /// - /// # Arguments - /// - /// * a - The index of the first element - /// * b - The index of the second element - /// - /// # Example - /// - /// ```rust - /// let mut v = ["a", "b", "c", "d"]; - /// v.swap(1, 3); - /// assert!(v == ["a", "d", "c", "b"]); - /// ``` - fn swap(self, a: uint, b: uint); - /// Divides one `&mut` into two at an index. - /// - /// The first will contain all indices from `[0, mid)` (excluding - /// the index `mid` itself) and the second will contain all - /// indices from `[mid, len)` (excluding the index `len` itself). - /// - /// Fails if `mid > len`. - /// - /// # Example - /// - /// ```rust - /// let mut v = [1i, 2, 3, 4, 5, 6]; - /// - /// // scoped to restrict the lifetime of the borrows - /// { - /// let (left, right) = v.mut_split_at(0); - /// assert!(left == &mut []); - /// assert!(right == &mut [1i, 2, 3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.mut_split_at(2); - /// assert!(left == &mut [1i, 2]); - /// assert!(right == &mut [3i, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.mut_split_at(6); - /// assert!(left == &mut [1i, 2, 3, 4, 5, 6]); - /// assert!(right == &mut []); - /// } - /// ``` - fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]); - /// Reverse the order of elements in a vector, in place. - /// - /// # Example - /// - /// ```rust - /// let mut v = [1i, 2, 3]; - /// v.reverse(); - /// assert!(v == [3i, 2, 1]); - /// ``` - fn reverse(self); +// +// Iterators +// - /// Returns an unsafe mutable pointer to the element in index - unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T; +// The shared definition of the `Item` and `MutItems` iterators +macro_rules! iterator { + (struct $name:ident -> $ptr:ty, $elem:ty) => { + impl<'a, T> Iterator<$elem> for $name<'a, T> { + #[inline] + fn next(&mut self) -> Option<$elem> { + // could be implemented with slices, but this avoids bounds checks + unsafe { + if self.ptr == self.end { + None + } else { + let old = self.ptr; + self.ptr = if mem::size_of::() == 0 { + // purposefully don't use 'ptr.offset' because for + // vectors with 0-size elements this would return the + // same pointer. + transmute(self.ptr as uint + 1) + } else { + self.ptr.offset(1) + }; - /// Return an unsafe mutable pointer to the vector's buffer. - /// - /// The caller must ensure that the vector outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// - /// Modifying the vector may cause its buffer to be reallocated, which - /// would also make any pointers to it invalid. + Some(transmute(old)) + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let diff = (self.end as uint) - (self.ptr as uint); + let size = mem::size_of::(); + let exact = diff / (if size == 0 {1} else {size}); + (exact, Some(exact)) + } + } + + impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<$elem> { + // could be implemented with slices, but this avoids bounds checks + unsafe { + if self.end == self.ptr { + None + } else { + self.end = if mem::size_of::() == 0 { + // See above for why 'ptr.offset' isn't used + transmute(self.end as uint - 1) + } else { + self.end.offset(-1) + }; + Some(transmute(self.end)) + } + } + } + } + } +} + +/// Immutable slice iterator +pub struct Items<'a, T> { + ptr: *const T, + end: *const T, + marker: marker::ContravariantLifetime<'a> +} + +iterator!{struct Items -> *const T, &'a T} + +impl<'a, T> ExactSize<&'a T> for Items<'a, T> {} + +impl<'a, T> Clone for Items<'a, T> { + fn clone(&self) -> Items<'a, T> { *self } +} + +impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { #[inline] - fn as_mut_ptr(self) -> *mut T; + fn indexable(&self) -> uint { + let (exact, _) = self.size_hint(); + exact + } - /// Unsafely sets the element in index to the value. - /// - /// This performs no bounds checks, and it is undefined behaviour - /// if `index` is larger than the length of `self`. However, it - /// does run the destructor at `index`. It is equivalent to - /// `self[index] = val`. - /// - /// # Example - /// - /// ```rust - /// let mut v = ["foo".to_string(), "bar".to_string(), "baz".to_string()]; - /// - /// unsafe { - /// // `"baz".to_string()` is deallocated. - /// v.unsafe_set(2, "qux".to_string()); - /// - /// // Out of bounds: could cause a crash, or overwriting - /// // other data, or something else. - /// // v.unsafe_set(10, "oops".to_string()); - /// } - /// ``` - unsafe fn unsafe_set(self, index: uint, val: T); + #[inline] + fn idx(&mut self, index: uint) -> Option<&'a T> { + unsafe { + if index < self.indexable() { + transmute(self.ptr.offset(index as int)) + } else { + None + } + } + } +} - /// Unchecked vector index assignment. Does not drop the - /// old value and hence is only suitable when the vector - /// is newly allocated. - /// - /// # Example - /// - /// ```rust - /// let mut v = ["foo".to_string(), "bar".to_string()]; - /// - /// // memory leak! `"bar".to_string()` is not deallocated. - /// unsafe { v.init_elem(1, "baz".to_string()); } - /// ``` - unsafe fn init_elem(self, i: uint, val: T); +/// Mutable slice iterator +pub struct MutItems<'a, T> { + ptr: *mut T, + end: *mut T, + marker: marker::ContravariantLifetime<'a>, + marker2: marker::NoCopy +} - /// Copies raw bytes from `src` to `self`. - /// - /// This does not run destructors on the overwritten elements, and - /// ignores move semantics. `self` and `src` must not - /// overlap. Fails if `self` is shorter than `src`. - unsafe fn copy_memory(self, src: &[T]); +iterator!{struct MutItems -> *mut T, &'a mut T} + +impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {} + +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function. +pub struct Splits<'a, T> { + v: &'a [T], + pred: |t: &T|: 'a -> bool, + finished: bool } -impl<'a,T> MutableVector<'a, T> for &'a mut [T] { +impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { #[inline] - fn get_mut(self, index: uint) -> Option<&'a mut T> { - if index < self.len() { Some(&mut self[index]) } else { None } + fn next(&mut self) -> Option<&'a [T]> { + if self.finished { return None; } + + match self.v.iter().position(|x| (self.pred)(x)) { + None => { + self.finished = true; + Some(self.v) + } + Some(idx) => { + let ret = Some(self.v.slice(0, idx)); + self.v = self.v.slice(idx + 1, self.v.len()); + ret + } + } } #[inline] - fn as_mut_slice(self) -> &'a mut [T] { self } + fn size_hint(&self) -> (uint, Option) { + if self.finished { + (0, Some(0)) + } else { + (1, Some(self.v.len() + 1)) + } + } +} - fn mut_slice(self, start: uint, end: uint) -> &'a mut [T] { - assert!(start <= end); - assert!(end <= self.len()); - unsafe { - transmute(Slice { - data: self.as_mut_ptr().offset(start as int) as *T, - len: (end - start) - }) +impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.finished { return None; } + + match self.v.iter().rposition(|x| (self.pred)(x)) { + None => { + self.finished = true; + Some(self.v) + } + Some(idx) => { + let ret = Some(self.v.slice(idx + 1, self.v.len())); + self.v = self.v.slice(0, idx); + ret + } + } + } +} + +/// An iterator over the subslices of the vector which are separated +/// by elements that match `pred`. +pub struct MutSplits<'a, T> { + v: &'a mut [T], + pred: |t: &T|: 'a -> bool, + finished: bool +} + +impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.finished { return None; } + + let pred = &mut self.pred; + match self.v.iter().position(|x| (*pred)(x)) { + None => { + self.finished = true; + let tmp = mem::replace(&mut self.v, &mut []); + let len = tmp.len(); + let (head, tail) = tmp.mut_split_at(len); + self.v = tail; + Some(head) + } + Some(idx) => { + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.mut_split_at(idx); + self.v = tail.mut_slice_from(1); + Some(head) + } } } #[inline] - fn mut_slice_from(self, start: uint) -> &'a mut [T] { - let len = self.len(); - self.mut_slice(start, len) + fn size_hint(&self) -> (uint, Option) { + if self.finished { + (0, Some(0)) + } else { + // if the predicate doesn't match anything, we yield one slice + // if it matches every element, we yield len+1 empty slices. + (1, Some(self.v.len() + 1)) + } } +} +impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> { #[inline] - fn mut_slice_to(self, end: uint) -> &'a mut [T] { - self.mut_slice(0, end) - } + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.finished { return None; } - #[inline] - fn mut_split_at(self, mid: uint) -> (&'a mut [T], &'a mut [T]) { - unsafe { - let len = self.len(); - let self2: &'a mut [T] = mem::transmute_copy(&self); - (self.mut_slice(0, mid), self2.mut_slice(mid, len)) + let pred = &mut self.pred; + match self.v.iter().rposition(|x| (*pred)(x)) { + None => { + self.finished = true; + let tmp = mem::replace(&mut self.v, &mut []); + Some(tmp) + } + Some(idx) => { + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.mut_split_at(idx); + self.v = head; + Some(tail.mut_slice_from(1)) + } } } +} + +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function, splitting at most a fixed number of times. +pub struct SplitsN<'a, T> { + iter: Splits<'a, T>, + count: uint, + invert: bool +} +impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> { #[inline] - fn mut_iter(self) -> MutItems<'a, T> { - unsafe { - let p = self.as_mut_ptr(); - if mem::size_of::() == 0 { - MutItems{ptr: p, - end: (p as uint + self.len()) as *mut T, - marker: marker::ContravariantLifetime::<'a>, - marker2: marker::NoCopy} + fn next(&mut self) -> Option<&'a [T]> { + if self.count == 0 { + if self.iter.finished { + None } else { - MutItems{ptr: p, - end: p.offset(self.len() as int), - marker: marker::ContravariantLifetime::<'a>, - marker2: marker::NoCopy} + self.iter.finished = true; + Some(self.iter.v) } + } else { + self.count -= 1; + if self.invert { self.iter.next_back() } else { self.iter.next() } } } #[inline] - fn mut_last(self) -> Option<&'a mut T> { - let len = self.len(); - if len == 0 { return None; } - Some(&mut self[len - 1]) + fn size_hint(&self) -> (uint, Option) { + if self.iter.finished { + (0, Some(0)) + } else { + (1, Some(cmp::min(self.count, self.iter.v.len()) + 1)) + } } +} - #[inline] - fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T> { - MutSplits { v: self, pred: pred, finished: false } - } +/// An iterator over the (overlapping) slices of length `size` within +/// a vector. +#[deriving(Clone)] +pub struct Windows<'a, T> { + v: &'a [T], + size: uint +} +impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> { #[inline] - fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T> { - assert!(chunk_size > 0); - MutChunks { v: self, chunk_size: chunk_size } + fn next(&mut self) -> Option<&'a [T]> { + if self.size > self.v.len() { + None + } else { + let ret = Some(self.v.slice(0, self.size)); + self.v = self.v.slice(1, self.v.len()); + ret + } } - fn mut_shift_ref(&mut self) -> Option<&'a mut T> { - unsafe { - let s: &mut Slice = transmute(self); - match raw::shift_ptr(s) { - // FIXME #13933: this `&` -> `&mut` cast is a little - // dubious - Some(p) => Some(&mut *(p as *mut _)), - None => None, - } + #[inline] + fn size_hint(&self) -> (uint, Option) { + if self.size > self.v.len() { + (0, Some(0)) + } else { + let x = self.v.len() - self.size; + (x.saturating_add(1), x.checked_add(&1u)) } } +} - fn mut_pop_ref(&mut self) -> Option<&'a mut T> { - unsafe { - let s: &mut Slice = transmute(self); - match raw::pop_ptr(s) { - // FIXME #13933: this `&` -> `&mut` cast is a little - // dubious - Some(p) => Some(&mut *(p as *mut _)), - None => None, - } +/// An iterator over a vector in (non-overlapping) chunks (`size` +/// elements at a time). +/// +/// When the vector len is not evenly divided by the chunk size, +/// the last slice of the iteration will be the remainder. +#[deriving(Clone)] +pub struct Chunks<'a, T> { + v: &'a [T], + size: uint +} + +impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.v.len() == 0 { + None + } else { + let chunksz = cmp::min(self.v.len(), self.size); + let (fst, snd) = (self.v.slice_to(chunksz), + self.v.slice_from(chunksz)); + self.v = snd; + Some(fst) } } - fn swap(self, a: uint, b: uint) { - unsafe { - // Can't take two mutable loans from one vector, so instead just cast - // them to their raw pointers to do the swap - let pa: *mut T = &mut self[a]; - let pb: *mut T = &mut self[b]; - ptr::swap(pa, pb); + #[inline] + fn size_hint(&self) -> (uint, Option) { + if self.v.len() == 0 { + (0, Some(0)) + } else { + let (n, rem) = div_rem(self.v.len(), self.size); + let n = if rem > 0 { n+1 } else { n }; + (n, Some(n)) } } +} - fn reverse(self) { - let mut i: uint = 0; - let ln = self.len(); - while i < ln / 2 { - self.swap(i, ln - i - 1); - i += 1; +impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.v.len() == 0 { + None + } else { + let remainder = self.v.len() % self.size; + let chunksz = if remainder != 0 { remainder } else { self.size }; + let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz), + self.v.slice_from(self.v.len() - chunksz)); + self.v = fst; + Some(snd) } } +} +impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> { #[inline] - unsafe fn unsafe_mut_ref(self, index: uint) -> &'a mut T { - transmute((self.repr().data as *mut T).offset(index as int)) + fn indexable(&self) -> uint { + self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 } } #[inline] - fn as_mut_ptr(self) -> *mut T { - self.repr().data as *mut T + fn idx(&mut self, index: uint) -> Option<&'a [T]> { + if index < self.indexable() { + let lo = index * self.size; + let mut hi = lo + self.size; + if hi < lo || hi > self.v.len() { hi = self.v.len(); } + + Some(self.v.slice(lo, hi)) + } else { + None + } } +} + +/// An iterator over a vector in (non-overlapping) mutable chunks (`size` elements at a time). When +/// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be +/// the remainder. +pub struct MutChunks<'a, T> { + v: &'a mut [T], + chunk_size: uint +} +impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> { #[inline] - unsafe fn unsafe_set(self, index: uint, val: T) { - *self.unsafe_mut_ref(index) = val; + fn next(&mut self) -> Option<&'a mut [T]> { + if self.v.len() == 0 { + None + } else { + let sz = cmp::min(self.v.len(), self.chunk_size); + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.mut_split_at(sz); + self.v = tail; + Some(head) + } } #[inline] - unsafe fn init_elem(self, i: uint, val: T) { - ptr::write(&mut (*self.as_mut_ptr().offset(i as int)), val); + fn size_hint(&self) -> (uint, Option) { + if self.v.len() == 0 { + (0, Some(0)) + } else { + let (n, rem) = div_rem(self.v.len(), self.chunk_size); + let n = if rem > 0 { n + 1 } else { n }; + (n, Some(n)) + } } +} +impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> { #[inline] - unsafe fn copy_memory(self, src: &[T]) { - let len_src = src.len(); - assert!(self.len() >= len_src); - ptr::copy_nonoverlapping_memory(self.as_mut_ptr(), src.as_ptr(), len_src) + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.v.len() == 0 { + None + } else { + let remainder = self.v.len() % self.chunk_size; + let sz = if remainder != 0 { remainder } else { self.chunk_size }; + let tmp = mem::replace(&mut self.v, &mut []); + let tmp_len = tmp.len(); + let (head, tail) = tmp.mut_split_at(tmp_len - sz); + self.v = head; + Some(tail) + } } } -/// Trait for &[T] where T is Cloneable -pub trait MutableCloneableVector { - /// Copies as many elements from `src` as it can into `self` (the - /// shorter of `self.len()` and `src.len()`). Returns the number - /// of elements copied. - /// - /// # Example - /// - /// ```rust - /// use std::slice::MutableCloneableVector; - /// - /// let mut dst = [0i, 0, 0]; - /// let src = [1i, 2]; - /// - /// assert!(dst.copy_from(src) == 2); - /// assert!(dst == [1, 2, 0]); - /// - /// let src2 = [3i, 4, 5, 6]; - /// assert!(dst.copy_from(src2) == 3); - /// assert!(dst == [3i, 4, 5]); - /// ``` - fn copy_from(self, &[T]) -> uint; + + + +// +// Free functions +// + +/** + * Converts a pointer to A into a slice of length 1 (without copying). + */ +pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { + unsafe { + transmute(Slice { data: s, len: 1 }) + } } -impl<'a, T:Clone> MutableCloneableVector for &'a mut [T] { - #[inline] - fn copy_from(self, src: &[T]) -> uint { - for (a, b) in self.mut_iter().zip(src.iter()) { - a.clone_from(b); - } - cmp::min(self.len(), src.len()) +/** + * Converts a pointer to A into a slice of length 1 (without copying). + */ +pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { + unsafe { + let ptr: *const A = transmute(s); + transmute(Slice { data: ptr, len: 1 }) } } + + + +// +// Submodules +// + /// Unsafe operations pub mod raw { use mem::transmute; @@ -1115,7 +1331,7 @@ pub mod raw { * not bytes). */ #[inline] - pub unsafe fn buf_as_slice(p: *T, len: uint, f: |v: &[T]| -> U) + pub unsafe fn buf_as_slice(p: *const T, len: uint, f: |v: &[T]| -> U) -> U { f(transmute(Slice { data: p, @@ -1135,7 +1351,7 @@ pub mod raw { f: |v: &mut [T]| -> U) -> U { f(transmute(Slice { - data: p as *T, + data: p as *const T, len: len })) } @@ -1146,9 +1362,9 @@ pub mod raw { * if the slice is empty. O(1). */ #[inline] - pub unsafe fn shift_ptr(slice: &mut Slice) -> Option<*T> { + pub unsafe fn shift_ptr(slice: &mut Slice) -> Option<*const T> { if slice.len == 0 { return None; } - let head: *T = slice.data; + let head: *const T = slice.data; slice.data = slice.data.offset(1); slice.len -= 1; Some(head) @@ -1160,9 +1376,9 @@ pub mod raw { * if the slice is empty. O(1). */ #[inline] - pub unsafe fn pop_ptr(slice: &mut Slice) -> Option<*T> { + pub unsafe fn pop_ptr(slice: &mut Slice) -> Option<*const T> { if slice.len == 0 { return None; } - let tail: *T = slice.data.offset((slice.len - 1) as int); + let tail: *const T = slice.data.offset((slice.len - 1) as int); slice.len -= 1; Some(tail) } @@ -1199,224 +1415,56 @@ pub mod bytes { } } -/// Immutable slice iterator -pub struct Items<'a, T> { - ptr: *T, - end: *T, - marker: marker::ContravariantLifetime<'a> -} - -/// Mutable slice iterator -pub struct MutItems<'a, T> { - ptr: *mut T, - end: *mut T, - marker: marker::ContravariantLifetime<'a>, - marker2: marker::NoCopy -} - -macro_rules! iterator { - (struct $name:ident -> $ptr:ty, $elem:ty) => { - impl<'a, T> Iterator<$elem> for $name<'a, T> { - #[inline] - fn next(&mut self) -> Option<$elem> { - // could be implemented with slices, but this avoids bounds checks - unsafe { - if self.ptr == self.end { - None - } else { - let old = self.ptr; - self.ptr = if mem::size_of::() == 0 { - // purposefully don't use 'ptr.offset' because for - // vectors with 0-size elements this would return the - // same pointer. - transmute(self.ptr as uint + 1) - } else { - self.ptr.offset(1) - }; - Some(transmute(old)) - } - } - } - #[inline] - fn size_hint(&self) -> (uint, Option) { - let diff = (self.end as uint) - (self.ptr as uint); - let size = mem::size_of::(); - let exact = diff / (if size == 0 {1} else {size}); - (exact, Some(exact)) - } - } - impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<$elem> { - // could be implemented with slices, but this avoids bounds checks - unsafe { - if self.end == self.ptr { - None - } else { - self.end = if mem::size_of::() == 0 { - // See above for why 'ptr.offset' isn't used - transmute(self.end as uint - 1) - } else { - self.end.offset(-1) - }; - Some(transmute(self.end)) - } - } - } - } - } -} +// +// Boilerplate traits +// -impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { - #[inline] - fn indexable(&self) -> uint { - let (exact, _) = self.size_hint(); - exact +impl<'a,T:PartialEq> PartialEq for &'a [T] { + fn eq(&self, other: & &'a [T]) -> bool { + self.len() == other.len() && + order::eq(self.iter(), other.iter()) } - - #[inline] - fn idx(&mut self, index: uint) -> Option<&'a T> { - unsafe { - if index < self.indexable() { - transmute(self.ptr.offset(index as int)) - } else { - None - } - } + fn ne(&self, other: & &'a [T]) -> bool { + self.len() != other.len() || + order::ne(self.iter(), other.iter()) } } -iterator!{struct Items -> *T, &'a T} - -impl<'a, T> ExactSize<&'a T> for Items<'a, T> {} -impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {} - -impl<'a, T> Clone for Items<'a, T> { - fn clone(&self) -> Items<'a, T> { *self } -} - -iterator!{struct MutItems -> *mut T, &'a mut T} - -/// An iterator over the subslices of the vector which are separated -/// by elements that match `pred`. -pub struct MutSplits<'a, T> { - v: &'a mut [T], - pred: |t: &T|: 'a -> bool, - finished: bool -} +impl<'a,T:Eq> Eq for &'a [T] {} -impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> { +impl<'a,T:PartialEq, V: Vector> Equiv for &'a [T] { #[inline] - fn next(&mut self) -> Option<&'a mut [T]> { - if self.finished { return None; } + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } +} - let pred = &mut self.pred; - match self.v.iter().position(|x| (*pred)(x)) { - None => { - self.finished = true; - let tmp = mem::replace(&mut self.v, &mut []); - let len = tmp.len(); - let (head, tail) = tmp.mut_split_at(len); - self.v = tail; - Some(head) - } - Some(idx) => { - let tmp = mem::replace(&mut self.v, &mut []); - let (head, tail) = tmp.mut_split_at(idx); - self.v = tail.mut_slice_from(1); - Some(head) - } - } +impl<'a,T:Ord> Ord for &'a [T] { + fn cmp(&self, other: & &'a [T]) -> Ordering { + order::cmp(self.iter(), other.iter()) } +} +impl<'a, T: PartialOrd> PartialOrd for &'a [T] { #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.finished { - (0, Some(0)) - } else { - // if the predicate doesn't match anything, we yield one slice - // if it matches every element, we yield len+1 empty slices. - (1, Some(self.v.len() + 1)) - } + fn partial_cmp(&self, other: &&'a [T]) -> Option { + order::partial_cmp(self.iter(), other.iter()) } -} - -impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> { #[inline] - fn next_back(&mut self) -> Option<&'a mut [T]> { - if self.finished { return None; } - - let pred = &mut self.pred; - match self.v.iter().rposition(|x| (*pred)(x)) { - None => { - self.finished = true; - let tmp = mem::replace(&mut self.v, &mut []); - Some(tmp) - } - Some(idx) => { - let tmp = mem::replace(&mut self.v, &mut []); - let (head, tail) = tmp.mut_split_at(idx); - self.v = head; - Some(tail.mut_slice_from(1)) - } - } + fn lt(&self, other: & &'a [T]) -> bool { + order::lt(self.iter(), other.iter()) } -} - -/// An iterator over a vector in (non-overlapping) mutable chunks (`size` elements at a time). When -/// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be -/// the remainder. -pub struct MutChunks<'a, T> { - v: &'a mut [T], - chunk_size: uint -} - -impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> { #[inline] - fn next(&mut self) -> Option<&'a mut [T]> { - if self.v.len() == 0 { - None - } else { - let sz = cmp::min(self.v.len(), self.chunk_size); - let tmp = mem::replace(&mut self.v, &mut []); - let (head, tail) = tmp.mut_split_at(sz); - self.v = tail; - Some(head) - } + fn le(&self, other: & &'a [T]) -> bool { + order::le(self.iter(), other.iter()) } - #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.v.len() == 0 { - (0, Some(0)) - } else { - let (n, rem) = div_rem(self.v.len(), self.chunk_size); - let n = if rem > 0 { n + 1 } else { n }; - (n, Some(n)) - } + fn ge(&self, other: & &'a [T]) -> bool { + order::ge(self.iter(), other.iter()) } -} - -impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> { #[inline] - fn next_back(&mut self) -> Option<&'a mut [T]> { - if self.v.len() == 0 { - None - } else { - let remainder = self.v.len() % self.chunk_size; - let sz = if remainder != 0 { remainder } else { self.chunk_size }; - let tmp = mem::replace(&mut self.v, &mut []); - let tmp_len = tmp.len(); - let (head, tail) = tmp.mut_split_at(tmp_len - sz); - self.v = head; - Some(tail) - } + fn gt(&self, other: & &'a [T]) -> bool { + order::gt(self.iter(), other.iter()) } } - -impl<'a, T> Default for &'a [T] { - fn default() -> &'a [T] { &[] } -} diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 13efeab57d492..94df7a5a6c2d9 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -16,6 +16,7 @@ use mem; use char; +use char::Char; use clone::Clone; use cmp; use cmp::{PartialEq, Eq}; @@ -24,7 +25,7 @@ use default::Default; use iter::{Filter, Map, Iterator}; use iter::{DoubleEndedIterator, ExactSize}; use iter::range; -use num::Saturating; +use num::{CheckedMul, Saturating}; use option::{None, Option, Some}; use raw::Repr; use slice::ImmutableVector; @@ -557,6 +558,41 @@ impl<'a> Iterator<&'a str> for StrSplits<'a> { } } +/// External iterator for a string's UTF16 codeunits. +/// Use with the `std::iter` module. +#[deriving(Clone)] +pub struct Utf16CodeUnits<'a> { + chars: Chars<'a>, + extra: u16 +} + +impl<'a> Iterator for Utf16CodeUnits<'a> { + #[inline] + fn next(&mut self) -> Option { + if self.extra != 0 { + let tmp = self.extra; + self.extra = 0; + return Some(tmp); + } + + let mut buf = [0u16, ..2]; + self.chars.next().map(|ch| { + let n = ch.encode_utf16(buf /* as mut slice! */); + if n == 2 { self.extra = buf[1]; } + buf[0] + }) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (low, high) = self.chars.size_hint(); + // every char gets either one u16 or two u16, + // so this iterator is between 1 or 2 times as + // long as the underlying iterator. + (low, high.and_then(|n| n.checked_mul(&2))) + } +} + /* Section: Comparing strings */ @@ -568,10 +604,10 @@ Section: Comparing strings #[inline] fn eq_slice_(a: &str, b: &str) -> bool { #[allow(ctypes)] - extern { fn memcmp(s1: *i8, s2: *i8, n: uint) -> i32; } + extern { fn memcmp(s1: *const i8, s2: *const i8, n: uint) -> i32; } a.len() == b.len() && unsafe { - memcmp(a.as_ptr() as *i8, - b.as_ptr() as *i8, + memcmp(a.as_ptr() as *const i8, + b.as_ptr() as *const i8, a.len()) == 0 } } @@ -579,20 +615,12 @@ fn eq_slice_(a: &str, b: &str) -> bool { /// Bytewise slice equality /// NOTE: This function is (ab)used in rustc::middle::trans::_match /// to compare &[u8] byte slices that are not necessarily valid UTF-8. -#[cfg(not(test))] #[lang="str_eq"] #[inline] pub fn eq_slice(a: &str, b: &str) -> bool { eq_slice_(a, b) } -/// Bytewise slice equality -#[cfg(test)] -#[inline] -pub fn eq_slice(a: &str, b: &str) -> bool { - eq_slice_(a, b) -} - /* Section: Misc */ @@ -888,8 +916,8 @@ pub mod raw { /// Form a slice from a C string. Unsafe because the caller must ensure the /// C string has the static lifetime, or else the return value may be /// invalidated later. - pub unsafe fn c_str_to_static_slice(s: *i8) -> &'static str { - let s = s as *u8; + pub unsafe fn c_str_to_static_slice(s: *const i8) -> &'static str { + let s = s as *const u8; let mut curr = s; let mut len = 0u; while *curr != 0u8 { @@ -934,13 +962,12 @@ pub mod raw { Section: Trait implementations */ -#[cfg(not(test))] #[allow(missing_doc)] pub mod traits { use cmp::{Ord, Ordering, Less, Equal, Greater, PartialEq, PartialOrd, Equiv, Eq}; use collections::Collection; use iter::Iterator; - use option::{Some, None}; + use option::{Option, Some, None}; use str::{Str, StrSlice, eq_slice}; impl<'a> Ord for &'a str { @@ -971,7 +998,9 @@ pub mod traits { impl<'a> PartialOrd for &'a str { #[inline] - fn lt(&self, other: & &'a str) -> bool { self.cmp(other) == Less } + fn partial_cmp(&self, other: &&'a str) -> Option { + Some(self.cmp(other)) + } } impl<'a, S: Str> Equiv for &'a str { @@ -980,9 +1009,6 @@ pub mod traits { } } -#[cfg(test)] -pub mod traits {} - /// Any string that can be represented as a slice pub trait Str { /// Work with `self` as a slice. @@ -1618,7 +1644,10 @@ pub trait StrSlice<'a> { /// The caller must ensure that the string outlives this pointer, /// and that it is not reallocated (e.g. by pushing to the /// string). - fn as_ptr(&self) -> *u8; + fn as_ptr(&self) -> *const u8; + + /// Return an iterator of `u16` over the string encoded as UTF-16. + fn utf16_units(&self) -> Utf16CodeUnits<'a>; } impl<'a> StrSlice<'a> for &'a str { @@ -1714,7 +1743,7 @@ impl<'a> StrSlice<'a> for &'a str { fn lines_any(&self) -> AnyLines<'a> { self.lines().map(|line| { let l = line.len(); - if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) } + if l > 0 && line.as_bytes()[l - 1] == '\r' as u8 { line.slice(0, l - 1) } else { line } }) } @@ -1838,26 +1867,26 @@ impl<'a> StrSlice<'a> for &'a str { fn is_char_boundary(&self, index: uint) -> bool { if index == self.len() { return true; } if index > self.len() { return false; } - let b = self[index]; + let b = self.as_bytes()[index]; return b < 128u8 || b >= 192u8; } #[inline] fn char_range_at(&self, i: uint) -> CharRange { - if self[i] < 128u8 { - return CharRange {ch: self[i] as char, next: i + 1 }; + if self.as_bytes()[i] < 128u8 { + return CharRange {ch: self.as_bytes()[i] as char, next: i + 1 }; } // Multibyte case is a fn to allow char_range_at to inline cleanly fn multibyte_char_range_at(s: &str, i: uint) -> CharRange { - let mut val = s[i] as u32; + let mut val = s.as_bytes()[i] as u32; let w = UTF8_CHAR_WIDTH[val as uint] as uint; assert!((w != 0)); val = utf8_first_byte!(val, w); - val = utf8_acc_cont_byte!(val, s[i + 1]); - if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); } - if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); } + val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]); + if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); } + if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); } return CharRange {ch: unsafe { mem::transmute(val) }, next: i + w}; } @@ -1870,23 +1899,25 @@ impl<'a> StrSlice<'a> for &'a str { let mut prev = start; prev = prev.saturating_sub(1); - if self[prev] < 128 { return CharRange{ch: self[prev] as char, next: prev} } + if self.as_bytes()[prev] < 128 { + return CharRange{ch: self.as_bytes()[prev] as char, next: prev} + } // Multibyte case is a fn to allow char_range_at_reverse to inline cleanly fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange { // while there is a previous byte == 10...... - while i > 0 && s[i] & 192u8 == TAG_CONT_U8 { + while i > 0 && s.as_bytes()[i] & 192u8 == TAG_CONT_U8 { i -= 1u; } - let mut val = s[i] as u32; + let mut val = s.as_bytes()[i] as u32; let w = UTF8_CHAR_WIDTH[val as uint] as uint; assert!((w != 0)); val = utf8_first_byte!(val, w); - val = utf8_acc_cont_byte!(val, s[i + 1]); - if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); } - if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); } + val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]); + if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); } + if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); } return CharRange {ch: unsafe { mem::transmute(val) }, next: i}; } @@ -1964,9 +1995,14 @@ impl<'a> StrSlice<'a> for &'a str { } #[inline] - fn as_ptr(&self) -> *u8 { + fn as_ptr(&self) -> *const u8 { self.repr().data } + + #[inline] + fn utf16_units(&self) -> Utf16CodeUnits<'a> { + Utf16CodeUnits{ chars: self.chars(), extra: 0} + } } impl<'a> Default for &'a str { diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 3508da5d51628..0e3722894bc46 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -62,8 +62,9 @@ #![doc(primitive = "tuple")] use clone::Clone; -#[cfg(not(test))] use cmp::*; -#[cfg(not(test))] use default::Default; +use cmp::*; +use default::Default; +use option::{Option, Some}; // macro for implementing n-ary tuple functions and operations macro_rules! tuple_impls { @@ -111,7 +112,6 @@ macro_rules! tuple_impls { } } - #[cfg(not(test))] impl<$($T:PartialEq),+> PartialEq for ($($T,)+) { #[inline] fn eq(&self, other: &($($T,)+)) -> bool { @@ -123,11 +123,13 @@ macro_rules! tuple_impls { } } - #[cfg(not(test))] impl<$($T:Eq),+> Eq for ($($T,)+) {} - #[cfg(not(test))] impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) { + #[inline] + fn partial_cmp(&self, other: &($($T,)+)) -> Option { + lexical_partial_cmp!($(self.$refN(), other.$refN()),+) + } #[inline] fn lt(&self, other: &($($T,)+)) -> bool { lexical_ord!(lt, $(self.$refN(), other.$refN()),+) @@ -146,7 +148,6 @@ macro_rules! tuple_impls { } } - #[cfg(not(test))] impl<$($T:Ord),+> Ord for ($($T,)+) { #[inline] fn cmp(&self, other: &($($T,)+)) -> Ordering { @@ -154,7 +155,6 @@ macro_rules! tuple_impls { } } - #[cfg(not(test))] impl<$($T:Default),+> Default for ($($T,)+) { #[inline] fn default() -> ($($T,)+) { @@ -177,6 +177,16 @@ macro_rules! lexical_ord { ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) }; } +macro_rules! lexical_partial_cmp { + ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + match ($a).partial_cmp($b) { + Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+), + ordering => ordering + } + }; + ($a:expr, $b:expr) => { ($a).partial_cmp($b) }; +} + macro_rules! lexical_cmp { ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { match ($a).cmp($b) { @@ -292,93 +302,3 @@ tuple_impls! { } } -#[cfg(test)] -mod tests { - use super::*; - use clone::Clone; - use cmp::*; - use realstd::str::Str; - - #[test] - fn test_clone() { - let a = (1i, "2"); - let b = a.clone(); - assert_eq!(a, b); - } - - #[test] - fn test_getters() { - macro_rules! test_getter( - ($x:expr, $valN:ident, $refN:ident, $mutN:ident, - $init:expr, $incr:expr, $result:expr) => ({ - assert_eq!($x.$valN(), $init); - assert_eq!(*$x.$refN(), $init); - *$x.$mutN() += $incr; - assert_eq!(*$x.$refN(), $result); - }) - ) - let mut x = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64); - test_getter!(x, val0, ref0, mut0, 0, 1, 1); - test_getter!(x, val1, ref1, mut1, 1, 1, 2); - test_getter!(x, val2, ref2, mut2, 2, 1, 3); - test_getter!(x, val3, ref3, mut3, 3, 1, 4); - test_getter!(x, val4, ref4, mut4, 4, 1, 5); - test_getter!(x, val5, ref5, mut5, 5, 1, 6); - test_getter!(x, val6, ref6, mut6, 6, 1, 7); - test_getter!(x, val7, ref7, mut7, 7, 1, 8); - test_getter!(x, val8, ref8, mut8, 8, 1, 9); - test_getter!(x, val9, ref9, mut9, 9, 1, 10); - test_getter!(x, val10, ref10, mut10, 10.0, 1.0, 11.0); - test_getter!(x, val11, ref11, mut11, 11.0, 1.0, 12.0); - } - - #[test] - fn test_tuple_cmp() { - let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u)); - - let nan = 0.0f64/0.0; - - // PartialEq - assert_eq!(small, small); - assert_eq!(big, big); - assert!(small != big); - assert!(big != small); - - // PartialOrd - assert!(small < big); - assert!(!(small < small)); - assert!(!(big < small)); - assert!(!(big < big)); - - assert!(small <= small); - assert!(big <= big); - - assert!(big > small); - assert!(small >= small); - assert!(big >= small); - assert!(big >= big); - - assert!(!((1.0f64, 2.0f64) < (nan, 3.0))); - assert!(!((1.0f64, 2.0f64) <= (nan, 3.0))); - assert!(!((1.0f64, 2.0f64) > (nan, 3.0))); - assert!(!((1.0f64, 2.0f64) >= (nan, 3.0))); - assert!(((1.0f64, 2.0f64) < (2.0, nan))); - assert!(!((2.0f64, 2.0f64) < (2.0, nan))); - - // Ord - assert!(small.cmp(&small) == Equal); - assert!(big.cmp(&big) == Equal); - assert!(small.cmp(&big) == Less); - assert!(big.cmp(&small) == Greater); - } - - #[test] - fn test_show() { - let s = format!("{}", (1i,)); - assert_eq!(s.as_slice(), "(1,)"); - let s = format!("{}", (1i, true)); - assert_eq!(s.as_slice(), "(1, true)"); - let s = format!("{}", (1i, "hi", true)); - assert_eq!(s.as_slice(), "(1, hi, true)"); - } -} diff --git a/src/libcore/ty.rs b/src/libcore/ty.rs index 47a2005fef1e6..5bdab6a78ca33 100644 --- a/src/libcore/ty.rs +++ b/src/libcore/ty.rs @@ -62,7 +62,7 @@ impl Unsafe { /// Gets a mutable pointer to the wrapped value #[inline] - pub unsafe fn get(&self) -> *mut T { &self.value as *T as *mut T } + pub unsafe fn get(&self) -> *mut T { &self.value as *const T as *mut T } /// Unwraps the value #[inline] diff --git a/src/libcoretest/any.rs b/src/libcoretest/any.rs new file mode 100644 index 0000000000000..fae4a26cd3863 --- /dev/null +++ b/src/libcoretest/any.rs @@ -0,0 +1,131 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +use core::any::*; +use test::Bencher; +use test; + +#[deriving(PartialEq, Show)] +struct Test; + +static TEST: &'static str = "Test"; + +#[test] +fn any_referenced() { + let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any); + + assert!(a.is::()); + assert!(!b.is::()); + assert!(!c.is::()); + + assert!(!a.is::<&'static str>()); + assert!(b.is::<&'static str>()); + assert!(!c.is::<&'static str>()); + + assert!(!a.is::()); + assert!(!b.is::()); + assert!(c.is::()); +} + +#[test] +fn any_owning() { + let (a, b, c) = (box 5u as Box, box TEST as Box, box Test as Box); + + assert!(a.is::()); + assert!(!b.is::()); + assert!(!c.is::()); + + assert!(!a.is::<&'static str>()); + assert!(b.is::<&'static str>()); + assert!(!c.is::<&'static str>()); + + assert!(!a.is::()); + assert!(!b.is::()); + assert!(c.is::()); +} + +#[test] +fn any_as_ref() { + let a = &5u as &Any; + + match a.as_ref::() { + Some(&5) => {} + x => fail!("Unexpected value {}", x) + } + + match a.as_ref::() { + None => {} + x => fail!("Unexpected value {}", x) + } +} + +#[test] +fn any_as_mut() { + let mut a = 5u; + let mut b = box 7u; + + let a_r = &mut a as &mut Any; + let tmp: &mut uint = &mut *b; + let b_r = tmp as &mut Any; + + match a_r.as_mut::() { + Some(x) => { + assert_eq!(*x, 5u); + *x = 612; + } + x => fail!("Unexpected value {}", x) + } + + match b_r.as_mut::() { + Some(x) => { + assert_eq!(*x, 7u); + *x = 413; + } + x => fail!("Unexpected value {}", x) + } + + match a_r.as_mut::() { + None => (), + x => fail!("Unexpected value {}", x) + } + + match b_r.as_mut::() { + None => (), + x => fail!("Unexpected value {}", x) + } + + match a_r.as_mut::() { + Some(&612) => {} + x => fail!("Unexpected value {}", x) + } + + match b_r.as_mut::() { + Some(&413) => {} + x => fail!("Unexpected value {}", x) + } +} + +#[test] +fn any_fixed_vec() { + let test = [0u, ..8]; + let test = &test as &Any; + assert!(test.is::<[uint, ..8]>()); + assert!(!test.is::<[uint, ..10]>()); +} + + +#[bench] +fn bench_as_ref(b: &mut Bencher) { + b.iter(|| { + let mut x = 0i; + let mut y = &mut x as &mut Any; + test::black_box(&mut y); + test::black_box(y.as_ref::() == Some(&0)); + }); +} diff --git a/src/libcoretest/atomics.rs b/src/libcoretest/atomics.rs new file mode 100644 index 0000000000000..3f960ae1f267f --- /dev/null +++ b/src/libcoretest/atomics.rs @@ -0,0 +1,83 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::atomics::*; + +#[test] +fn bool_() { + let a = AtomicBool::new(false); + assert_eq!(a.compare_and_swap(false, true, SeqCst), false); + assert_eq!(a.compare_and_swap(false, true, SeqCst), true); + + a.store(false, SeqCst); + assert_eq!(a.compare_and_swap(false, true, SeqCst), false); +} + +#[test] +fn bool_and() { + let a = AtomicBool::new(true); + assert_eq!(a.fetch_and(false, SeqCst),true); + assert_eq!(a.load(SeqCst),false); +} + +#[test] +fn uint_and() { + let x = AtomicUint::new(0xf731); + assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); +} + +#[test] +fn uint_or() { + let x = AtomicUint::new(0xf731); + assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731 | 0x137f); +} + +#[test] +fn uint_xor() { + let x = AtomicUint::new(0xf731); + assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); +} + +#[test] +fn int_and() { + let x = AtomicInt::new(0xf731); + assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731 & 0x137f); +} + +#[test] +fn int_or() { + let x = AtomicInt::new(0xf731); + assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731 | 0x137f); +} + +#[test] +fn int_xor() { + let x = AtomicInt::new(0xf731); + assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); +} + +static mut S_BOOL : AtomicBool = INIT_ATOMIC_BOOL; +static mut S_INT : AtomicInt = INIT_ATOMIC_INT; +static mut S_UINT : AtomicUint = INIT_ATOMIC_UINT; + +#[test] +fn static_init() { + unsafe { + assert!(!S_BOOL.load(SeqCst)); + assert!(S_INT.load(SeqCst) == 0); + assert!(S_UINT.load(SeqCst) == 0); + } +} diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs new file mode 100644 index 0000000000000..b3ae110363cb5 --- /dev/null +++ b/src/libcoretest/cell.rs @@ -0,0 +1,129 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::cell::*; +use std::mem::drop; + +#[test] +fn smoketest_cell() { + let x = Cell::new(10i); + assert!(x == Cell::new(10)); + assert!(x.get() == 10); + x.set(20); + assert!(x == Cell::new(20)); + assert!(x.get() == 20); + + let y = Cell::new((30i, 40i)); + assert!(y == Cell::new((30, 40))); + assert!(y.get() == (30, 40)); +} + +#[test] +fn cell_has_sensible_show() { + let x = Cell::new("foo bar"); + assert!(format!("{}", x).as_slice().contains(x.get())); + + x.set("baz qux"); + assert!(format!("{}", x).as_slice().contains(x.get())); +} + +#[test] +fn ref_and_refmut_have_sensible_show() { + let refcell = RefCell::new("foo"); + + let refcell_refmut = refcell.borrow_mut(); + assert!(format!("{}", refcell_refmut).as_slice().contains("foo")); + drop(refcell_refmut); + + let refcell_ref = refcell.borrow(); + assert!(format!("{}", refcell_ref).as_slice().contains("foo")); + drop(refcell_ref); +} + +#[test] +fn double_imm_borrow() { + let x = RefCell::new(0i); + let _b1 = x.borrow(); + x.borrow(); +} + +#[test] +fn no_mut_then_imm_borrow() { + let x = RefCell::new(0i); + let _b1 = x.borrow_mut(); + assert!(x.try_borrow().is_none()); +} + +#[test] +fn no_imm_then_borrow_mut() { + let x = RefCell::new(0i); + let _b1 = x.borrow(); + assert!(x.try_borrow_mut().is_none()); +} + +#[test] +fn no_double_borrow_mut() { + let x = RefCell::new(0i); + let _b1 = x.borrow_mut(); + assert!(x.try_borrow_mut().is_none()); +} + +#[test] +fn imm_release_borrow_mut() { + let x = RefCell::new(0i); + { + let _b1 = x.borrow(); + } + x.borrow_mut(); +} + +#[test] +fn mut_release_borrow_mut() { + let x = RefCell::new(0i); + { + let _b1 = x.borrow_mut(); + } + x.borrow(); +} + +#[test] +fn double_borrow_single_release_no_borrow_mut() { + let x = RefCell::new(0i); + let _b1 = x.borrow(); + { + let _b2 = x.borrow(); + } + assert!(x.try_borrow_mut().is_none()); +} + +#[test] +#[should_fail] +fn discard_doesnt_unborrow() { + let x = RefCell::new(0i); + let _b = x.borrow(); + let _ = _b; + let _b = x.borrow_mut(); +} + +#[test] +#[allow(experimental)] +fn clone_ref_updates_flag() { + let x = RefCell::new(0i); + { + let b1 = x.borrow(); + assert!(x.try_borrow_mut().is_none()); + { + let _b2 = clone_ref(&b1); + assert!(x.try_borrow_mut().is_none()); + } + assert!(x.try_borrow_mut().is_none()); + } + assert!(x.try_borrow_mut().is_some()); +} diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs new file mode 100644 index 0000000000000..852edd90b0f3f --- /dev/null +++ b/src/libcoretest/char.rs @@ -0,0 +1,202 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::char::{escape_unicode, escape_default}; + +#[test] +fn test_is_lowercase() { + assert!('a'.is_lowercase()); + assert!('ö'.is_lowercase()); + assert!('ß'.is_lowercase()); + assert!(!'Ü'.is_lowercase()); + assert!(!'P'.is_lowercase()); +} + +#[test] +fn test_is_uppercase() { + assert!(!'h'.is_uppercase()); + assert!(!'ä'.is_uppercase()); + assert!(!'ß'.is_uppercase()); + assert!('Ö'.is_uppercase()); + assert!('T'.is_uppercase()); +} + +#[test] +fn test_is_whitespace() { + assert!(' '.is_whitespace()); + assert!('\u2007'.is_whitespace()); + assert!('\t'.is_whitespace()); + assert!('\n'.is_whitespace()); + assert!(!'a'.is_whitespace()); + assert!(!'_'.is_whitespace()); + assert!(!'\u0000'.is_whitespace()); +} + +#[test] +fn test_to_digit() { + assert_eq!('0'.to_digit(10u), Some(0u)); + assert_eq!('1'.to_digit(2u), Some(1u)); + assert_eq!('2'.to_digit(3u), Some(2u)); + assert_eq!('9'.to_digit(10u), Some(9u)); + assert_eq!('a'.to_digit(16u), Some(10u)); + assert_eq!('A'.to_digit(16u), Some(10u)); + assert_eq!('b'.to_digit(16u), Some(11u)); + assert_eq!('B'.to_digit(16u), Some(11u)); + assert_eq!('z'.to_digit(36u), Some(35u)); + assert_eq!('Z'.to_digit(36u), Some(35u)); + assert_eq!(' '.to_digit(10u), None); + assert_eq!('$'.to_digit(36u), None); +} + +#[test] +fn test_to_lowercase() { + assert_eq!('A'.to_lowercase(), 'a'); + assert_eq!('Ö'.to_lowercase(), 'ö'); + assert_eq!('ß'.to_lowercase(), 'ß'); + assert_eq!('Ü'.to_lowercase(), 'ü'); + assert_eq!('💩'.to_lowercase(), '💩'); + assert_eq!('Σ'.to_lowercase(), 'σ'); + assert_eq!('Τ'.to_lowercase(), 'τ'); + assert_eq!('Ι'.to_lowercase(), 'ι'); + assert_eq!('Γ'.to_lowercase(), 'γ'); + assert_eq!('Μ'.to_lowercase(), 'μ'); + assert_eq!('Α'.to_lowercase(), 'α'); + assert_eq!('Σ'.to_lowercase(), 'σ'); +} + +#[test] +fn test_to_uppercase() { + assert_eq!('a'.to_uppercase(), 'A'); + assert_eq!('ö'.to_uppercase(), 'Ö'); + assert_eq!('ß'.to_uppercase(), 'ß'); // not ẞ: Latin capital letter sharp s + assert_eq!('ü'.to_uppercase(), 'Ü'); + assert_eq!('💩'.to_uppercase(), '💩'); + + assert_eq!('σ'.to_uppercase(), 'Σ'); + assert_eq!('τ'.to_uppercase(), 'Τ'); + assert_eq!('ι'.to_uppercase(), 'Ι'); + assert_eq!('γ'.to_uppercase(), 'Γ'); + assert_eq!('μ'.to_uppercase(), 'Μ'); + assert_eq!('α'.to_uppercase(), 'Α'); + assert_eq!('ς'.to_uppercase(), 'Σ'); +} + +#[test] +fn test_is_control() { + assert!('\u0000'.is_control()); + assert!('\u0003'.is_control()); + assert!('\u0006'.is_control()); + assert!('\u0009'.is_control()); + assert!('\u007f'.is_control()); + assert!('\u0092'.is_control()); + assert!(!'\u0020'.is_control()); + assert!(!'\u0055'.is_control()); + assert!(!'\u0068'.is_control()); +} + +#[test] +fn test_is_digit() { + assert!('2'.is_digit()); + assert!('7'.is_digit()); + assert!(!'c'.is_digit()); + assert!(!'i'.is_digit()); + assert!(!'z'.is_digit()); + assert!(!'Q'.is_digit()); +} + +#[test] +fn test_escape_default() { + fn string(c: char) -> String { + let mut result = String::new(); + escape_default(c, |c| { result.push_char(c); }); + return result; + } + let s = string('\n'); + assert_eq!(s.as_slice(), "\\n"); + let s = string('\r'); + assert_eq!(s.as_slice(), "\\r"); + let s = string('\''); + assert_eq!(s.as_slice(), "\\'"); + let s = string('"'); + assert_eq!(s.as_slice(), "\\\""); + let s = string(' '); + assert_eq!(s.as_slice(), " "); + let s = string('a'); + assert_eq!(s.as_slice(), "a"); + let s = string('~'); + assert_eq!(s.as_slice(), "~"); + let s = string('\x00'); + assert_eq!(s.as_slice(), "\\x00"); + let s = string('\x1f'); + assert_eq!(s.as_slice(), "\\x1f"); + let s = string('\x7f'); + assert_eq!(s.as_slice(), "\\x7f"); + let s = string('\xff'); + assert_eq!(s.as_slice(), "\\xff"); + let s = string('\u011b'); + assert_eq!(s.as_slice(), "\\u011b"); + let s = string('\U0001d4b6'); + assert_eq!(s.as_slice(), "\\U0001d4b6"); +} + +#[test] +fn test_escape_unicode() { + fn string(c: char) -> String { + let mut result = String::new(); + escape_unicode(c, |c| { result.push_char(c); }); + return result; + } + let s = string('\x00'); + assert_eq!(s.as_slice(), "\\x00"); + let s = string('\n'); + assert_eq!(s.as_slice(), "\\x0a"); + let s = string(' '); + assert_eq!(s.as_slice(), "\\x20"); + let s = string('a'); + assert_eq!(s.as_slice(), "\\x61"); + let s = string('\u011b'); + assert_eq!(s.as_slice(), "\\u011b"); + let s = string('\U0001d4b6'); + assert_eq!(s.as_slice(), "\\U0001d4b6"); +} + +#[test] +fn test_to_str() { + let s = 't'.to_str(); + assert_eq!(s.as_slice(), "t"); +} + +#[test] +fn test_encode_utf8() { + fn check(input: char, expect: &[u8]) { + let mut buf = [0u8, ..4]; + let n = input.encode_utf8(buf /* as mut slice! */); + assert_eq!(buf.slice_to(n), expect); + } + + check('x', [0x78]); + check('\u00e9', [0xc3, 0xa9]); + check('\ua66e', [0xea, 0x99, 0xae]); + check('\U0001f4a9', [0xf0, 0x9f, 0x92, 0xa9]); +} + +#[test] +fn test_encode_utf16() { + fn check(input: char, expect: &[u16]) { + let mut buf = [0u16, ..2]; + let n = input.encode_utf16(buf /* as mut slice! */); + assert_eq!(buf.slice_to(n), expect); + } + + check('x', [0x0078]); + check('\u00e9', [0x00e9]); + check('\ua66e', [0xa66e]); + check('\U0001f4a9', [0xd83d, 0xdca9]); +} diff --git a/src/libcoretest/clone.rs b/src/libcoretest/clone.rs new file mode 100644 index 0000000000000..67c30d945d497 --- /dev/null +++ b/src/libcoretest/clone.rs @@ -0,0 +1,39 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[test] +fn test_borrowed_clone() { + let x = 5i; + let y: &int = &x; + let z: &int = (&y).clone(); + assert_eq!(*z, 5); +} + +#[test] +fn test_clone_from() { + let a = box 5i; + let mut b = box 10i; + b.clone_from(&a); + assert_eq!(*b, 5); +} + +#[test] +fn test_extern_fn_clone() { + trait Empty {} + impl Empty for int {} + + fn test_fn_a() -> f64 { 1.0 } + fn test_fn_b(x: T) -> T { x } + fn test_fn_c(_: int, _: f64, _: int, _: int, _: int) {} + + let _ = test_fn_a.clone(); + let _ = test_fn_b::.clone(); + let _ = test_fn_c.clone(); +} diff --git a/src/libcoretest/cmp.rs b/src/libcoretest/cmp.rs new file mode 100644 index 0000000000000..88e944be3e860 --- /dev/null +++ b/src/libcoretest/cmp.rs @@ -0,0 +1,69 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::cmp::lexical_ordering; + +#[test] +fn test_int_totalord() { + assert_eq!(5i.cmp(&10), Less); + assert_eq!(10i.cmp(&5), Greater); + assert_eq!(5i.cmp(&5), Equal); + assert_eq!((-5i).cmp(&12), Less); + assert_eq!(12i.cmp(&-5), Greater); +} + +#[test] +fn test_mut_int_totalord() { + assert_eq!((&mut 5i).cmp(&&mut 10), Less); + assert_eq!((&mut 10i).cmp(&&mut 5), Greater); + assert_eq!((&mut 5i).cmp(&&mut 5), Equal); + assert_eq!((&mut -5i).cmp(&&mut 12), Less); + assert_eq!((&mut 12i).cmp(&&mut -5), Greater); +} + +#[test] +fn test_ordering_order() { + assert!(Less < Equal); + assert_eq!(Greater.cmp(&Less), Greater); +} + +#[test] +fn test_lexical_ordering() { + fn t(o1: Ordering, o2: Ordering, e: Ordering) { + assert_eq!(lexical_ordering(o1, o2), e); + } + + let xs = [Less, Equal, Greater]; + for &o in xs.iter() { + t(Less, o, Less); + t(Equal, o, o); + t(Greater, o, Greater); + } +} + +#[test] +fn test_user_defined_eq() { + // Our type. + struct SketchyNum { + num : int + } + + // Our implementation of `PartialEq` to support `==` and `!=`. + impl PartialEq for SketchyNum { + // Our custom eq allows numbers which are near each other to be equal! :D + fn eq(&self, other: &SketchyNum) -> bool { + (self.num - other.num).abs() < 5 + } + } + + // Now these binary operators will work when applied! + assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); + assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); +} diff --git a/src/libcoretest/finally.rs b/src/libcoretest/finally.rs new file mode 100644 index 0000000000000..5da004086d27f --- /dev/null +++ b/src/libcoretest/finally.rs @@ -0,0 +1,59 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::finally::{try_finally, Finally}; +use std::task::failing; + +#[test] +fn test_success() { + let mut i = 0i; + try_finally( + &mut i, (), + |i, ()| { + *i = 10; + }, + |i| { + assert!(!failing()); + assert_eq!(*i, 10); + *i = 20; + }); + assert_eq!(i, 20); +} + +#[test] +#[should_fail] +fn test_fail() { + let mut i = 0i; + try_finally( + &mut i, (), + |i, ()| { + *i = 10; + fail!(); + }, + |i| { + assert!(failing()); + assert_eq!(*i, 10); + }) +} + +#[test] +fn test_retval() { + let mut closure: || -> int = || 10; + let i = closure.finally(|| { }); + assert_eq!(i, 10); +} + +#[test] +fn test_compact() { + fn do_some_fallible_work() {} + fn but_always_run_this_function() { } + let mut f = do_some_fallible_work; + f.finally(but_always_run_this_function); +} diff --git a/src/libcoretest/fmt/mod.rs b/src/libcoretest/fmt/mod.rs new file mode 100644 index 0000000000000..9fc09b3124ef3 --- /dev/null +++ b/src/libcoretest/fmt/mod.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod num; diff --git a/src/libcoretest/fmt/num.rs b/src/libcoretest/fmt/num.rs new file mode 100644 index 0000000000000..baef7e3a11e85 --- /dev/null +++ b/src/libcoretest/fmt/num.rs @@ -0,0 +1,234 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(unsigned_negate)] + +use core::fmt::radix; + +#[test] +fn test_format_int() { + // Formatting integers should select the right implementation based off + // the type of the argument. Also, hex/octal/binary should be defined + // for integers, but they shouldn't emit the negative sign. + assert!(format!("{}", 1i).as_slice() == "1"); + assert!(format!("{}", 1i8).as_slice() == "1"); + assert!(format!("{}", 1i16).as_slice() == "1"); + assert!(format!("{}", 1i32).as_slice() == "1"); + assert!(format!("{}", 1i64).as_slice() == "1"); + assert!(format!("{:d}", -1i).as_slice() == "-1"); + assert!(format!("{:d}", -1i8).as_slice() == "-1"); + assert!(format!("{:d}", -1i16).as_slice() == "-1"); + assert!(format!("{:d}", -1i32).as_slice() == "-1"); + assert!(format!("{:d}", -1i64).as_slice() == "-1"); + assert!(format!("{:t}", 1i).as_slice() == "1"); + assert!(format!("{:t}", 1i8).as_slice() == "1"); + assert!(format!("{:t}", 1i16).as_slice() == "1"); + assert!(format!("{:t}", 1i32).as_slice() == "1"); + assert!(format!("{:t}", 1i64).as_slice() == "1"); + assert!(format!("{:x}", 1i).as_slice() == "1"); + assert!(format!("{:x}", 1i8).as_slice() == "1"); + assert!(format!("{:x}", 1i16).as_slice() == "1"); + assert!(format!("{:x}", 1i32).as_slice() == "1"); + assert!(format!("{:x}", 1i64).as_slice() == "1"); + assert!(format!("{:X}", 1i).as_slice() == "1"); + assert!(format!("{:X}", 1i8).as_slice() == "1"); + assert!(format!("{:X}", 1i16).as_slice() == "1"); + assert!(format!("{:X}", 1i32).as_slice() == "1"); + assert!(format!("{:X}", 1i64).as_slice() == "1"); + assert!(format!("{:o}", 1i).as_slice() == "1"); + assert!(format!("{:o}", 1i8).as_slice() == "1"); + assert!(format!("{:o}", 1i16).as_slice() == "1"); + assert!(format!("{:o}", 1i32).as_slice() == "1"); + assert!(format!("{:o}", 1i64).as_slice() == "1"); + + assert!(format!("{}", 1u).as_slice() == "1"); + assert!(format!("{}", 1u8).as_slice() == "1"); + assert!(format!("{}", 1u16).as_slice() == "1"); + assert!(format!("{}", 1u32).as_slice() == "1"); + assert!(format!("{}", 1u64).as_slice() == "1"); + assert!(format!("{:u}", 1u).as_slice() == "1"); + assert!(format!("{:u}", 1u8).as_slice() == "1"); + assert!(format!("{:u}", 1u16).as_slice() == "1"); + assert!(format!("{:u}", 1u32).as_slice() == "1"); + assert!(format!("{:u}", 1u64).as_slice() == "1"); + assert!(format!("{:t}", 1u).as_slice() == "1"); + assert!(format!("{:t}", 1u8).as_slice() == "1"); + assert!(format!("{:t}", 1u16).as_slice() == "1"); + assert!(format!("{:t}", 1u32).as_slice() == "1"); + assert!(format!("{:t}", 1u64).as_slice() == "1"); + assert!(format!("{:x}", 1u).as_slice() == "1"); + assert!(format!("{:x}", 1u8).as_slice() == "1"); + assert!(format!("{:x}", 1u16).as_slice() == "1"); + assert!(format!("{:x}", 1u32).as_slice() == "1"); + assert!(format!("{:x}", 1u64).as_slice() == "1"); + assert!(format!("{:X}", 1u).as_slice() == "1"); + assert!(format!("{:X}", 1u8).as_slice() == "1"); + assert!(format!("{:X}", 1u16).as_slice() == "1"); + assert!(format!("{:X}", 1u32).as_slice() == "1"); + assert!(format!("{:X}", 1u64).as_slice() == "1"); + assert!(format!("{:o}", 1u).as_slice() == "1"); + assert!(format!("{:o}", 1u8).as_slice() == "1"); + assert!(format!("{:o}", 1u16).as_slice() == "1"); + assert!(format!("{:o}", 1u32).as_slice() == "1"); + assert!(format!("{:o}", 1u64).as_slice() == "1"); + + // Test a larger number + assert!(format!("{:t}", 55i).as_slice() == "110111"); + assert!(format!("{:o}", 55i).as_slice() == "67"); + assert!(format!("{:d}", 55i).as_slice() == "55"); + assert!(format!("{:x}", 55i).as_slice() == "37"); + assert!(format!("{:X}", 55i).as_slice() == "37"); +} + +#[test] +fn test_format_int_zero() { + assert!(format!("{}", 0i).as_slice() == "0"); + assert!(format!("{:d}", 0i).as_slice() == "0"); + assert!(format!("{:t}", 0i).as_slice() == "0"); + assert!(format!("{:o}", 0i).as_slice() == "0"); + assert!(format!("{:x}", 0i).as_slice() == "0"); + assert!(format!("{:X}", 0i).as_slice() == "0"); + + assert!(format!("{}", 0u).as_slice() == "0"); + assert!(format!("{:u}", 0u).as_slice() == "0"); + assert!(format!("{:t}", 0u).as_slice() == "0"); + assert!(format!("{:o}", 0u).as_slice() == "0"); + assert!(format!("{:x}", 0u).as_slice() == "0"); + assert!(format!("{:X}", 0u).as_slice() == "0"); +} + +#[test] +fn test_format_int_flags() { + assert!(format!("{:3d}", 1i).as_slice() == " 1"); + assert!(format!("{:>3d}", 1i).as_slice() == " 1"); + assert!(format!("{:>+3d}", 1i).as_slice() == " +1"); + assert!(format!("{:<3d}", 1i).as_slice() == "1 "); + assert!(format!("{:#d}", 1i).as_slice() == "1"); + assert!(format!("{:#x}", 10i).as_slice() == "0xa"); + assert!(format!("{:#X}", 10i).as_slice() == "0xA"); + assert!(format!("{:#5x}", 10i).as_slice() == " 0xa"); + assert!(format!("{:#o}", 10i).as_slice() == "0o12"); + assert!(format!("{:08x}", 10i).as_slice() == "0000000a"); + assert!(format!("{:8x}", 10i).as_slice() == " a"); + assert!(format!("{:<8x}", 10i).as_slice() == "a "); + assert!(format!("{:>8x}", 10i).as_slice() == " a"); + assert!(format!("{:#08x}", 10i).as_slice() == "0x00000a"); + assert!(format!("{:08d}", -10i).as_slice() == "-0000010"); + assert!(format!("{:x}", -1u8).as_slice() == "ff"); + assert!(format!("{:X}", -1u8).as_slice() == "FF"); + assert!(format!("{:t}", -1u8).as_slice() == "11111111"); + assert!(format!("{:o}", -1u8).as_slice() == "377"); + assert!(format!("{:#x}", -1u8).as_slice() == "0xff"); + assert!(format!("{:#X}", -1u8).as_slice() == "0xFF"); + assert!(format!("{:#t}", -1u8).as_slice() == "0b11111111"); + assert!(format!("{:#o}", -1u8).as_slice() == "0o377"); +} + +#[test] +fn test_format_int_sign_padding() { + assert!(format!("{:+5d}", 1i).as_slice() == " +1"); + assert!(format!("{:+5d}", -1i).as_slice() == " -1"); + assert!(format!("{:05d}", 1i).as_slice() == "00001"); + assert!(format!("{:05d}", -1i).as_slice() == "-0001"); + assert!(format!("{:+05d}", 1i).as_slice() == "+0001"); + assert!(format!("{:+05d}", -1i).as_slice() == "-0001"); +} + +#[test] +fn test_format_int_twos_complement() { + use core::{i8, i16, i32, i64}; + assert!(format!("{}", i8::MIN).as_slice() == "-128"); + assert!(format!("{}", i16::MIN).as_slice() == "-32768"); + assert!(format!("{}", i32::MIN).as_slice() == "-2147483648"); + assert!(format!("{}", i64::MIN).as_slice() == "-9223372036854775808"); +} + +#[test] +fn test_format_radix() { + assert!(format!("{:04}", radix(3i, 2)).as_slice() == "0011"); + assert!(format!("{}", radix(55i, 36)).as_slice() == "1j"); +} + +#[test] +#[should_fail] +fn test_radix_base_too_large() { + let _ = radix(55i, 37); +} + +mod uint { + use test::Bencher; + use core::fmt::radix; + use std::rand::{weak_rng, Rng}; + + #[bench] + fn format_bin(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:t}", rng.gen::()); }) + } + + #[bench] + fn format_oct(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:o}", rng.gen::()); }) + } + + #[bench] + fn format_dec(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:u}", rng.gen::()); }) + } + + #[bench] + fn format_hex(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:x}", rng.gen::()); }) + } + + #[bench] + fn format_base_36(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) + } +} + +mod int { + use test::Bencher; + use core::fmt::radix; + use std::rand::{weak_rng, Rng}; + + #[bench] + fn format_bin(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:t}", rng.gen::()); }) + } + + #[bench] + fn format_oct(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:o}", rng.gen::()); }) + } + + #[bench] + fn format_dec(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:d}", rng.gen::()); }) + } + + #[bench] + fn format_hex(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{:x}", rng.gen::()); }) + } + + #[bench] + fn format_base_36(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) + } +} diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs new file mode 100644 index 0000000000000..86b5ffece4103 --- /dev/null +++ b/src/libcoretest/iter.rs @@ -0,0 +1,835 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::iter::*; +use core::iter::order::*; +use core::uint; +use core::cmp; +use core::num; + +#[test] +fn test_lt() { + let empty: [int, ..0] = []; + let xs = [1i,2,3]; + let ys = [1i,2,0]; + + assert!(!lt(xs.iter(), ys.iter())); + assert!(!le(xs.iter(), ys.iter())); + assert!( gt(xs.iter(), ys.iter())); + assert!( ge(xs.iter(), ys.iter())); + + assert!( lt(ys.iter(), xs.iter())); + assert!( le(ys.iter(), xs.iter())); + assert!(!gt(ys.iter(), xs.iter())); + assert!(!ge(ys.iter(), xs.iter())); + + assert!( lt(empty.iter(), xs.iter())); + assert!( le(empty.iter(), xs.iter())); + assert!(!gt(empty.iter(), xs.iter())); + assert!(!ge(empty.iter(), xs.iter())); + + // Sequence with NaN + let u = [1.0f64, 2.0]; + let v = [0.0f64/0.0, 3.0]; + + assert!(!lt(u.iter(), v.iter())); + assert!(!le(u.iter(), v.iter())); + assert!(!gt(u.iter(), v.iter())); + assert!(!ge(u.iter(), v.iter())); + + let a = [0.0f64/0.0]; + let b = [1.0f64]; + let c = [2.0f64]; + + assert!(lt(a.iter(), b.iter()) == (a[0] < b[0])); + assert!(le(a.iter(), b.iter()) == (a[0] <= b[0])); + assert!(gt(a.iter(), b.iter()) == (a[0] > b[0])); + assert!(ge(a.iter(), b.iter()) == (a[0] >= b[0])); + + assert!(lt(c.iter(), b.iter()) == (c[0] < b[0])); + assert!(le(c.iter(), b.iter()) == (c[0] <= b[0])); + assert!(gt(c.iter(), b.iter()) == (c[0] > b[0])); + assert!(ge(c.iter(), b.iter()) == (c[0] >= b[0])); +} + +#[test] +fn test_multi_iter() { + let xs = [1i,2,3,4]; + let ys = [4i,3,2,1]; + assert!(eq(xs.iter(), ys.iter().rev())); + assert!(lt(xs.iter(), xs.iter().skip(2))); +} + +#[test] +fn test_counter_from_iter() { + let it = count(0i, 5).take(10); + let xs: Vec = FromIterator::from_iter(it); + assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); +} + +#[test] +fn test_iterator_chain() { + let xs = [0u, 1, 2, 3, 4, 5]; + let ys = [30u, 40, 50, 60]; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + let mut it = xs.iter().chain(ys.iter()); + let mut i = 0; + for &x in it { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); + + let ys = count(30u, 10).take(4); + let mut it = xs.iter().map(|&x| x).chain(ys); + let mut i = 0; + for x in it { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); +} + +#[test] +fn test_filter_map() { + let mut it = count(0u, 1u).take(10) + .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); + assert!(it.collect::>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]); +} + +#[test] +fn test_iterator_enumerate() { + let xs = [0u, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + for (i, &x) in it { + assert_eq!(i, x); + } +} + +#[test] +fn test_iterator_peekable() { + let xs = vec![0u, 1, 2, 3, 4, 5]; + let mut it = xs.iter().map(|&x|x).peekable(); + assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.next().unwrap(), 0); + assert_eq!(it.next().unwrap(), 1); + assert_eq!(it.next().unwrap(), 2); + assert_eq!(it.peek().unwrap(), &3); + assert_eq!(it.peek().unwrap(), &3); + assert_eq!(it.next().unwrap(), 3); + assert_eq!(it.next().unwrap(), 4); + assert_eq!(it.peek().unwrap(), &5); + assert_eq!(it.next().unwrap(), 5); + assert!(it.peek().is_none()); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_take_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5, 13]; + let mut it = xs.iter().take_while(|&x| *x < 15u); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); +} + +#[test] +fn test_iterator_skip_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let mut it = xs.iter().skip_while(|&x| *x < 15u); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); +} + +#[test] +fn test_iterator_skip() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let mut it = xs.iter().skip(5); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); +} + +#[test] +fn test_iterator_take() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5]; + let mut it = xs.iter().take(5); + let mut i = 0; + for &x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); +} + +#[test] +fn test_iterator_scan() { + // test the type inference + fn add(old: &mut int, new: &uint) -> Option { + *old += *new as int; + Some(*old as f64) + } + let xs = [0u, 1, 2, 3, 4]; + let ys = [0f64, 1.0, 3.0, 6.0, 10.0]; + + let mut it = xs.iter().scan(0, add); + let mut i = 0; + for x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); +} + +#[test] +fn test_iterator_flat_map() { + let xs = [0u, 3, 6]; + let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8]; + let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3)); + let mut i = 0; + for x in it { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); +} + +#[test] +fn test_inspect() { + let xs = [1u, 2, 3, 4]; + let mut n = 0; + + let ys = xs.iter() + .map(|&x| x) + .inspect(|_| n += 1) + .collect::>(); + + assert_eq!(n, xs.len()); + assert_eq!(xs.as_slice(), ys.as_slice()); +} + +#[test] +fn test_unfoldr() { + fn count(st: &mut uint) -> Option { + if *st < 10 { + let ret = Some(*st); + *st += 1; + ret + } else { + None + } + } + + let mut it = Unfold::new(0, count); + let mut i = 0; + for counted in it { + assert_eq!(counted, i); + i += 1; + } + assert_eq!(i, 10); +} + +#[test] +fn test_cycle() { + let cycle_len = 3; + let it = count(0u, 1).take(cycle_len).cycle(); + assert_eq!(it.size_hint(), (uint::MAX, None)); + for (i, x) in it.take(100).enumerate() { + assert_eq!(i % cycle_len, x); + } + + let mut it = count(0u, 1).take(0).cycle(); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iterator_nth() { + let v = &[0i, 1, 2, 3, 4]; + for i in range(0u, v.len()) { + assert_eq!(v.iter().nth(i).unwrap(), &v[i]); + } +} + +#[test] +fn test_iterator_last() { + let v = &[0i, 1, 2, 3, 4]; + assert_eq!(v.iter().last().unwrap(), &4); + assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0); +} + +#[test] +fn test_iterator_len() { + let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().count(), 4); + assert_eq!(v.slice(0, 10).iter().count(), 10); + assert_eq!(v.slice(0, 0).iter().count(), 0); +} + +#[test] +fn test_iterator_sum() { + let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).sum(), 6); + assert_eq!(v.iter().map(|&x| x).sum(), 55); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).sum(), 0); +} + +#[test] +fn test_iterator_product() { + let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).product(), 0); + assert_eq!(v.slice(1, 5).iter().map(|&x| x).product(), 24); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).product(), 1); +} + +#[test] +fn test_iterator_max() { + let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).max(), Some(3)); + assert_eq!(v.iter().map(|&x| x).max(), Some(10)); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).max(), None); +} + +#[test] +fn test_iterator_min() { + let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().map(|&x| x).min(), Some(0)); + assert_eq!(v.iter().map(|&x| x).min(), Some(0)); + assert_eq!(v.slice(0, 0).iter().map(|&x| x).min(), None); +} + +#[test] +fn test_iterator_size_hint() { + let c = count(0i, 1); + let v = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let v2 = &[10i, 11, 12]; + let vi = v.iter(); + + assert_eq!(c.size_hint(), (uint::MAX, None)); + assert_eq!(vi.size_hint(), (10, Some(10))); + + assert_eq!(c.take(5).size_hint(), (5, Some(5))); + assert_eq!(c.skip(5).size_hint().val1(), None); + assert_eq!(c.take_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.skip_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.enumerate().size_hint(), (uint::MAX, None)); + assert_eq!(c.chain(vi.map(|&i| i)).size_hint(), (uint::MAX, None)); + assert_eq!(c.zip(vi).size_hint(), (10, Some(10))); + assert_eq!(c.scan(0i, |_,_| Some(0i)).size_hint(), (0, None)); + assert_eq!(c.filter(|_| false).size_hint(), (0, None)); + assert_eq!(c.map(|_| 0i).size_hint(), (uint::MAX, None)); + assert_eq!(c.filter_map(|_| Some(0i)).size_hint(), (0, None)); + + assert_eq!(vi.take(5).size_hint(), (5, Some(5))); + assert_eq!(vi.take(12).size_hint(), (10, Some(10))); + assert_eq!(vi.skip(3).size_hint(), (7, Some(7))); + assert_eq!(vi.skip(12).size_hint(), (0, Some(0))); + assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.enumerate().size_hint(), (10, Some(10))); + assert_eq!(vi.chain(v2.iter()).size_hint(), (13, Some(13))); + assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3))); + assert_eq!(vi.scan(0i, |_,_| Some(0i)).size_hint(), (0, Some(10))); + assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.map(|i| i+1).size_hint(), (10, Some(10))); + assert_eq!(vi.filter_map(|_| Some(0i)).size_hint(), (0, Some(10))); +} + +#[test] +fn test_collect() { + let a = vec![1i, 2, 3, 4, 5]; + let b: Vec = a.iter().map(|&x| x).collect(); + assert!(a == b); +} + +#[test] +fn test_all() { + let v: Box<&[int]> = box &[1i, 2, 3, 4, 5]; + assert!(v.iter().all(|&x| x < 10)); + assert!(!v.iter().all(|&x| x % 2 == 0)); + assert!(!v.iter().all(|&x| x > 100)); + assert!(v.slice(0, 0).iter().all(|_| fail!())); +} + +#[test] +fn test_any() { + let v: Box<&[int]> = box &[1i, 2, 3, 4, 5]; + assert!(v.iter().any(|&x| x < 10)); + assert!(v.iter().any(|&x| x % 2 == 0)); + assert!(!v.iter().any(|&x| x > 100)); + assert!(!v.slice(0, 0).iter().any(|_| fail!())); +} + +#[test] +fn test_find() { + let v: &[int] = &[1i, 3, 9, 27, 103, 14, 11]; + assert_eq!(*v.iter().find(|x| *x & 1 == 0).unwrap(), 14); + assert_eq!(*v.iter().find(|x| *x % 3 == 0).unwrap(), 3); + assert!(v.iter().find(|x| *x % 12 == 0).is_none()); +} + +#[test] +fn test_position() { + let v = &[1i, 3, 9, 27, 103, 14, 11]; + assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5); + assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1); + assert!(v.iter().position(|x| *x % 12 == 0).is_none()); +} + +#[test] +fn test_count() { + let xs = &[1i, 2, 2, 1, 5, 9, 0, 2]; + assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3); + assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1); + assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0); +} + +#[test] +fn test_max_by() { + let xs: &[int] = &[-3i, 0, 1, 5, -10]; + assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); +} + +#[test] +fn test_min_by() { + let xs: &[int] = &[-3i, 0, 1, 5, -10]; + assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); +} + +#[test] +fn test_by_ref() { + let mut xs = range(0i, 10); + // sum the first five values + let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b); + assert_eq!(partial_sum, 10); + assert_eq!(xs.next(), Some(5)); +} + +#[test] +fn test_rev() { + let xs = [2i, 4, 6, 8, 10, 12, 14, 16]; + let mut it = xs.iter(); + it.next(); + it.next(); + assert!(it.rev().map(|&x| x).collect::>() == + vec![16, 14, 12, 10, 8, 6]); +} + +#[test] +fn test_double_ended_map() { + let xs = [1i, 2, 3, 4, 5, 6]; + let mut it = xs.iter().map(|&x| x * -1); + assert_eq!(it.next(), Some(-1)); + assert_eq!(it.next(), Some(-2)); + assert_eq!(it.next_back(), Some(-6)); + assert_eq!(it.next_back(), Some(-5)); + assert_eq!(it.next(), Some(-3)); + assert_eq!(it.next_back(), Some(-4)); + assert_eq!(it.next(), None); +} + +#[test] +fn test_double_ended_enumerate() { + let xs = [1i, 2, 3, 4, 5, 6]; + let mut it = xs.iter().map(|&x| x).enumerate(); + assert_eq!(it.next(), Some((0, 1))); + assert_eq!(it.next(), Some((1, 2))); + assert_eq!(it.next_back(), Some((5, 6))); + assert_eq!(it.next_back(), Some((4, 5))); + assert_eq!(it.next_back(), Some((3, 4))); + assert_eq!(it.next_back(), Some((2, 3))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_double_ended_zip() { + let xs = [1i, 2, 3, 4, 5, 6]; + let ys = [1i, 2, 3, 7]; + let a = xs.iter().map(|&x| x); + let b = ys.iter().map(|&x| x); + let mut it = a.zip(b); + assert_eq!(it.next(), Some((1, 1))); + assert_eq!(it.next(), Some((2, 2))); + assert_eq!(it.next_back(), Some((4, 7))); + assert_eq!(it.next_back(), Some((3, 3))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_double_ended_filter() { + let xs = [1i, 2, 3, 4, 5, 6]; + let mut it = xs.iter().filter(|&x| *x & 1 == 0); + assert_eq!(it.next_back().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.next_back(), None); +} + +#[test] +fn test_double_ended_filter_map() { + let xs = [1i, 2, 3, 4, 5, 6]; + let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None }); + assert_eq!(it.next_back().unwrap(), 12); + assert_eq!(it.next_back().unwrap(), 8); + assert_eq!(it.next().unwrap(), 4); + assert_eq!(it.next_back(), None); +} + +#[test] +fn test_double_ended_chain() { + let xs = [1i, 2, 3, 4, 5]; + let ys = [7i, 9, 11]; + let mut it = xs.iter().chain(ys.iter()).rev(); + assert_eq!(it.next().unwrap(), &11) + assert_eq!(it.next().unwrap(), &9) + assert_eq!(it.next_back().unwrap(), &1) + assert_eq!(it.next_back().unwrap(), &2) + assert_eq!(it.next_back().unwrap(), &3) + assert_eq!(it.next_back().unwrap(), &4) + assert_eq!(it.next_back().unwrap(), &5) + assert_eq!(it.next_back().unwrap(), &7) + assert_eq!(it.next_back(), None) +} + +#[test] +fn test_rposition() { + fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } + fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } + let v = [(0i, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert_eq!(v.iter().rposition(f), Some(3u)); + assert!(v.iter().rposition(g).is_none()); +} + +#[test] +#[should_fail] +fn test_rposition_fail() { + use std::gc::GC; + let v = [(box 0i, box(GC) 0i), (box 0i, box(GC) 0i), + (box 0i, box(GC) 0i), (box 0i, box(GC) 0i)]; + let mut i = 0i; + v.iter().rposition(|_elt| { + if i == 2 { + fail!() + } + i += 1; + false + }); +} + + +#[cfg(test)] +fn check_randacc_iter>(a: T, len: uint) +{ + let mut b = a.clone(); + assert_eq!(len, b.indexable()); + let mut n = 0u; + for (i, elt) in a.enumerate() { + assert!(Some(elt) == b.idx(i)); + n += 1; + } + assert_eq!(n, len); + assert!(None == b.idx(n)); + // call recursively to check after picking off an element + if len > 0 { + b.next(); + check_randacc_iter(b, len-1); + } +} + + +#[test] +fn test_double_ended_flat_map() { + let u = [0u,1]; + let v = [5u,6,7,8]; + let mut it = u.iter().flat_map(|x| v.slice(*x, v.len()).iter()); + assert_eq!(it.next_back().unwrap(), &8); + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.next_back().unwrap(), &7); + assert_eq!(it.next_back().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &8); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &7); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); + assert_eq!(it.next_back(), None); +} + +#[test] +fn test_random_access_chain() { + let xs = [1i, 2, 3, 4, 5]; + let ys = [7i, 9, 11]; + let mut it = xs.iter().chain(ys.iter()); + assert_eq!(it.idx(0).unwrap(), &1); + assert_eq!(it.idx(5).unwrap(), &7); + assert_eq!(it.idx(7).unwrap(), &11); + assert!(it.idx(8).is_none()); + + it.next(); + it.next(); + it.next_back(); + + assert_eq!(it.idx(0).unwrap(), &3); + assert_eq!(it.idx(4).unwrap(), &9); + assert!(it.idx(6).is_none()); + + check_randacc_iter(it, xs.len() + ys.len() - 3); +} + +#[test] +fn test_random_access_enumerate() { + let xs = [1i, 2, 3, 4, 5]; + check_randacc_iter(xs.iter().enumerate(), xs.len()); +} + +#[test] +fn test_random_access_rev() { + let xs = [1i, 2, 3, 4, 5]; + check_randacc_iter(xs.iter().rev(), xs.len()); + let mut it = xs.iter().rev(); + it.next(); + it.next_back(); + it.next(); + check_randacc_iter(it, xs.len() - 3); +} + +#[test] +fn test_random_access_zip() { + let xs = [1i, 2, 3, 4, 5]; + let ys = [7i, 9, 11]; + check_randacc_iter(xs.iter().zip(ys.iter()), cmp::min(xs.len(), ys.len())); +} + +#[test] +fn test_random_access_take() { + let xs = [1i, 2, 3, 4, 5]; + let empty: &[int] = []; + check_randacc_iter(xs.iter().take(3), 3); + check_randacc_iter(xs.iter().take(20), xs.len()); + check_randacc_iter(xs.iter().take(0), 0); + check_randacc_iter(empty.iter().take(2), 0); +} + +#[test] +fn test_random_access_skip() { + let xs = [1i, 2, 3, 4, 5]; + let empty: &[int] = []; + check_randacc_iter(xs.iter().skip(2), xs.len() - 2); + check_randacc_iter(empty.iter().skip(2), 0); +} + +#[test] +fn test_random_access_inspect() { + let xs = [1i, 2, 3, 4, 5]; + + // test .map and .inspect that don't implement Clone + let mut it = xs.iter().inspect(|_| {}); + assert_eq!(xs.len(), it.indexable()); + for (i, elt) in xs.iter().enumerate() { + assert_eq!(Some(elt), it.idx(i)); + } + +} + +#[test] +fn test_random_access_map() { + let xs = [1i, 2, 3, 4, 5]; + + let mut it = xs.iter().map(|x| *x); + assert_eq!(xs.len(), it.indexable()); + for (i, elt) in xs.iter().enumerate() { + assert_eq!(Some(*elt), it.idx(i)); + } +} + +#[test] +fn test_random_access_cycle() { + let xs = [1i, 2, 3, 4, 5]; + let empty: &[int] = []; + check_randacc_iter(xs.iter().cycle().take(27), 27); + check_randacc_iter(empty.iter().cycle(), 0); +} + +#[test] +fn test_double_ended_range() { + assert!(range(11i, 14).rev().collect::>() == vec![13i, 12, 11]); + for _ in range(10i, 0).rev() { + fail!("unreachable"); + } + + assert!(range(11u, 14).rev().collect::>() == vec![13u, 12, 11]); + for _ in range(10u, 0).rev() { + fail!("unreachable"); + } +} + +#[test] +fn test_range() { + /// A mock type to check Range when ToPrimitive returns None + struct Foo; + + impl ToPrimitive for Foo { + fn to_i64(&self) -> Option { None } + fn to_u64(&self) -> Option { None } + } + + impl Add for Foo { + fn add(&self, _: &Foo) -> Foo { + Foo + } + } + + impl PartialEq for Foo { + fn eq(&self, _: &Foo) -> bool { + true + } + } + + impl PartialOrd for Foo { + fn partial_cmp(&self, _: &Foo) -> Option { + None + } + } + + impl Clone for Foo { + fn clone(&self) -> Foo { + Foo + } + } + + impl Mul for Foo { + fn mul(&self, _: &Foo) -> Foo { + Foo + } + } + + impl num::One for Foo { + fn one() -> Foo { + Foo + } + } + + assert!(range(0i, 5).collect::>() == vec![0i, 1, 2, 3, 4]); + assert!(range(-10i, -1).collect::>() == + vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); + assert!(range(0i, 5).rev().collect::>() == vec![4, 3, 2, 1, 0]); + assert_eq!(range(200i, -5).count(), 0); + assert_eq!(range(200i, -5).rev().count(), 0); + assert_eq!(range(200i, 200).count(), 0); + assert_eq!(range(200i, 200).rev().count(), 0); + + assert_eq!(range(0i, 100).size_hint(), (100, Some(100))); + // this test is only meaningful when sizeof uint < sizeof u64 + assert_eq!(range(uint::MAX - 1, uint::MAX).size_hint(), (1, Some(1))); + assert_eq!(range(-10i, -1).size_hint(), (9, Some(9))); + assert_eq!(range(Foo, Foo).size_hint(), (0, None)); +} + +#[test] +fn test_range_inclusive() { + assert!(range_inclusive(0i, 5).collect::>() == + vec![0i, 1, 2, 3, 4, 5]); + assert!(range_inclusive(0i, 5).rev().collect::>() == + vec![5i, 4, 3, 2, 1, 0]); + assert_eq!(range_inclusive(200i, -5).count(), 0); + assert_eq!(range_inclusive(200i, -5).rev().count(), 0); + assert!(range_inclusive(200i, 200).collect::>() == vec![200]); + assert!(range_inclusive(200i, 200).rev().collect::>() == vec![200]); +} + +#[test] +fn test_range_step() { + assert!(range_step(0i, 20, 5).collect::>() == + vec![0, 5, 10, 15]); + assert!(range_step(20i, 0, -5).collect::>() == + vec![20, 15, 10, 5]); + assert!(range_step(20i, 0, -6).collect::>() == + vec![20, 14, 8, 2]); + assert!(range_step(200u8, 255, 50).collect::>() == + vec![200u8, 250]); + assert!(range_step(200i, -5, 1).collect::>() == vec![]); + assert!(range_step(200i, 200, 1).collect::>() == vec![]); +} + +#[test] +fn test_range_step_inclusive() { + assert!(range_step_inclusive(0i, 20, 5).collect::>() == + vec![0, 5, 10, 15, 20]); + assert!(range_step_inclusive(20i, 0, -5).collect::>() == + vec![20, 15, 10, 5, 0]); + assert!(range_step_inclusive(20i, 0, -6).collect::>() == + vec![20, 14, 8, 2]); + assert!(range_step_inclusive(200u8, 255, 50).collect::>() == + vec![200u8, 250]); + assert!(range_step_inclusive(200i, -5, 1).collect::>() == + vec![]); + assert!(range_step_inclusive(200i, 200, 1).collect::>() == + vec![200]); +} + +#[test] +fn test_reverse() { + let mut ys = [1i, 2, 3, 4, 5]; + ys.mut_iter().reverse_(); + assert!(ys == [5, 4, 3, 2, 1]); +} + +#[test] +fn test_peekable_is_empty() { + let a = [1i]; + let mut it = a.iter().peekable(); + assert!( !it.is_empty() ); + it.next(); + assert!( it.is_empty() ); +} + +#[test] +fn test_min_max() { + let v: [int, ..0] = []; + assert_eq!(v.iter().min_max(), NoElements); + + let v = [1i]; + assert!(v.iter().min_max() == OneElement(&1)); + + let v = [1i, 2, 3, 4, 5]; + assert!(v.iter().min_max() == MinMax(&1, &5)); + + let v = [1i, 2, 3, 4, 5, 6]; + assert!(v.iter().min_max() == MinMax(&1, &6)); + + let v = [1i, 1, 1, 1]; + assert!(v.iter().min_max() == MinMax(&1, &1)); +} + +#[test] +fn test_min_max_result() { + let r: MinMaxResult = NoElements; + assert_eq!(r.into_option(), None) + + let r = OneElement(1i); + assert_eq!(r.into_option(), Some((1,1))); + + let r = MinMax(1i,2); + assert_eq!(r.into_option(), Some((1,2))); +} diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs new file mode 100644 index 0000000000000..3a3cac542c91b --- /dev/null +++ b/src/libcoretest/lib.rs @@ -0,0 +1,31 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(globs, unsafe_destructor, macro_rules)] + +extern crate core; +extern crate test; +extern crate libc; + +mod any; +mod atomics; +mod cell; +mod char; +mod cmp; +mod finally; +mod fmt; +mod iter; +mod mem; +mod num; +mod ops; +mod option; +mod ptr; +mod raw; +mod result; +mod tuple; diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs new file mode 100644 index 0000000000000..fde640158f51e --- /dev/null +++ b/src/libcoretest/mem.rs @@ -0,0 +1,173 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +use core::mem::*; +use test::Bencher; + +#[test] +fn size_of_basic() { + assert_eq!(size_of::(), 1u); + assert_eq!(size_of::(), 2u); + assert_eq!(size_of::(), 4u); + assert_eq!(size_of::(), 8u); +} + +#[test] +#[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] +#[cfg(target_arch = "mips")] +#[cfg(target_arch = "mipsel")] +fn size_of_32() { + assert_eq!(size_of::(), 4u); + assert_eq!(size_of::<*const uint>(), 4u); +} + +#[test] +#[cfg(target_arch = "x86_64")] +fn size_of_64() { + assert_eq!(size_of::(), 8u); + assert_eq!(size_of::<*const uint>(), 8u); +} + +#[test] +fn size_of_val_basic() { + assert_eq!(size_of_val(&1u8), 1); + assert_eq!(size_of_val(&1u16), 2); + assert_eq!(size_of_val(&1u32), 4); + assert_eq!(size_of_val(&1u64), 8); +} + +#[test] +fn align_of_basic() { + assert_eq!(align_of::(), 1u); + assert_eq!(align_of::(), 2u); + assert_eq!(align_of::(), 4u); +} + +#[test] +#[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] +#[cfg(target_arch = "mips")] +#[cfg(target_arch = "mipsel")] +fn align_of_32() { + assert_eq!(align_of::(), 4u); + assert_eq!(align_of::<*const uint>(), 4u); +} + +#[test] +#[cfg(target_arch = "x86_64")] +fn align_of_64() { + assert_eq!(align_of::(), 8u); + assert_eq!(align_of::<*const uint>(), 8u); +} + +#[test] +fn align_of_val_basic() { + assert_eq!(align_of_val(&1u8), 1u); + assert_eq!(align_of_val(&1u16), 2u); + assert_eq!(align_of_val(&1u32), 4u); +} + +#[test] +fn test_swap() { + let mut x = 31337i; + let mut y = 42i; + swap(&mut x, &mut y); + assert_eq!(x, 42); + assert_eq!(y, 31337); +} + +#[test] +fn test_replace() { + let mut x = Some("test".to_string()); + let y = replace(&mut x, None); + assert!(x.is_none()); + assert!(y.is_some()); +} + +#[test] +fn test_transmute_copy() { + assert_eq!(1u, unsafe { transmute_copy(&1i) }); +} + +#[test] +fn test_transmute() { + trait Foo {} + impl Foo for int {} + + let a = box 100i as Box; + unsafe { + let x: ::core::raw::TraitObject = transmute(a); + assert!(*(x.data as *const int) == 100); + let _x: Box = transmute(x); + } + + unsafe { + assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); + } +} + +// FIXME #13642 (these benchmarks should be in another place) +/// Completely miscellaneous language-construct benchmarks. +// Static/dynamic method dispatch + +struct Struct { + field: int +} + +trait Trait { + fn method(&self) -> int; +} + +impl Trait for Struct { + fn method(&self) -> int { + self.field + } +} + +#[bench] +fn trait_vtable_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + let t = &s as &Trait; + b.iter(|| { + t.method() + }); +} + +#[bench] +fn trait_static_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + b.iter(|| { + s.method() + }); +} + +// Overhead of various match forms + +#[bench] +fn match_option_some(b: &mut Bencher) { + let x = Some(10i); + b.iter(|| { + match x { + Some(y) => y, + None => 11 + } + }); +} + +#[bench] +fn match_vec_pattern(b: &mut Bencher) { + let x = [1i,2,3,4,5,6]; + b.iter(|| { + match x { + [1,2,3,..] => 10i, + _ => 11i, + } + }); +} diff --git a/src/libcoretest/num/i16.rs b/src/libcoretest/num/i16.rs new file mode 100644 index 0000000000000..f3c2d67cdeb1b --- /dev/null +++ b/src/libcoretest/num/i16.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +int_module!(i16, i16) diff --git a/src/libcoretest/num/i32.rs b/src/libcoretest/num/i32.rs new file mode 100644 index 0000000000000..7232fc7505df9 --- /dev/null +++ b/src/libcoretest/num/i32.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +int_module!(i32, i32) diff --git a/src/libcoretest/num/i64.rs b/src/libcoretest/num/i64.rs new file mode 100644 index 0000000000000..075b8448f3529 --- /dev/null +++ b/src/libcoretest/num/i64.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +int_module!(i64, i64) diff --git a/src/libcoretest/num/i8.rs b/src/libcoretest/num/i8.rs new file mode 100644 index 0000000000000..9e0439f281889 --- /dev/null +++ b/src/libcoretest/num/i8.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +int_module!(i8, i8) diff --git a/src/libcoretest/num/int.rs b/src/libcoretest/num/int.rs new file mode 100644 index 0000000000000..f01ec3f0310a3 --- /dev/null +++ b/src/libcoretest/num/int.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +int_module!(int, int) diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs new file mode 100644 index 0000000000000..940b036ca907b --- /dev/null +++ b/src/libcoretest/num/int_macros.rs @@ -0,0 +1,160 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![macro_escape] + +macro_rules! int_module (($T:ty, $T_i:ident) => ( +#[cfg(test)] +mod tests { + use core::$T_i::*; + use core::int; + use num; + use core::num::CheckedDiv; + + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert!(MIN + MAX + 1 == 0); + } + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + pub fn test_abs() { + assert!((1 as $T).abs() == 1 as $T); + assert!((0 as $T).abs() == 0 as $T); + assert!((-1 as $T).abs() == 1 as $T); + } + + #[test] + fn test_abs_sub() { + assert!((-1 as $T).abs_sub(&(1 as $T)) == 0 as $T); + assert!((1 as $T).abs_sub(&(1 as $T)) == 0 as $T); + assert!((1 as $T).abs_sub(&(0 as $T)) == 1 as $T); + assert!((1 as $T).abs_sub(&(-1 as $T)) == 2 as $T); + } + + #[test] + fn test_signum() { + assert!((1 as $T).signum() == 1 as $T); + assert!((0 as $T).signum() == 0 as $T); + assert!((-0 as $T).signum() == 0 as $T); + assert!((-1 as $T).signum() == -1 as $T); + } + + #[test] + fn test_is_positive() { + assert!((1 as $T).is_positive()); + assert!(!(0 as $T).is_positive()); + assert!(!(-0 as $T).is_positive()); + assert!(!(-1 as $T).is_positive()); + } + + #[test] + fn test_is_negative() { + assert!(!(1 as $T).is_negative()); + assert!(!(0 as $T).is_negative()); + assert!(!(-0 as $T).is_negative()); + assert!((-1 as $T).is_negative()); + } + + #[test] + fn test_bitwise_operators() { + assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); + assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); + assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); + assert!(0b1110 as $T == (0b0111 as $T).shl(&(1 as $T))); + assert!(0b0111 as $T == (0b1110 as $T).shr(&(1 as $T))); + assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not()); + } + + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + + #[test] + fn test_count_ones() { + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); + } + + #[test] + fn test_count_zeros() { + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); + } + + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // Rotating these should make no difference + // + // We test using 124 bits because to ensure that overlong bit shifts do + // not cause undefined behaviour. See #10183. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_le() { + assert_eq!(Int::from_le(A.to_le()), A); + assert_eq!(Int::from_le(B.to_le()), B); + assert_eq!(Int::from_le(C.to_le()), C); + assert_eq!(Int::from_le(_0), _0); + assert_eq!(Int::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } + + #[test] + fn test_be() { + assert_eq!(Int::from_be(A.to_be()), A); + assert_eq!(Int::from_be(B.to_be()), B); + assert_eq!(Int::from_be(C.to_be()), C); + assert_eq!(Int::from_be(_0), _0); + assert_eq!(Int::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } + + #[test] + fn test_signed_checked_div() { + assert!(10i.checked_div(&2) == Some(5)); + assert!(5i.checked_div(&0) == None); + assert!(int::MIN.checked_div(&-1) == None); + } +} + +)) diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs new file mode 100644 index 0000000000000..8bb238c0b66e8 --- /dev/null +++ b/src/libcoretest/num/mod.rs @@ -0,0 +1,39 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::num::cast; + +mod int_macros; +mod i8; +mod i16; +mod i32; +mod i64; +mod int; +mod uint_macros; +mod u8; +mod u16; +mod u32; +mod u64; +mod uint; + +/// Helper function for testing numeric operations +pub fn test_num(ten: T, two: T) { + assert_eq!(ten.add(&two), cast(12i).unwrap()); + assert_eq!(ten.sub(&two), cast(8i).unwrap()); + assert_eq!(ten.mul(&two), cast(20i).unwrap()); + assert_eq!(ten.div(&two), cast(5i).unwrap()); + assert_eq!(ten.rem(&two), cast(0i).unwrap()); + + assert_eq!(ten.add(&two), ten + two); + assert_eq!(ten.sub(&two), ten - two); + assert_eq!(ten.mul(&two), ten * two); + assert_eq!(ten.div(&two), ten / two); + assert_eq!(ten.rem(&two), ten % two); +} diff --git a/src/libcoretest/num/u16.rs b/src/libcoretest/num/u16.rs new file mode 100644 index 0000000000000..d6aa647667804 --- /dev/null +++ b/src/libcoretest/num/u16.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uint_module!(u16, u16) diff --git a/src/libcoretest/num/u32.rs b/src/libcoretest/num/u32.rs new file mode 100644 index 0000000000000..218e79df5aece --- /dev/null +++ b/src/libcoretest/num/u32.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uint_module!(u32, u32) diff --git a/src/libcoretest/num/u64.rs b/src/libcoretest/num/u64.rs new file mode 100644 index 0000000000000..f78d4813503e7 --- /dev/null +++ b/src/libcoretest/num/u64.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uint_module!(u64, u64) diff --git a/src/libcoretest/num/u8.rs b/src/libcoretest/num/u8.rs new file mode 100644 index 0000000000000..bb08072320b70 --- /dev/null +++ b/src/libcoretest/num/u8.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uint_module!(u8, u8) diff --git a/src/libcoretest/num/uint.rs b/src/libcoretest/num/uint.rs new file mode 100644 index 0000000000000..0db865f4cde7a --- /dev/null +++ b/src/libcoretest/num/uint.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uint_module!(uint, uint) diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs new file mode 100644 index 0000000000000..2272af67daf85 --- /dev/null +++ b/src/libcoretest/num/uint_macros.rs @@ -0,0 +1,118 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![macro_escape] + +macro_rules! uint_module (($T:ty, $T_i:ident) => ( +#[cfg(test)] +mod tests { + use core::$T_i::*; + use num; + use core::num::CheckedDiv; + + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert!(MIN + MAX + 1 == 0); + } + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + fn test_bitwise_operators() { + assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); + assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); + assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); + assert!(0b1110 as $T == (0b0111 as $T).shl(&(1 as $T))); + assert!(0b0111 as $T == (0b1110 as $T).shr(&(1 as $T))); + assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); + } + + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + + #[test] + fn test_count_ones() { + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); + } + + #[test] + fn test_count_zeros() { + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); + } + + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // Rotating these should make no difference + // + // We test using 124 bits because to ensure that overlong bit shifts do + // not cause undefined behaviour. See #10183. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_le() { + assert_eq!(Int::from_le(A.to_le()), A); + assert_eq!(Int::from_le(B.to_le()), B); + assert_eq!(Int::from_le(C.to_le()), C); + assert_eq!(Int::from_le(_0), _0); + assert_eq!(Int::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } + + #[test] + fn test_be() { + assert_eq!(Int::from_be(A.to_be()), A); + assert_eq!(Int::from_be(B.to_be()), B); + assert_eq!(Int::from_be(C.to_be()), C); + assert_eq!(Int::from_be(_0), _0); + assert_eq!(Int::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } + + #[test] + fn test_unsigned_checked_div() { + assert!(10u.checked_div(&2) == Some(5)); + assert!(5u.checked_div(&0) == None); + } +} +)) diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs new file mode 100644 index 0000000000000..447fd1c699d3d --- /dev/null +++ b/src/libcoretest/ops.rs @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use test::Bencher; + +// Overhead of dtors + +struct HasDtor { + _x: int +} + +impl Drop for HasDtor { + fn drop(&mut self) { + } +} + +#[bench] +fn alloc_obj_with_dtor(b: &mut Bencher) { + b.iter(|| { + HasDtor { _x : 10 }; + }) +} diff --git a/src/libcoretest/option.rs b/src/libcoretest/option.rs new file mode 100644 index 0000000000000..776637f3be97d --- /dev/null +++ b/src/libcoretest/option.rs @@ -0,0 +1,278 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::option::*; +use core::kinds::marker; +use core::mem; + +#[test] +fn test_get_ptr() { + unsafe { + let x = box 0i; + let addr_x: *const int = mem::transmute(&*x); + let opt = Some(x); + let y = opt.unwrap(); + let addr_y: *const int = mem::transmute(&*y); + assert_eq!(addr_x, addr_y); + } +} + +#[test] +fn test_get_str() { + let x = "test".to_string(); + let addr_x = x.as_slice().as_ptr(); + let opt = Some(x); + let y = opt.unwrap(); + let addr_y = y.as_slice().as_ptr(); + assert_eq!(addr_x, addr_y); +} + +#[test] +fn test_get_resource() { + use std::rc::Rc; + use core::cell::RefCell; + + struct R { + i: Rc>, + } + + #[unsafe_destructor] + impl Drop for R { + fn drop(&mut self) { + let ii = &*self.i; + let i = *ii.borrow(); + *ii.borrow_mut() = i + 1; + } + } + + fn r(i: Rc>) -> R { + R { + i: i + } + } + + let i = Rc::new(RefCell::new(0i)); + { + let x = r(i.clone()); + let opt = Some(x); + let _y = opt.unwrap(); + } + assert_eq!(*i.borrow(), 1); +} + +#[test] +fn test_option_dance() { + let x = Some(()); + let mut y = Some(5i); + let mut y2 = 0; + for _x in x.iter() { + y2 = y.take_unwrap(); + } + assert_eq!(y2, 5); + assert!(y.is_none()); +} + +#[test] #[should_fail] +fn test_option_too_much_dance() { + let mut y = Some(marker::NoCopy); + let _y2 = y.take_unwrap(); + let _y3 = y.take_unwrap(); +} + +#[test] +fn test_and() { + let x: Option = Some(1i); + assert_eq!(x.and(Some(2i)), Some(2)); + assert_eq!(x.and(None::), None); + + let x: Option = None; + assert_eq!(x.and(Some(2i)), None); + assert_eq!(x.and(None::), None); +} + +#[test] +fn test_and_then() { + let x: Option = Some(1); + assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); + assert_eq!(x.and_then(|_| None::), None); + + let x: Option = None; + assert_eq!(x.and_then(|x| Some(x + 1)), None); + assert_eq!(x.and_then(|_| None::), None); +} + +#[test] +fn test_or() { + let x: Option = Some(1); + assert_eq!(x.or(Some(2)), Some(1)); + assert_eq!(x.or(None), Some(1)); + + let x: Option = None; + assert_eq!(x.or(Some(2)), Some(2)); + assert_eq!(x.or(None), None); +} + +#[test] +fn test_or_else() { + let x: Option = Some(1); + assert_eq!(x.or_else(|| Some(2)), Some(1)); + assert_eq!(x.or_else(|| None), Some(1)); + + let x: Option = None; + assert_eq!(x.or_else(|| Some(2)), Some(2)); + assert_eq!(x.or_else(|| None), None); +} + +#[test] +fn test_option_while_some() { + let mut i = 0i; + Some(10i).while_some(|j| { + i += 1; + if j > 0 { + Some(j-1) + } else { + None + } + }); + assert_eq!(i, 11); +} + +#[test] +fn test_unwrap() { + assert_eq!(Some(1i).unwrap(), 1); + let s = Some("hello".to_string()).unwrap(); + assert_eq!(s.as_slice(), "hello"); +} + +#[test] +#[should_fail] +fn test_unwrap_fail1() { + let x: Option = None; + x.unwrap(); +} + +#[test] +#[should_fail] +fn test_unwrap_fail2() { + let x: Option = None; + x.unwrap(); +} + +#[test] +fn test_unwrap_or() { + let x: Option = Some(1); + assert_eq!(x.unwrap_or(2), 1); + + let x: Option = None; + assert_eq!(x.unwrap_or(2), 2); +} + +#[test] +fn test_unwrap_or_else() { + let x: Option = Some(1); + assert_eq!(x.unwrap_or_else(|| 2), 1); + + let x: Option = None; + assert_eq!(x.unwrap_or_else(|| 2), 2); +} + +#[test] +fn test_filtered() { + let some_stuff = Some(42i); + let modified_stuff = some_stuff.filtered(|&x| {x < 10}); + assert_eq!(some_stuff.unwrap(), 42); + assert!(modified_stuff.is_none()); +} + +#[test] +fn test_iter() { + let val = 5i; + + let x = Some(val); + let mut it = x.iter(); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(&val)); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_iter() { + let val = 5i; + let new_val = 11i; + + let mut x = Some(val); + { + let mut it = x.mut_iter(); + + assert_eq!(it.size_hint(), (1, Some(1))); + + match it.next() { + Some(interior) => { + assert_eq!(*interior, val); + *interior = new_val; + } + None => assert!(false), + } + + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); + } + assert_eq!(x, Some(new_val)); +} + +#[test] +fn test_ord() { + let small = Some(1.0f64); + let big = Some(5.0f64); + let nan = Some(0.0f64/0.0); + assert!(!(nan < big)); + assert!(!(nan > big)); + assert!(small < big); + assert!(None < big); + assert!(big > None); +} + +#[test] +fn test_mutate() { + let mut x = Some(3i); + assert!(x.mutate(|i| i+1)); + assert_eq!(x, Some(4i)); + assert!(x.mutate_or_set(0, |i| i+1)); + assert_eq!(x, Some(5i)); + x = None; + assert!(!x.mutate(|i| i+1)); + assert_eq!(x, None); + assert!(!x.mutate_or_set(0i, |i| i+1)); + assert_eq!(x, Some(0i)); +} + +#[test] +fn test_collect() { + let v: Option> = collect(range(0i, 0) + .map(|_| Some(0i))); + assert!(v == Some(vec![])); + + let v: Option> = collect(range(0i, 3) + .map(|x| Some(x))); + assert!(v == Some(vec![0, 1, 2])); + + let v: Option> = collect(range(0i, 3) + .map(|x| if x > 1 { None } else { Some(x) })); + assert!(v == None); + + // test that it does not take more elements than it needs + let mut functions = [|| Some(()), || None, || fail!()]; + + let v: Option> = collect(functions.mut_iter().map(|f| (*f)())); + + assert!(v == None); +} diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs new file mode 100644 index 0000000000000..2a4ef5e275d20 --- /dev/null +++ b/src/libcoretest/ptr.rs @@ -0,0 +1,255 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(deprecated)] +use core::ptr::*; +use libc::c_char; +use core::mem; +use std::str; +use libc; + +#[test] +fn test() { + unsafe { + struct Pair { + fst: int, + snd: int + }; + let mut p = Pair {fst: 10, snd: 20}; + let pptr: *mut Pair = &mut p; + let iptr: *mut int = mem::transmute(pptr); + assert_eq!(*iptr, 10); + *iptr = 30; + assert_eq!(*iptr, 30); + assert_eq!(p.fst, 30); + + *pptr = Pair {fst: 50, snd: 60}; + assert_eq!(*iptr, 50); + assert_eq!(p.fst, 50); + assert_eq!(p.snd, 60); + + let v0 = vec![32000u16, 32001u16, 32002u16]; + let mut v1 = vec![0u16, 0u16, 0u16]; + + copy_memory(v1.as_mut_ptr().offset(1), + v0.as_ptr().offset(1), 1); + assert!((*v1.get(0) == 0u16 && + *v1.get(1) == 32001u16 && + *v1.get(2) == 0u16)); + copy_memory(v1.as_mut_ptr(), + v0.as_ptr().offset(2), 1); + assert!((*v1.get(0) == 32002u16 && + *v1.get(1) == 32001u16 && + *v1.get(2) == 0u16)); + copy_memory(v1.as_mut_ptr().offset(2), + v0.as_ptr(), 1u); + assert!((*v1.get(0) == 32002u16 && + *v1.get(1) == 32001u16 && + *v1.get(2) == 32000u16)); + } +} + +#[test] +fn test_position() { + use libc::c_char; + + "hello".with_c_str(|p| { + unsafe { + assert!(2u == position(p, |c| *c == 'l' as c_char)); + assert!(4u == position(p, |c| *c == 'o' as c_char)); + assert!(5u == position(p, |c| *c == 0 as c_char)); + } + }) +} + +#[test] +fn test_buf_len() { + "hello".with_c_str(|p0| { + "there".with_c_str(|p1| { + "thing".with_c_str(|p2| { + let v = vec![p0, p1, p2, null()]; + unsafe { + assert_eq!(buf_len(v.as_ptr()), 3u); + } + }) + }) + }) +} + +#[test] +fn test_is_null() { + let p: *const int = null(); + assert!(p.is_null()); + assert!(!p.is_not_null()); + + let q = unsafe { p.offset(1) }; + assert!(!q.is_null()); + assert!(q.is_not_null()); + + let mp: *mut int = mut_null(); + assert!(mp.is_null()); + assert!(!mp.is_not_null()); + + let mq = unsafe { mp.offset(1) }; + assert!(!mq.is_null()); + assert!(mq.is_not_null()); +} + +#[test] +fn test_to_option() { + unsafe { + let p: *const int = null(); + assert_eq!(p.to_option(), None); + + let q: *const int = &2; + assert_eq!(q.to_option().unwrap(), &2); + + let p: *mut int = mut_null(); + assert_eq!(p.to_option(), None); + + let q: *mut int = &mut 2; + assert_eq!(q.to_option().unwrap(), &2); + } +} + +#[test] +fn test_ptr_addition() { + unsafe { + let xs = Vec::from_elem(16, 5i); + let mut ptr = xs.as_ptr(); + let end = ptr.offset(16); + + while ptr < end { + assert_eq!(*ptr, 5); + ptr = ptr.offset(1); + } + + let mut xs_mut = xs; + let mut m_ptr = xs_mut.as_mut_ptr(); + let m_end = m_ptr.offset(16); + + while m_ptr < m_end { + *m_ptr += 5; + m_ptr = m_ptr.offset(1); + } + + assert!(xs_mut == Vec::from_elem(16, 10i)); + } +} + +#[test] +fn test_ptr_subtraction() { + unsafe { + let xs = vec![0,1,2,3,4,5,6,7,8,9]; + let mut idx = 9i8; + let ptr = xs.as_ptr(); + + while idx >= 0i8 { + assert_eq!(*(ptr.offset(idx as int)), idx as int); + idx = idx - 1i8; + } + + let mut xs_mut = xs; + let m_start = xs_mut.as_mut_ptr(); + let mut m_ptr = m_start.offset(9); + + while m_ptr >= m_start { + *m_ptr += *m_ptr; + m_ptr = m_ptr.offset(-1); + } + + assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]); + } +} + +#[test] +fn test_ptr_array_each_with_len() { + unsafe { + let one = "oneOne".to_c_str(); + let two = "twoTwo".to_c_str(); + let three = "threeThree".to_c_str(); + let arr = vec![ + one.as_ptr(), + two.as_ptr(), + three.as_ptr() + ]; + let expected_arr = [ + one, two, three + ]; + + let mut ctr = 0; + let mut iteration_count = 0; + array_each_with_len(arr.as_ptr(), arr.len(), |e| { + let actual = str::raw::from_c_str(e); + let expected = str::raw::from_c_str(expected_arr[ctr].as_ptr()); + assert_eq!(actual.as_slice(), expected.as_slice()); + ctr += 1; + iteration_count += 1; + }); + assert_eq!(iteration_count, 3u); + } +} + +#[test] +fn test_ptr_array_each() { + unsafe { + let one = "oneOne".to_c_str(); + let two = "twoTwo".to_c_str(); + let three = "threeThree".to_c_str(); + let arr = vec![ + one.as_ptr(), + two.as_ptr(), + three.as_ptr(), + // fake a null terminator + null() + ]; + let expected_arr = [ + one, two, three + ]; + + let arr_ptr = arr.as_ptr(); + let mut ctr = 0u; + let mut iteration_count = 0u; + array_each(arr_ptr, |e| { + let actual = str::raw::from_c_str(e); + let expected = str::raw::from_c_str(expected_arr[ctr].as_ptr()); + assert_eq!(actual.as_slice(), expected.as_slice()); + ctr += 1; + iteration_count += 1; + }); + assert_eq!(iteration_count, 3); + } +} + +#[test] +#[should_fail] +fn test_ptr_array_each_with_len_null_ptr() { + unsafe { + array_each_with_len(0 as *const *const libc::c_char, 1, |e| { + str::raw::from_c_str(e); + }); + } +} +#[test] +#[should_fail] +fn test_ptr_array_each_null_ptr() { + unsafe { + array_each(0 as *const *const libc::c_char, |e| { + str::raw::from_c_str(e); + }); + } +} + +#[test] +fn test_set_memory() { + let mut xs = [0u8, ..20]; + let ptr = xs.as_mut_ptr(); + unsafe { set_memory(ptr, 5u8, xs.len()); } + assert!(xs == [5u8, ..20]); +} diff --git a/src/libcoretest/raw.rs b/src/libcoretest/raw.rs new file mode 100644 index 0000000000000..f2c23c7c77327 --- /dev/null +++ b/src/libcoretest/raw.rs @@ -0,0 +1,35 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::raw::*; +use core::mem; + +#[test] +fn synthesize_closure() { + unsafe { + let x = 10; + let f: |int| -> int = |y| x + y; + + assert_eq!(f(20), 30); + + let original_closure: Closure = mem::transmute(f); + + let actual_function_pointer = original_closure.code; + let environment = original_closure.env; + + let new_closure = Closure { + code: actual_function_pointer, + env: environment + }; + + let new_f: |int| -> int = mem::transmute(new_closure); + assert_eq!(new_f(20), 30); + } +} diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs new file mode 100644 index 0000000000000..7c7e0a542cd87 --- /dev/null +++ b/src/libcoretest/result.rs @@ -0,0 +1,161 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::result::{collect, fold, fold_}; +use core::iter::range; + +pub fn op1() -> Result { Ok(666) } +pub fn op2() -> Result { Err("sadface") } + +#[test] +pub fn test_and() { + assert_eq!(op1().and(Ok(667i)).unwrap(), 667); + assert_eq!(op1().and(Err::<(), &'static str>("bad")).unwrap_err(), + "bad"); + + assert_eq!(op2().and(Ok(667i)).unwrap_err(), "sadface"); + assert_eq!(op2().and(Err::<(),&'static str>("bad")).unwrap_err(), + "sadface"); +} + +#[test] +pub fn test_and_then() { + assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); + assert_eq!(op1().and_then(|_| Err::("bad")).unwrap_err(), + "bad"); + + assert_eq!(op2().and_then(|i| Ok::(i + 1)).unwrap_err(), + "sadface"); + assert_eq!(op2().and_then(|_| Err::("bad")).unwrap_err(), + "sadface"); +} + +#[test] +pub fn test_or() { + assert_eq!(op1().or(Ok(667)).unwrap(), 666); + assert_eq!(op1().or(Err("bad")).unwrap(), 666); + + assert_eq!(op2().or(Ok(667)).unwrap(), 667); + assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad"); +} + +#[test] +pub fn test_or_else() { + assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), 666); + assert_eq!(op1().or_else(|e| Err::(e)).unwrap(), 666); + + assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), 667); + assert_eq!(op2().or_else(|e| Err::(e)).unwrap_err(), + "sadface"); +} + +#[test] +pub fn test_impl_map() { + assert!(Ok::(1).map(|x| x + 1) == Ok(2)); + assert!(Err::(1).map(|x| x + 1) == Err(1)); +} + +#[test] +pub fn test_impl_map_err() { + assert!(Ok::(1).map_err(|x| x + 1) == Ok(1)); + assert!(Err::(1).map_err(|x| x + 1) == Err(2)); +} + +#[test] +fn test_collect() { + let v: Result, ()> = collect(range(0i, 0).map(|_| Ok::(0))); + assert!(v == Ok(vec![])); + + let v: Result, ()> = collect(range(0i, 3).map(|x| Ok::(x))); + assert!(v == Ok(vec![0, 1, 2])); + + let v: Result, int> = collect(range(0i, 3) + .map(|x| if x > 1 { Err(x) } else { Ok(x) })); + assert!(v == Err(2)); + + // test that it does not take more elements than it needs + let mut functions = [|| Ok(()), || Err(1i), || fail!()]; + + let v: Result, int> = collect(functions.mut_iter().map(|f| (*f)())); + assert!(v == Err(1)); +} + +#[test] +fn test_fold() { + assert_eq!(fold_(range(0i, 0) + .map(|_| Ok::<(), ()>(()))), + Ok(())); + assert_eq!(fold(range(0i, 3) + .map(|x| Ok::(x)), + 0, |a, b| a + b), + Ok(3)); + assert_eq!(fold_(range(0i, 3) + .map(|x| if x > 1 { Err(x) } else { Ok(()) })), + Err(2)); + + // test that it does not take more elements than it needs + let mut functions = [|| Ok(()), || Err(1i), || fail!()]; + + assert_eq!(fold_(functions.mut_iter() + .map(|f| (*f)())), + Err(1)); +} + +#[test] +pub fn test_fmt_default() { + let ok: Result = Ok(100); + let err: Result = Err("Err"); + + let s = format!("{}", ok); + assert_eq!(s.as_slice(), "Ok(100)"); + let s = format!("{}", err); + assert_eq!(s.as_slice(), "Err(Err)"); +} + +#[test] +pub fn test_unwrap_or() { + let ok: Result = Ok(100i); + let ok_err: Result = Err("Err"); + + assert_eq!(ok.unwrap_or(50), 100); + assert_eq!(ok_err.unwrap_or(50), 50); +} + +#[test] +pub fn test_unwrap_or_else() { + fn handler(msg: &'static str) -> int { + if msg == "I got this." { + 50i + } else { + fail!("BadBad") + } + } + + let ok: Result = Ok(100); + let ok_err: Result = Err("I got this."); + + assert_eq!(ok.unwrap_or_else(handler), 100); + assert_eq!(ok_err.unwrap_or_else(handler), 50); +} + +#[test] +#[should_fail] +pub fn test_unwrap_or_else_failure() { + fn handler(msg: &'static str) -> int { + if msg == "I got this." { + 50i + } else { + fail!("BadBad") + } + } + + let bad_err: Result = Err("Unrecoverable mess."); + let _ : int = bad_err.unwrap_or_else(handler); +} diff --git a/src/libcoretest/tuple.rs b/src/libcoretest/tuple.rs new file mode 100644 index 0000000000000..be71e42ae9ad6 --- /dev/null +++ b/src/libcoretest/tuple.rs @@ -0,0 +1,92 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[test] +fn test_clone() { + let a = (1i, "2"); + let b = a.clone(); + assert_eq!(a, b); +} + +#[test] +fn test_getters() { + macro_rules! test_getter( + ($x:expr, $valN:ident, $refN:ident, $mutN:ident, + $init:expr, $incr:expr, $result:expr) => ({ + assert_eq!($x.$valN(), $init); + assert_eq!(*$x.$refN(), $init); + *$x.$mutN() += $incr; + assert_eq!(*$x.$refN(), $result); + }) + ) + let mut x = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64); + test_getter!(x, val0, ref0, mut0, 0, 1, 1); + test_getter!(x, val1, ref1, mut1, 1, 1, 2); + test_getter!(x, val2, ref2, mut2, 2, 1, 3); + test_getter!(x, val3, ref3, mut3, 3, 1, 4); + test_getter!(x, val4, ref4, mut4, 4, 1, 5); + test_getter!(x, val5, ref5, mut5, 5, 1, 6); + test_getter!(x, val6, ref6, mut6, 6, 1, 7); + test_getter!(x, val7, ref7, mut7, 7, 1, 8); + test_getter!(x, val8, ref8, mut8, 8, 1, 9); + test_getter!(x, val9, ref9, mut9, 9, 1, 10); + test_getter!(x, val10, ref10, mut10, 10.0, 1.0, 11.0); + test_getter!(x, val11, ref11, mut11, 11.0, 1.0, 12.0); +} + +#[test] +fn test_tuple_cmp() { + let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u)); + + let nan = 0.0f64/0.0; + + // PartialEq + assert_eq!(small, small); + assert_eq!(big, big); + assert!(small != big); + assert!(big != small); + + // PartialOrd + assert!(small < big); + assert!(!(small < small)); + assert!(!(big < small)); + assert!(!(big < big)); + + assert!(small <= small); + assert!(big <= big); + + assert!(big > small); + assert!(small >= small); + assert!(big >= small); + assert!(big >= big); + + assert!(!((1.0f64, 2.0f64) < (nan, 3.0))); + assert!(!((1.0f64, 2.0f64) <= (nan, 3.0))); + assert!(!((1.0f64, 2.0f64) > (nan, 3.0))); + assert!(!((1.0f64, 2.0f64) >= (nan, 3.0))); + assert!(((1.0f64, 2.0f64) < (2.0, nan))); + assert!(!((2.0f64, 2.0f64) < (2.0, nan))); + + // Ord + assert!(small.cmp(&small) == Equal); + assert!(big.cmp(&big) == Equal); + assert!(small.cmp(&big) == Less); + assert!(big.cmp(&small) == Greater); +} + +#[test] +fn test_show() { + let s = format!("{}", (1i,)); + assert_eq!(s.as_slice(), "(1,)"); + let s = format!("{}", (1i, true)); + assert_eq!(s.as_slice(), "(1, true)"); + let s = format!("{}", (1i, "hi", true)); + assert_eq!(s.as_slice(), "(1, hi, true)"); +} diff --git a/src/libdebug/reflect.rs b/src/libdebug/reflect.rs index 280e8753b34b5..0cbae6ee2d3a3 100644 --- a/src/libdebug/reflect.rs +++ b/src/libdebug/reflect.rs @@ -28,7 +28,7 @@ use std::gc::Gc; * as `TyVisitor`; then build a MovePtrAdaptor wrapped around your struct. */ pub trait MovePtr { - fn move_ptr(&mut self, adjustment: |*u8| -> *u8); + fn move_ptr(&mut self, adjustment: |*const u8| -> *const u8); fn push_ptr(&mut self); fn pop_ptr(&mut self); } @@ -51,12 +51,12 @@ impl MovePtrAdaptor { #[inline] pub fn bump(&mut self, sz: uint) { - self.inner.move_ptr(|p| ((p as uint) + sz) as *u8) + self.inner.move_ptr(|p| ((p as uint) + sz) as *const u8) } #[inline] pub fn align(&mut self, a: uint) { - self.inner.move_ptr(|p| align(p as uint, a) as *u8) + self.inner.move_ptr(|p| align(p as uint, a) as *const u8) } #[inline] @@ -202,35 +202,35 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { self.align_to::>(); if ! self.inner.visit_box(mtbl, inner) { return false; } self.bump_past::>(); true } - fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_uniq(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { self.align_to::>(); if ! self.inner.visit_uniq(mtbl, inner) { return false; } self.bump_past::>(); true } - fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::<*u8>(); + fn visit_ptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { + self.align_to::<*const u8>(); if ! self.inner.visit_ptr(mtbl, inner) { return false; } - self.bump_past::<*u8>(); + self.bump_past::<*const u8>(); true } - fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_rptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { self.align_to::<&'static u8>(); if ! self.inner.visit_rptr(mtbl, inner) { return false; } self.bump_past::<&'static u8>(); true } - fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { self.align_to::<&'static [u8]>(); if ! self.inner.visit_evec_slice(mtbl, inner) { return false; } self.bump_past::<&'static [u8]>(); @@ -238,7 +238,7 @@ impl TyVisitor for MovePtrAdaptor { } fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, - mtbl: uint, inner: *TyDesc) -> bool { + mtbl: uint, inner: *const TyDesc) -> bool { self.align(align); if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) { return false; @@ -254,7 +254,7 @@ impl TyVisitor for MovePtrAdaptor { } fn visit_rec_field(&mut self, i: uint, name: &str, - mtbl: uint, inner: *TyDesc) -> bool { + mtbl: uint, inner: *const TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_rec_field(i, name, mtbl, inner) { return false; @@ -278,7 +278,7 @@ impl TyVisitor for MovePtrAdaptor { } fn visit_class_field(&mut self, i: uint, name: &str, named: bool, mtbl: uint, - inner: *TyDesc) -> bool { + inner: *const TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_class_field(i, name, named, mtbl, inner) { return false; @@ -301,7 +301,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { + fn visit_tup_field(&mut self, i: uint, inner: *const TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_tup_field(i, inner) { return false; } unsafe { self.bump((*inner).size); } @@ -321,12 +321,14 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool { + fn visit_fn_input(&mut self, i: uint, mode: uint, + inner: *const TyDesc) -> bool { if ! self.inner.visit_fn_input(i, mode, inner) { return false; } true } - fn visit_fn_output(&mut self, retstyle: uint, variadic: bool, inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, retstyle: uint, variadic: bool, + inner: *const TyDesc) -> bool { if ! self.inner.visit_fn_output(retstyle, variadic, inner) { return false; } true } @@ -340,7 +342,7 @@ impl TyVisitor for MovePtrAdaptor { } fn visit_enter_enum(&mut self, n_variants: uint, - get_disr: unsafe extern fn(ptr: *Opaque) -> Disr, + get_disr: unsafe extern fn(ptr: *const Opaque) -> Disr, sz: uint, align: uint) -> bool { self.align(align); @@ -361,7 +363,8 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool { + fn visit_enum_variant_field(&mut self, i: uint, offset: uint, + inner: *const TyDesc) -> bool { self.inner.push_ptr(); self.bump(offset); if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } @@ -381,7 +384,7 @@ impl TyVisitor for MovePtrAdaptor { } fn visit_leave_enum(&mut self, n_variants: uint, - get_disr: unsafe extern fn(ptr: *Opaque) -> Disr, + get_disr: unsafe extern fn(ptr: *const Opaque) -> Disr, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { return false; diff --git a/src/libdebug/repr.rs b/src/libdebug/repr.rs index 6562e2fb6e382..133353ec3d717 100644 --- a/src/libdebug/repr.rs +++ b/src/libdebug/repr.rs @@ -92,8 +92,8 @@ enum VariantState { } pub struct ReprVisitor<'a> { - ptr: *u8, - ptr_stk: Vec<*u8>, + ptr: *const u8, + ptr_stk: Vec<*const u8>, var_stk: Vec, writer: &'a mut io::Writer, last_err: Option, @@ -101,7 +101,7 @@ pub struct ReprVisitor<'a> { impl<'a> MovePtr for ReprVisitor<'a> { #[inline] - fn move_ptr(&mut self, adjustment: |*u8| -> *u8) { + fn move_ptr(&mut self, adjustment: |*const u8| -> *const u8) { self.ptr = adjustment(self.ptr); } fn push_ptr(&mut self) { @@ -114,7 +114,7 @@ impl<'a> MovePtr for ReprVisitor<'a> { impl<'a> ReprVisitor<'a> { // Various helpers for the TyVisitor impl - pub fn new(ptr: *u8, writer: &'a mut io::Writer) -> ReprVisitor<'a> { + pub fn new(ptr: *const u8, writer: &'a mut io::Writer) -> ReprVisitor<'a> { ReprVisitor { ptr: ptr, ptr_stk: vec!(), @@ -128,18 +128,19 @@ impl<'a> ReprVisitor<'a> { pub fn get(&mut self, f: |&mut ReprVisitor, &T| -> bool) -> bool { unsafe { let ptr = self.ptr; - f(self, mem::transmute::<*u8,&T>(ptr)) + f(self, mem::transmute::<*const u8,&T>(ptr)) } } #[inline] - pub fn visit_inner(&mut self, inner: *TyDesc) -> bool { + pub fn visit_inner(&mut self, inner: *const TyDesc) -> bool { let ptr = self.ptr; self.visit_ptr_inner(ptr, inner) } #[inline] - pub fn visit_ptr_inner(&mut self, ptr: *u8, inner: *TyDesc) -> bool { + pub fn visit_ptr_inner(&mut self, ptr: *const u8, + inner: *const TyDesc) -> bool { unsafe { let u = ReprVisitor::new(ptr, mem::transmute_copy(&self.writer)); let mut v = reflect::MovePtrAdaptor::new(u); @@ -183,8 +184,9 @@ impl<'a> ReprVisitor<'a> { true } - pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool { - let mut p = ptr as *u8; + pub fn write_vec_range(&mut self, ptr: *const (), len: uint, + inner: *const TyDesc) -> bool { + let mut p = ptr as *const u8; let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; try!(self, self.writer.write(['[' as u8])); let mut first = true; @@ -197,8 +199,8 @@ impl<'a> ReprVisitor<'a> { } else { try!(self, self.writer.write(", ".as_bytes())); } - self.visit_ptr_inner(p as *u8, inner); - p = align(unsafe { p.offset(sz as int) as uint }, al) as *u8; + self.visit_ptr_inner(p as *const u8, inner); + p = align(unsafe { p.offset(sz as int) as uint }, al) as *const u8; left -= dec; } try!(self, self.writer.write([']' as u8])); @@ -276,40 +278,46 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_estr_fixed(&mut self, _n: uint, _sz: uint, _align: uint) -> bool { fail!(); } - fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { try!(self, self.writer.write("box(GC) ".as_bytes())); self.write_mut_qualifier(mtbl); self.get::<&raw::Box<()>>(|this, b| { - let p = &b.data as *() as *u8; + let p = &b.data as *const () as *const u8; this.visit_ptr_inner(p, inner) }) } - fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { + fn visit_uniq(&mut self, _mtbl: uint, inner: *const TyDesc) -> bool { try!(self, self.writer.write("box ".as_bytes())); - self.get::<*u8>(|this, b| { + self.get::<*const u8>(|this, b| { this.visit_ptr_inner(*b, inner) }) } - fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool { - self.get::<*u8>(|this, p| { + fn visit_ptr(&mut self, mtbl: uint, _inner: *const TyDesc) -> bool { + self.get::<*const u8>(|this, p| { try!(this, write!(this.writer, "({} as *", *p)); - this.write_mut_qualifier(mtbl); + if mtbl == 0 { + try!(this, this.writer.write("mut ".as_bytes())); + } else if mtbl == 1 { + try!(this, this.writer.write("const ".as_bytes())); + } else { + fail!("invalid mutability value"); + } try!(this, this.writer.write("())".as_bytes())); true }) } - fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_rptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { try!(self, self.writer.write(['&' as u8])); self.write_mut_qualifier(mtbl); - self.get::<*u8>(|this, p| { + self.get::<*const u8>(|this, p| { this.visit_ptr_inner(*p, inner) }) } - fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool { self.get::>(|this, s| { try!(this, this.writer.write(['&' as u8])); this.write_mut_qualifier(mtbl); @@ -321,7 +329,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint, - _: uint, inner: *TyDesc) -> bool { + _: uint, inner: *const TyDesc) -> bool { let assumed_size = if sz == 0 { n } else { sz }; self.get::<()>(|this, b| { this.write_vec_range(b, assumed_size, inner) @@ -335,7 +343,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } fn visit_rec_field(&mut self, i: uint, name: &str, - mtbl: uint, inner: *TyDesc) -> bool { + mtbl: uint, inner: *const TyDesc) -> bool { if i != 0 { try!(self, self.writer.write(", ".as_bytes())); } @@ -366,7 +374,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } fn visit_class_field(&mut self, i: uint, name: &str, named: bool, - _mtbl: uint, inner: *TyDesc) -> bool { + _mtbl: uint, inner: *const TyDesc) -> bool { if i != 0 { try!(self, self.writer.write(", ".as_bytes())); } @@ -396,7 +404,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { true } - fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { + fn visit_tup_field(&mut self, i: uint, inner: *const TyDesc) -> bool { if i != 0 { try!(self, self.writer.write(", ".as_bytes())); } @@ -415,7 +423,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_enum(&mut self, _n_variants: uint, - get_disr: unsafe extern fn(ptr: *Opaque) -> Disr, + get_disr: unsafe extern fn(ptr: *const Opaque) -> Disr, _sz: uint, _align: uint) -> bool { let disr = unsafe { @@ -456,7 +464,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enum_variant_field(&mut self, i: uint, _offset: uint, - inner: *TyDesc) + inner: *const TyDesc) -> bool { match *self.var_stk.get(self.var_stk.len() - 1) { Matched => { @@ -489,7 +497,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_leave_enum(&mut self, _n_variants: uint, - _get_disr: unsafe extern fn(ptr: *Opaque) -> Disr, + _get_disr: unsafe extern fn(ptr: *const Opaque) -> Disr, _sz: uint, _align: uint) -> bool { @@ -505,7 +513,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> { true } - fn visit_fn_input(&mut self, i: uint, _mode: uint, inner: *TyDesc) -> bool { + fn visit_fn_input(&mut self, i: uint, _mode: uint, + inner: *const TyDesc) -> bool { if i != 0 { try!(self, self.writer.write(", ".as_bytes())); } @@ -515,7 +524,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, - inner: *TyDesc) -> bool { + inner: *const TyDesc) -> bool { if variadic { try!(self, self.writer.write(", ...".as_bytes())); } @@ -543,7 +552,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { pub fn write_repr(writer: &mut io::Writer, object: &T) -> io::IoResult<()> { unsafe { - let ptr = object as *T as *u8; + let ptr = object as *const T as *const u8; let tydesc = get_tydesc::(); let u = ReprVisitor::new(ptr, writer); let mut v = reflect::MovePtrAdaptor::new(u); @@ -579,22 +588,22 @@ fn test_repr() { assert_eq!(s.as_slice(), e); } - exact_test(&10, "10"); + exact_test(&10i, "10"); exact_test(&true, "true"); exact_test(&false, "false"); - exact_test(&1.234, "1.234f64"); + exact_test(&1.234f64, "1.234f64"); exact_test(&("hello"), "\"hello\""); - exact_test(&(box(GC) 10), "box(GC) 10"); - exact_test(&(box 10), "box 10"); - exact_test(&(&10), "&10"); - let mut x = 10; + exact_test(&(box(GC) 10i), "box(GC) 10"); + exact_test(&(box 10i), "box 10"); + exact_test(&(&10i), "&10"); + let mut x = 10i; exact_test(&(&mut x), "&mut 10"); - exact_test(&(0 as *()), "(0x0 as *())"); - exact_test(&(0 as *mut ()), "(0x0 as *mut ())"); + exact_test(&(0i as *const()), "(0x0 as *const ())"); + exact_test(&(0i as *mut ()), "(0x0 as *mut ())"); - exact_test(&(1,), "(1,)"); + exact_test(&(1i,), "(1,)"); exact_test(&(&["hi", "there"]), "&[\"hi\", \"there\"]"); exact_test(&(P{a:10, b:1.234}), @@ -604,8 +613,8 @@ fn test_repr() { exact_test(&(box P{a:10, b:1.234}), "box repr::P{a: 10, b: 1.234f64}"); - exact_test(&(&[1, 2]), "&[1, 2]"); - exact_test(&(&mut [1, 2]), "&mut [1, 2]"); + exact_test(&(&[1i, 2i]), "&[1, 2]"); + exact_test(&(&mut [1i, 2i]), "&mut [1, 2]"); exact_test(&'\'', "'\\''"); exact_test(&'"', "'\"'"); diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 7d0ae03c87812..d944818abc56a 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -38,18 +38,18 @@ use libc::{c_void, size_t, c_int}; #[link(name = "miniz", kind = "static")] extern { /// Raw miniz compression function. - fn tdefl_compress_mem_to_heap(psrc_buf: *c_void, - src_buf_len: size_t, - pout_len: *mut size_t, - flags: c_int) - -> *mut c_void; + fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void, + src_buf_len: size_t, + pout_len: *mut size_t, + flags: c_int) + -> *mut c_void; /// Raw miniz decompression function. - fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void, - src_buf_len: size_t, - pout_len: *mut size_t, - flags: c_int) - -> *mut c_void; + fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void, + src_buf_len: size_t, + pout_len: *mut size_t, + flags: c_int) + -> *mut c_void; } static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal" @@ -59,10 +59,10 @@ static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { unsafe { let mut outsz : size_t = 0; - let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void, - bytes.len() as size_t, - &mut outsz, - flags); + let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, + bytes.len() as size_t, + &mut outsz, + flags); if !res.is_null() { Some(CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res))) } else { @@ -84,10 +84,10 @@ pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option> { fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { unsafe { let mut outsz : size_t = 0; - let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void, - bytes.len() as size_t, - &mut outsz, - flags); + let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _, + bytes.len() as size_t, + &mut outsz, + flags); if !res.is_null() { Some(CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res))) } else { diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index ccb1adf93de6d..00e6df9ffbbb2 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -370,7 +370,7 @@ impl Matches { } fn is_arg(arg: &str) -> bool { - arg.len() > 1 && arg[0] == '-' as u8 + arg.len() > 1 && arg.as_bytes()[0] == '-' as u8 } fn find_opt(opts: &[Opt], nm: Name) -> Option { @@ -553,7 +553,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { } else { let mut names; let mut i_arg = None; - if cur.as_slice()[1] == '-' as u8 { + if cur.as_bytes()[1] == '-' as u8 { let tail = cur.as_slice().slice(2, curlen); let tail_eq: Vec<&str> = tail.split('=').collect(); if tail_eq.len() <= 1 { diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs index a34791f470eaf..bd19f19cec6b2 100644 --- a/src/libgraphviz/maybe_owned_vec.rs +++ b/src/libgraphviz/maybe_owned_vec.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::collections::Collection; +use std::default::Default; use std::fmt; use std::iter::FromIterator; +use std::path::BytesContainer; use std::slice; // Note 1: It is not clear whether the flexibility of providing both @@ -61,6 +64,32 @@ impl<'a,T> MaybeOwnedVector<'a,T> { } } +impl<'a, T: PartialEq> PartialEq for MaybeOwnedVector<'a, T> { + fn eq(&self, other: &MaybeOwnedVector) -> bool { + self.as_slice() == other.as_slice() + } +} + +impl<'a, T: Eq> Eq for MaybeOwnedVector<'a, T> {} + +impl<'a, T: PartialOrd> PartialOrd for MaybeOwnedVector<'a, T> { + fn partial_cmp(&self, other: &MaybeOwnedVector) -> Option { + self.as_slice().partial_cmp(&other.as_slice()) + } +} + +impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> { + fn cmp(&self, other: &MaybeOwnedVector) -> Ordering { + self.as_slice().cmp(&other.as_slice()) + } +} + +impl<'a, T: PartialEq, V: Vector> Equiv for MaybeOwnedVector<'a, T> { + fn equiv(&self, other: &V) -> bool { + self.as_slice() == other.as_slice() + } +} + // The `Vector` trait is provided in the prelude and is implemented on // both `&'a [T]` and `Vec`, so it makes sense to try to support it // seamlessly. The other vector related traits from the prelude do @@ -108,6 +137,34 @@ impl<'a,T:Clone> CloneableVector for MaybeOwnedVector<'a,T> { } } +impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> { + fn clone(&self) -> MaybeOwnedVector<'a, T> { + match *self { + Growable(ref v) => Growable(v.to_owned()), + Borrowed(v) => Borrowed(v) + } + } +} + + +impl<'a, T> Default for MaybeOwnedVector<'a, T> { + fn default() -> MaybeOwnedVector<'a, T> { + Growable(Vec::new()) + } +} + +impl<'a, T> Collection for MaybeOwnedVector<'a, T> { + fn len(&self) -> uint { + self.as_slice().len() + } +} + +impl<'a> BytesContainer for MaybeOwnedVector<'a, u8> { + fn container_as_bytes<'a>(&'a self) -> &'a [u8] { + self.as_slice() + } +} + impl<'a,T:Clone> MaybeOwnedVector<'a,T> { /// Convert `self` into a growable `Vec`, not making a copy if possible. pub fn into_vec(self) -> Vec { diff --git a/src/libgreen/context.rs b/src/libgreen/context.rs index f11a1d2c66737..8c60f3d9fe1dc 100644 --- a/src/libgreen/context.rs +++ b/src/libgreen/context.rs @@ -27,7 +27,7 @@ pub struct Context { stack_bounds: Option<(uint, uint)>, } -pub type InitFn = extern "C" fn(uint, *(), *()) -> !; +pub type InitFn = extern "C" fn(uint, *mut (), *mut ()) -> !; impl Context { pub fn empty() -> Context { @@ -49,7 +49,7 @@ impl Context { pub fn new(init: InitFn, arg: uint, start: proc():Send, stack: &mut Stack) -> Context { - let sp: *uint = stack.end(); + let sp: *const uint = stack.end(); let sp: *mut uint = sp as *mut uint; // Save and then immediately load the current context, // which we will then modify to call the given function when restored @@ -66,7 +66,7 @@ impl Context { // them in terms of the code running on them (and hopefully they don't // overflow). Additionally, their coroutine stacks are listed as being // zero-length, so that's how we detect what's what here. - let stack_base: *uint = stack.start(); + let stack_base: *const uint = stack.start(); let bounds = if sp as uint == stack_base as uint { None } else { @@ -116,7 +116,7 @@ impl Context { #[link(name = "context_switch", kind = "static")] extern { - fn rust_swap_registers(out_regs: *mut Registers, in_regs: *Registers); + fn rust_swap_registers(out_regs: *mut Registers, in_regs: *const Registers); } // Register contexts used in various architectures diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 1d23b0f1832d7..1b34679b0a18a 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -116,7 +116,7 @@ //! extern crate green; //! //! #[start] -//! fn start(argc: int, argv: **u8) -> int { +//! fn start(argc: int, argv: *const *const u8) -> int { //! green::start(argc, argv, green::basic::event_loop, main) //! } //! @@ -135,7 +135,7 @@ //! extern crate rustuv; //! //! #[start] -//! fn start(argc: int, argv: **u8) -> int { +//! fn start(argc: int, argv: *const *const u8) -> int { //! green::start(argc, argv, rustuv::event_loop, main) //! } //! @@ -267,7 +267,7 @@ macro_rules! green_start( ($f:ident) => ( extern crate rustuv; #[start] - fn start(argc: int, argv: **u8) -> int { + fn start(argc: int, argv: *const *const u8) -> int { green::start(argc, argv, rustuv::event_loop, super::$f) } } @@ -291,7 +291,7 @@ macro_rules! green_start( ($f:ident) => ( /// /// The return value is used as the process return code. 0 on success, 101 on /// error. -pub fn start(argc: int, argv: **u8, +pub fn start(argc: int, argv: *const *const u8, event_loop_factory: fn() -> Box, main: proc():Send) -> int { rt::init(argc, argv); diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index f8272e5f2376e..7603b0a8013c7 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -611,13 +611,13 @@ impl Scheduler { // old task as inputs. pub fn change_task_context(mut ~self, - current_task: Box, + mut current_task: Box, mut next_task: Box, f: |&mut Scheduler, Box|) -> Box { let f_opaque = ClosureConverter::from_fn(f); - let current_task_dupe = &*current_task as *GreenTask; + let current_task_dupe = &mut *current_task as *mut GreenTask; // The current task is placed inside an enum with the cleanup // function. This enum is then placed inside the scheduler. @@ -871,7 +871,7 @@ impl Scheduler { // * Utility Functions - pub fn sched_id(&self) -> uint { self as *Scheduler as uint } + pub fn sched_id(&self) -> uint { self as *const Scheduler as uint } pub fn run_cleanup_job(&mut self) { let cleanup_job = self.cleanup_job.take_unwrap(); @@ -1413,7 +1413,7 @@ mod test { impl Drop for S { fn drop(&mut self) { - let _foo = box 0; + let _foo = box 0i; } } diff --git a/src/libgreen/simple.rs b/src/libgreen/simple.rs index 7b738ed9c7c15..874ddbfe7ed0e 100644 --- a/src/libgreen/simple.rs +++ b/src/libgreen/simple.rs @@ -32,7 +32,7 @@ impl Runtime for SimpleTask { assert!(times == 1); let me = &mut *self as *mut SimpleTask; - let cur_dupe = &*cur_task as *Task; + let cur_dupe = &mut *cur_task as *mut Task; cur_task.put_runtime(self); let task = BlockedTask::block(cur_task); diff --git a/src/libgreen/stack.rs b/src/libgreen/stack.rs index 526ce66b1ead8..c4885edb7d3a7 100644 --- a/src/libgreen/stack.rs +++ b/src/libgreen/stack.rs @@ -78,14 +78,14 @@ impl Stack { } /// Point to the low end of the allocated stack - pub fn start(&self) -> *uint { - self.buf.data as *uint + pub fn start(&self) -> *const uint { + self.buf.data as *const uint } /// Point one uint beyond the high end of the allocated stack - pub fn end(&self) -> *uint { + pub fn end(&self) -> *const uint { unsafe { - self.buf.data.offset(self.buf.len as int) as *uint + self.buf.data.offset(self.buf.len as int) as *const uint } } } @@ -168,8 +168,8 @@ fn max_cached_stacks() -> uint { } extern { - fn rust_valgrind_stack_register(start: *libc::uintptr_t, - end: *libc::uintptr_t) -> libc::c_uint; + fn rust_valgrind_stack_register(start: *const libc::uintptr_t, + end: *const libc::uintptr_t) -> libc::c_uint; fn rust_valgrind_stack_deregister(id: libc::c_uint); } diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs index 25c2a95234192..68a454233cf9a 100644 --- a/src/libgreen/task.rs +++ b/src/libgreen/task.rs @@ -89,7 +89,7 @@ pub enum Home { /// /// The goal for having this weird-looking function is to reduce the number of /// allocations done on a green-task startup as much as possible. -extern fn bootstrap_green_task(task: uint, code: *(), env: *()) -> ! { +extern fn bootstrap_green_task(task: uint, code: *mut (), env: *mut ()) -> ! { // Acquire ownership of the `proc()` let start: proc() = unsafe { mem::transmute(raw::Procedure { code: code, env: env }) @@ -256,7 +256,7 @@ impl GreenTask { // context switches pub fn as_uint(&self) -> uint { - self as *GreenTask as uint + self as *const GreenTask as uint } pub unsafe fn from_uint(val: uint) -> Box { diff --git a/src/libhexfloat/lib.rs b/src/libhexfloat/lib.rs index d0e9e2e436eaa..6b2c39628fc88 100644 --- a/src/libhexfloat/lib.rs +++ b/src/libhexfloat/lib.rs @@ -77,12 +77,12 @@ fn hex_float_lit_err(s: &str) -> Option<(uint, String)> { if chars.next() != Some('x') { return Some((i, "Expected 'x'".to_string())); } i+=1; - let mut d_len = 0; + let mut d_len = 0i; for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;} if chars.next() != Some('.') { return Some((i, "Expected '.'".to_string())); } i+=1; - let mut f_len = 0; + let mut f_len = 0i; for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;} if d_len == 0 && f_len == 0 { return Some((i, "Expected digits before or after decimal \ @@ -92,7 +92,7 @@ fn hex_float_lit_err(s: &str) -> Option<(uint, String)> { return Some((i, "Expected 'p'".to_string())); } i+=1; if chars.peek() == Some(&'-') { chars.next(); i+= 1 } - let mut e_len = 0; + let mut e_len = 0i; for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1} if e_len == 0 { return Some((i, "Expected exponent digits".to_string())); diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 83b6c696adf07..81e50889952ec 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -369,14 +369,14 @@ pub mod types { pub struct glob_t { pub gl_pathc: size_t, - pub gl_pathv: **c_char, + pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, - pub __unused1: *c_void, - pub __unused2: *c_void, - pub __unused3: *c_void, - pub __unused4: *c_void, - pub __unused5: *c_void, + pub __unused1: *mut c_void, + pub __unused2: *mut c_void, + pub __unused3: *mut c_void, + pub __unused4: *mut c_void, + pub __unused5: *mut c_void, } pub struct timeval { @@ -444,18 +444,18 @@ pub mod types { pub ai_addrlen: socklen_t, #[cfg(target_os = "linux")] - pub ai_addr: *sockaddr, + pub ai_addr: *mut sockaddr, #[cfg(target_os = "linux")] - pub ai_canonname: *c_char, + pub ai_canonname: *mut c_char, #[cfg(target_os = "android")] - pub ai_canonname: *c_char, + pub ai_canonname: *mut c_char, #[cfg(target_os = "android")] - pub ai_addr: *sockaddr, + pub ai_addr: *mut sockaddr, - pub ai_next: *addrinfo, + pub ai_next: *mut addrinfo, } pub struct sockaddr_un { pub sun_family: sa_family_t, @@ -755,15 +755,15 @@ pub mod types { pub __unused1: size_t, pub gl_offs: size_t, pub __unused2: c_int, - pub gl_pathv: **c_char, + pub gl_pathv: *mut *mut c_char, - pub __unused3: *c_void, + pub __unused3: *mut c_void, - pub __unused4: *c_void, - pub __unused5: *c_void, - pub __unused6: *c_void, - pub __unused7: *c_void, - pub __unused8: *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 { @@ -834,9 +834,9 @@ pub mod types { pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, - pub ai_canonname: *c_char, - pub ai_addr: *sockaddr, - pub ai_next: *addrinfo, + pub ai_canonname: *mut c_char, + pub ai_addr: *mut sockaddr, + pub ai_next: *mut addrinfo, } pub struct sockaddr_un { pub sun_len: u8, @@ -926,7 +926,7 @@ pub mod types { pub modtime: time_t, } - pub type pthread_attr_t = *c_void; + pub type pthread_attr_t = *mut c_void; } pub mod posix08 { } @@ -1032,9 +1032,9 @@ pub mod types { pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: size_t, - pub ai_canonname: *c_char, - pub ai_addr: *sockaddr, - pub ai_next: *addrinfo, + pub ai_canonname: *mut c_char, + pub ai_addr: *mut sockaddr, + pub ai_next: *mut addrinfo, } pub struct sockaddr_un { pub sun_family: sa_family_t, @@ -1146,8 +1146,8 @@ pub mod types { pub type LARGE_INTEGER = c_longlong; pub type PLARGE_INTEGER = *mut c_longlong; - pub type LPCWSTR = *WCHAR; - pub type LPCSTR = *CHAR; + pub type LPCWSTR = *const WCHAR; + pub type LPCSTR = *const CHAR; pub type LPWSTR = *mut WCHAR; pub type LPSTR = *mut CHAR; @@ -1163,7 +1163,7 @@ pub mod types { pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES; pub type LPVOID = *mut c_void; - pub type LPCVOID = *c_void; + pub type LPCVOID = *const c_void; pub type LPBYTE = *mut BYTE; pub type LPWORD = *mut WORD; pub type LPDWORD = *mut DWORD; @@ -1235,8 +1235,8 @@ pub mod types { pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION; pub struct OVERLAPPED { - pub Internal: *c_ulong, - pub InternalHigh: *c_ulong, + pub Internal: *mut c_ulong, + pub InternalHigh: *mut c_ulong, pub Offset: DWORD, pub OffsetHigh: DWORD, pub hEvent: HANDLE, @@ -1312,15 +1312,15 @@ pub mod types { pub __unused1: c_int, pub gl_offs: size_t, pub __unused2: c_int, - pub gl_pathv: **c_char, + pub gl_pathv: *mut *mut c_char, - pub __unused3: *c_void, + pub __unused3: *mut c_void, - pub __unused4: *c_void, - pub __unused5: *c_void, - pub __unused6: *c_void, - pub __unused7: *c_void, - pub __unused8: *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 { @@ -1392,9 +1392,9 @@ pub mod types { pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, - pub ai_canonname: *c_char, - pub ai_addr: *sockaddr, - pub ai_next: *addrinfo, + pub ai_canonname: *mut c_char, + pub ai_addr: *mut sockaddr, + pub ai_next: *mut addrinfo, } pub struct sockaddr_un { pub sun_len: u8, @@ -3543,53 +3543,56 @@ pub mod funcs { use types::os::arch::c95::{c_char, c_int, c_long, size_t}; extern { - pub fn fopen(filename: *c_char, mode: *c_char) -> *FILE; - pub fn freopen(filename: *c_char, mode: *c_char, file: *FILE) - -> *FILE; - pub fn fflush(file: *FILE) -> c_int; - pub fn fclose(file: *FILE) -> c_int; - pub fn remove(filename: *c_char) -> c_int; - pub fn rename(oldname: *c_char, newname: *c_char) -> c_int; - pub fn tmpfile() -> *FILE; - pub fn setvbuf(stream: *FILE, - buffer: *c_char, + pub fn fopen(filename: *const c_char, + mode: *const c_char) -> *mut FILE; + pub fn freopen(filename: *const c_char, mode: *const c_char, + file: *mut FILE) + -> *mut FILE; + pub fn fflush(file: *mut FILE) -> c_int; + pub fn fclose(file: *mut FILE) -> c_int; + pub fn remove(filename: *const c_char) -> c_int; + pub fn rename(oldname: *const c_char, + newname: *const c_char) -> c_int; + pub fn tmpfile() -> *mut FILE; + pub fn setvbuf(stream: *mut FILE, + buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; - pub fn setbuf(stream: *FILE, buf: *c_char); + pub fn setbuf(stream: *mut FILE, buf: *mut c_char); // Omitted: printf and scanf variants. - pub fn fgetc(stream: *FILE) -> c_int; - pub fn fgets(buf: *mut c_char, n: c_int, stream: *FILE) - -> *c_char; - pub fn fputc(c: c_int, stream: *FILE) -> c_int; - pub fn fputs(s: *c_char, stream: *FILE) -> *c_char; + pub fn fgetc(stream: *mut FILE) -> c_int; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) + -> *mut c_char; + pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; + pub fn fputs(s: *const c_char, stream: *mut FILE)-> c_int; // Omitted: getc, getchar (might be macros). // Omitted: gets, so ridiculously unsafe that it should not // survive. // Omitted: putc, putchar (might be macros). - pub fn puts(s: *c_char) -> c_int; - pub fn ungetc(c: c_int, stream: *FILE) -> c_int; + pub fn puts(s: *const c_char) -> c_int; + pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, - stream: *FILE) + stream: *mut FILE) -> size_t; - pub fn fwrite(ptr: *c_void, + pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, - stream: *FILE) + stream: *mut FILE) -> size_t; - pub fn fseek(stream: *FILE, offset: c_long, whence: c_int) + pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; - pub fn ftell(stream: *FILE) -> c_long; - pub fn rewind(stream: *FILE); - pub fn fgetpos(stream: *FILE, ptr: *fpos_t) -> c_int; - pub fn fsetpos(stream: *FILE, ptr: *fpos_t) -> c_int; - pub fn feof(stream: *FILE) -> c_int; - pub fn ferror(stream: *FILE) -> c_int; - pub fn perror(s: *c_char); + pub fn ftell(stream: *mut FILE) -> c_long; + pub fn rewind(stream: *mut FILE); + pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; + pub fn fsetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; + pub fn feof(stream: *mut FILE) -> c_int; + pub fn ferror(stream: *mut FILE) -> c_int; + pub fn perror(s: *const c_char); } } @@ -3603,22 +3606,23 @@ pub mod funcs { pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; // Omitted: div, ldiv (return pub type incomplete). - pub fn atof(s: *c_char) -> c_double; - pub fn atoi(s: *c_char) -> c_int; - pub fn strtod(s: *c_char, endp: **c_char) -> c_double; - pub fn strtol(s: *c_char, endp: **c_char, base: c_int) - -> c_long; - pub fn strtoul(s: *c_char, endp: **c_char, base: c_int) - -> c_ulong; - pub fn calloc(nobj: size_t, size: size_t) -> *c_void; + pub fn atof(s: *const c_char) -> c_double; + pub fn atoi(s: *const c_char) -> c_int; + pub fn strtod(s: *const c_char, + endp: *mut *mut c_char) -> c_double; + pub fn strtol(s: *const c_char, + endp: *mut *mut c_char, base: c_int) -> c_long; + pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, + base: c_int) -> c_ulong; + pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; // Omitted: atexit. - pub fn system(s: *c_char) -> c_int; - pub fn getenv(s: *c_char) -> *c_char; + pub fn system(s: *const c_char) -> c_int; + pub fn getenv(s: *const c_char) -> *mut c_char; // Omitted: bsearch, qsort pub fn rand() -> c_int; pub fn srand(seed: c_uint); @@ -3631,32 +3635,40 @@ pub mod funcs { use types::os::arch::c95::{wchar_t}; extern { - pub fn strcpy(dst: *c_char, src: *c_char) -> *c_char; - pub fn strncpy(dst: *c_char, src: *c_char, n: size_t) - -> *c_char; - pub fn strcat(s: *c_char, ct: *c_char) -> *c_char; - pub fn strncat(s: *c_char, ct: *c_char, n: size_t) -> *c_char; - pub fn strcmp(cs: *c_char, ct: *c_char) -> c_int; - pub fn strncmp(cs: *c_char, ct: *c_char, n: size_t) -> c_int; - pub fn strcoll(cs: *c_char, ct: *c_char) -> c_int; - pub fn strchr(cs: *c_char, c: c_int) -> *c_char; - pub fn strrchr(cs: *c_char, c: c_int) -> *c_char; - pub fn strspn(cs: *c_char, ct: *c_char) -> size_t; - pub fn strcspn(cs: *c_char, ct: *c_char) -> size_t; - pub fn strpbrk(cs: *c_char, ct: *c_char) -> *c_char; - pub fn strstr(cs: *c_char, ct: *c_char) -> *c_char; - pub fn strlen(cs: *c_char) -> size_t; - pub fn strerror(n: c_int) -> *c_char; - pub fn strtok(s: *c_char, t: *c_char) -> *c_char; - pub fn strxfrm(s: *c_char, ct: *c_char, n: size_t) -> size_t; - pub fn wcslen(buf: *wchar_t) -> size_t; + pub fn strcpy(dst: *mut c_char, + src: *const c_char) -> *mut c_char; + pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) + -> *mut c_char; + pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; + pub fn strncat(s: *mut c_char, ct: *const c_char, + n: size_t) -> *mut c_char; + pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; + pub fn strncmp(cs: *const c_char, ct: *const c_char, + n: size_t) -> c_int; + pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; + pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; + pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; + pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; + pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; + pub fn strpbrk(cs: *const c_char, + ct: *const c_char) -> *mut c_char; + pub fn strstr(cs: *const c_char, + ct: *const c_char) -> *mut c_char; + pub fn strlen(cs: *const c_char) -> size_t; + pub fn strerror(n: c_int) -> *mut c_char; + pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; + pub fn strxfrm(s: *mut c_char, ct: *const c_char, + n: size_t) -> size_t; + pub fn wcslen(buf: *const wchar_t) -> size_t; // Omitted: memcpy, memmove, memset (provided by LLVM) // These are fine to execute on the Rust stack. They must be, // in fact, because LLVM generates calls to them! - pub fn memcmp(cx: *c_void, ct: *c_void, n: size_t) -> c_int; - pub fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void; + pub fn memcmp(cx: *const c_void, ct: *const c_void, + n: size_t) -> c_int; + pub fn memchr(cx: *const c_void, c: c_int, + n: size_t) -> *mut c_void; } } } @@ -3675,21 +3687,21 @@ pub mod funcs { extern { #[link_name = "_chmod"] - pub fn chmod(path: *c_char, mode: c_int) -> c_int; + pub fn chmod(path: *const c_char, mode: c_int) -> c_int; #[link_name = "_wchmod"] - pub fn wchmod(path: *wchar_t, mode: c_int) -> c_int; + pub fn wchmod(path: *const wchar_t, mode: c_int) -> c_int; #[link_name = "_mkdir"] - pub fn mkdir(path: *c_char) -> c_int; + pub fn mkdir(path: *const c_char) -> c_int; #[link_name = "_wrmdir"] - pub fn wrmdir(path: *wchar_t) -> c_int; + pub fn wrmdir(path: *const wchar_t) -> c_int; #[link_name = "_fstat64"] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; #[link_name = "_stat64"] - pub fn stat(path: *c_char, buf: *mut stat) -> c_int; + pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; #[link_name = "_wstat64"] - pub fn wstat(path: *wchar_t, buf: *mut stat) -> c_int; + pub fn wstat(path: *const wchar_t, buf: *mut stat) -> c_int; #[link_name = "_wutime64"] - pub fn wutime(file: *wchar_t, buf: *utimbuf) -> c_int; + pub fn wutime(file: *const wchar_t, buf: *mut utimbuf) -> c_int; } } @@ -3699,13 +3711,14 @@ pub mod funcs { extern { #[link_name = "_popen"] - pub fn popen(command: *c_char, mode: *c_char) -> *FILE; + pub fn popen(command: *const c_char, + mode: *const c_char) -> *mut FILE; #[link_name = "_pclose"] - pub fn pclose(stream: *FILE) -> c_int; + pub fn pclose(stream: *mut FILE) -> c_int; #[link_name = "_fdopen"] - pub fn fdopen(fd: c_int, mode: *c_char) -> *FILE; + pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE; #[link_name = "_fileno"] - pub fn fileno(stream: *FILE) -> c_int; + pub fn fileno(stream: *mut FILE) -> c_int; } } @@ -3713,13 +3726,13 @@ pub mod funcs { use types::os::arch::c95::{c_int, c_char, wchar_t}; extern { #[link_name = "_open"] - pub fn open(path: *c_char, oflag: c_int, mode: c_int) + pub fn open(path: *const c_char, oflag: c_int, mode: c_int) -> c_int; #[link_name = "_wopen"] - pub fn wopen(path: *wchar_t, oflag: c_int, mode: c_int) + pub fn wopen(path: *const wchar_t, oflag: c_int, mode: c_int) -> c_int; #[link_name = "_creat"] - pub fn creat(path: *c_char, mode: c_int) -> c_int; + pub fn creat(path: *const c_char, mode: c_int) -> c_int; } } @@ -3735,9 +3748,9 @@ pub mod funcs { extern { #[link_name = "_access"] - pub fn access(path: *c_char, amode: c_int) -> c_int; + pub fn access(path: *const c_char, amode: c_int) -> c_int; #[link_name = "_chdir"] - pub fn chdir(dir: *c_char) -> c_int; + pub fn chdir(dir: *const c_char) -> c_int; #[link_name = "_close"] pub fn close(fd: c_int) -> c_int; #[link_name = "_dup"] @@ -3745,17 +3758,20 @@ pub mod funcs { #[link_name = "_dup2"] pub fn dup2(src: c_int, dst: c_int) -> c_int; #[link_name = "_execv"] - pub fn execv(prog: *c_char, argv: **c_char) -> intptr_t; + pub fn execv(prog: *const c_char, + argv: *mut *const c_char) -> intptr_t; #[link_name = "_execve"] - pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char) + pub fn execve(prog: *const c_char, argv: *mut *const c_char, + envp: *mut *const c_char) -> c_int; #[link_name = "_execvp"] - pub fn execvp(c: *c_char, argv: **c_char) -> c_int; + pub fn execvp(c: *const c_char, + argv: *mut *const c_char) -> c_int; #[link_name = "_execvpe"] - pub fn execvpe(c: *c_char, argv: **c_char, envp: **c_char) - -> c_int; + pub fn execvpe(c: *const c_char, argv: *mut *const c_char, + envp: *mut *const c_char) -> c_int; #[link_name = "_getcwd"] - pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char; + pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; #[link_name = "_getpid"] pub fn getpid() -> c_int; #[link_name = "_isatty"] @@ -3770,11 +3786,12 @@ pub mod funcs { pub fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int; #[link_name = "_rmdir"] - pub fn rmdir(path: *c_char) -> c_int; + pub fn rmdir(path: *const c_char) -> c_int; #[link_name = "_unlink"] - pub fn unlink(c: *c_char) -> c_int; + pub fn unlink(c: *const c_char) -> c_int; #[link_name = "_write"] - pub fn write(fd: c_int, buf: *c_void, count: c_uint) -> c_int; + pub fn write(fd: c_int, buf: *const c_void, + count: c_uint) -> c_int; } } @@ -3795,7 +3812,7 @@ pub mod funcs { use types::os::arch::posix88::mode_t; extern { - pub fn chmod(path: *c_char, mode: mode_t) -> c_int; + pub fn chmod(path: *const c_char, mode: mode_t) -> c_int; pub fn fchmod(fd: c_int, mode: mode_t) -> c_int; #[cfg(target_os = "linux")] @@ -3808,18 +3825,18 @@ pub mod funcs { #[link_name = "fstat64"] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; - pub fn mkdir(path: *c_char, mode: mode_t) -> c_int; - pub fn mkfifo(path: *c_char, mode: mode_t) -> c_int; + pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; + pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; #[cfg(target_os = "linux")] #[cfg(target_os = "freebsd")] #[cfg(target_os = "android")] #[cfg(target_os = "ios")] - pub fn stat(path: *c_char, buf: *mut stat) -> c_int; + pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] #[link_name = "stat64"] - pub fn stat(path: *c_char, buf: *mut stat) -> c_int; + pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; } } @@ -3828,10 +3845,11 @@ pub mod funcs { use types::os::arch::c95::{c_char, c_int}; extern { - pub fn popen(command: *c_char, mode: *c_char) -> *FILE; - pub fn pclose(stream: *FILE) -> c_int; - pub fn fdopen(fd: c_int, mode: *c_char) -> *FILE; - pub fn fileno(stream: *FILE) -> c_int; + pub fn popen(command: *const c_char, + mode: *const c_char) -> *mut FILE; + pub fn pclose(stream: *mut FILE) -> c_int; + pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE; + pub fn fileno(stream: *mut FILE) -> c_int; } } @@ -3840,9 +3858,9 @@ pub mod funcs { use types::os::arch::posix88::mode_t; extern { - pub fn open(path: *c_char, oflag: c_int, mode: c_int) + pub fn open(path: *const c_char, oflag: c_int, mode: c_int) -> c_int; - pub fn creat(path: *c_char, mode: mode_t) -> c_int; + pub fn creat(path: *const c_char, mode: mode_t) -> c_int; pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; } } @@ -3860,17 +3878,17 @@ pub mod funcs { extern { #[link_name="rust_opendir"] - pub fn opendir(dirname: *c_char) -> *DIR; + pub fn opendir(dirname: *const c_char) -> *mut DIR; #[link_name="rust_readdir_r"] - pub fn readdir_r(dirp: *DIR, entry: *mut dirent_t, + pub fn readdir_r(dirp: *mut DIR, entry: *mut dirent_t, result: *mut *mut dirent_t) -> c_int; } extern { - pub fn closedir(dirp: *DIR) -> c_int; - pub fn rewinddir(dirp: *DIR); - pub fn seekdir(dirp: *DIR, loc: c_long); - pub fn telldir(dirp: *DIR) -> c_long; + pub fn closedir(dirp: *mut DIR) -> c_int; + pub fn rewinddir(dirp: *mut DIR); + pub fn seekdir(dirp: *mut DIR, loc: c_long); + pub fn telldir(dirp: *mut DIR) -> c_long; } } @@ -3886,60 +3904,65 @@ pub mod funcs { pub static _PC_NAME_MAX: c_int = 4; extern { - pub fn access(path: *c_char, amode: c_int) -> c_int; + pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn alarm(seconds: c_uint) -> c_uint; - pub fn chdir(dir: *c_char) -> c_int; - pub fn chown(path: *c_char, uid: uid_t, gid: gid_t) -> c_int; + pub fn chdir(dir: *const c_char) -> c_int; + pub fn chown(path: *const c_char, uid: uid_t, + gid: gid_t) -> c_int; pub fn close(fd: c_int) -> c_int; pub fn dup(fd: c_int) -> c_int; pub fn dup2(src: c_int, dst: c_int) -> c_int; - pub fn execv(prog: *c_char, argv: **c_char) -> c_int; - pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char) + pub fn execv(prog: *const c_char, + argv: *mut *const c_char) -> c_int; + pub fn execve(prog: *const c_char, argv: *mut *const c_char, + envp: *mut *const c_char) -> c_int; - pub fn execvp(c: *c_char, argv: **c_char) -> c_int; + pub fn execvp(c: *const c_char, + argv: *mut *const c_char) -> c_int; pub fn fork() -> pid_t; pub fn fpathconf(filedes: c_int, name: c_int) -> c_long; - pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char; + pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgid() -> gid_t ; pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; - pub fn getlogin() -> *c_char; - pub fn getopt(argc: c_int, argv: **c_char, optstr: *c_char) - -> c_int; + pub fn getlogin() -> *mut c_char; + pub fn getopt(argc: c_int, argv: *mut *const c_char, + optstr: *const c_char) -> c_int; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; pub fn getppid() -> pid_t; pub fn getuid() -> uid_t; pub fn isatty(fd: c_int) -> c_int; - pub fn link(src: *c_char, dst: *c_char) -> c_int; + pub fn link(src: *const c_char, dst: *const c_char) -> c_int; pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; - pub fn pathconf(path: *c_char, name: c_int) -> c_long; + pub fn pathconf(path: *mut c_char, name: c_int) -> c_long; pub fn pause() -> c_int; pub fn pipe(fds: *mut c_int) -> c_int; pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; - pub fn rmdir(path: *c_char) -> c_int; + pub fn rmdir(path: *const c_char) -> c_int; pub fn setgid(gid: gid_t) -> c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int; pub fn setsid() -> pid_t; pub fn setuid(uid: uid_t) -> c_int; pub fn sleep(secs: c_uint) -> c_uint; pub fn usleep(secs: c_uint) -> c_int; - pub fn nanosleep(rqtp: *timespec, rmtp: *mut timespec) -> c_int; + pub fn nanosleep(rqtp: *const timespec, + rmtp: *mut timespec) -> c_int; pub fn sysconf(name: c_int) -> c_long; pub fn tcgetpgrp(fd: c_int) -> pid_t; - pub fn ttyname(fd: c_int) -> *c_char; - pub fn unlink(c: *c_char) -> c_int; - pub fn write(fd: c_int, buf: *c_void, count: size_t) + pub fn ttyname(fd: c_int) -> *mut c_char; + pub fn unlink(c: *const c_char) -> c_int; + pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; - pub fn pread(fd: c_int, buf: *c_void, count: size_t, + pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t; - pub fn pwrite(fd: c_int, buf: *c_void, count: size_t, + pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_t) -> ssize_t; - pub fn utime(file: *c_char, buf: *utimbuf) -> c_int; + pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; } } @@ -3958,8 +3981,8 @@ pub mod funcs { use types::os::arch::posix88::{mode_t, off_t}; extern { - pub fn mlock(addr: *c_void, len: size_t) -> c_int; - pub fn munlock(addr: *c_void, len: size_t) -> c_int; + pub fn mlock(addr: *const c_void, len: size_t) -> c_int; + pub fn munlock(addr: *const c_void, len: size_t) -> c_int; pub fn mlockall(flags: c_int) -> c_int; pub fn munlockall() -> c_int; @@ -3977,9 +4000,9 @@ pub mod funcs { pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; - pub fn shm_open(name: *c_char, oflag: c_int, mode: mode_t) + pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; - pub fn shm_unlink(name: *c_char) -> c_int; + pub fn shm_unlink(name: *const c_char) -> c_int; } } } @@ -3999,11 +4022,11 @@ pub mod funcs { #[cfg(target_os = "freebsd")] #[cfg(target_os = "android")] #[cfg(target_os = "ios")] - pub fn lstat(path: *c_char, buf: *mut stat) -> c_int; + pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] #[link_name = "lstat64"] - pub fn lstat(path: *c_char, buf: *mut stat) -> c_int; + pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; } } @@ -4012,7 +4035,7 @@ pub mod funcs { use types::os::arch::posix88::{ssize_t, off_t}; extern { - pub fn readlink(path: *c_char, + pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t; @@ -4023,12 +4046,13 @@ pub mod funcs { #[cfg(target_os = "android")] pub fn fdatasync(fd: c_int) -> c_int; - pub fn setenv(name: *c_char, val: *c_char, overwrite: c_int) - -> c_int; - pub fn unsetenv(name: *c_char) -> c_int; - pub fn putenv(string: *c_char) -> c_int; + pub fn setenv(name: *const c_char, val: *const c_char, + overwrite: c_int) -> c_int; + pub fn unsetenv(name: *const c_char) -> c_int; + pub fn putenv(string: *mut c_char) -> c_int; - pub fn symlink(path1: *c_char, path2: *c_char) -> c_int; + pub fn symlink(path1: *const c_char, + path2: *const c_char) -> c_int; pub fn ftruncate(fd: c_int, length: off_t) -> c_int; } @@ -4057,9 +4081,10 @@ pub mod funcs { use types::os::common::posix01::{glob_t}; extern { - pub fn glob(pattern: *c_char, + pub fn glob(pattern: *const c_char, flags: c_int, - errfunc: ::Nullable int>, + errfunc: ::Nullable int>, pglob: *mut glob_t); pub fn globfree(pglob: *mut glob_t); } @@ -4070,7 +4095,7 @@ pub mod funcs { use types::os::arch::c95::{c_int, size_t}; extern { - pub fn posix_madvise(addr: *c_void, + pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; @@ -4114,9 +4139,9 @@ pub mod funcs { extern "system" { pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int; - pub fn connect(socket: c_int, address: *sockaddr, + pub fn connect(socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int; - pub fn bind(socket: c_int, address: *sockaddr, + pub fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int; pub fn listen(socket: c_int, backlog: c_int) -> c_int; pub fn accept(socket: c_int, address: *mut sockaddr, @@ -4126,7 +4151,8 @@ pub mod funcs { pub fn getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; pub fn setsockopt(socket: c_int, level: c_int, name: c_int, - value: *c_void, option_len: socklen_t) -> c_int; + value: *const c_void, + option_len: socklen_t) -> c_int; pub fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t; pub fn send(socket: c_int, buf: *mut c_void, len: size_t, @@ -4134,8 +4160,8 @@ pub mod funcs { pub fn recvfrom(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> ssize_t; - pub fn sendto(socket: c_int, buf: *c_void, len: size_t, - flags: c_int, addr: *sockaddr, + pub fn sendto(socket: c_int, buf: *const c_void, len: size_t, + flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t; pub fn shutdown(socket: c_int, how: c_int) -> c_int; } @@ -4150,9 +4176,9 @@ pub mod funcs { extern "system" { pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> SOCKET; - pub fn connect(socket: SOCKET, address: *sockaddr, + pub fn connect(socket: SOCKET, address: *const sockaddr, len: socklen_t) -> c_int; - pub fn bind(socket: SOCKET, address: *sockaddr, + pub fn bind(socket: SOCKET, address: *const sockaddr, address_len: socklen_t) -> c_int; pub fn listen(socket: SOCKET, backlog: c_int) -> c_int; pub fn accept(socket: SOCKET, address: *mut sockaddr, @@ -4162,7 +4188,8 @@ pub mod funcs { pub fn getsockname(socket: SOCKET, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; pub fn setsockopt(socket: SOCKET, level: c_int, name: c_int, - value: *c_void, option_len: socklen_t) -> c_int; + value: *const c_void, + option_len: socklen_t) -> c_int; pub fn closesocket(socket: SOCKET) -> c_int; pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int; @@ -4171,8 +4198,8 @@ pub mod funcs { pub fn recvfrom(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int, addr: *mut sockaddr, addrlen: *mut c_int) -> ssize_t; - pub fn sendto(socket: SOCKET, buf: *c_void, len: c_int, - flags: c_int, addr: *sockaddr, + pub fn sendto(socket: SOCKET, buf: *const c_void, len: c_int, + flags: c_int, addr: *const sockaddr, addrlen: c_int) -> c_int; pub fn shutdown(socket: SOCKET, how: c_int) -> c_int; } @@ -4186,27 +4213,27 @@ pub mod funcs { use types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, size_t}; extern { - pub fn sysctl(name: *c_int, + pub fn sysctl(name: *mut c_int, namelen: c_uint, oldp: *mut c_void, oldlenp: *mut size_t, - newp: *c_void, + newp: *mut c_void, newlen: size_t) -> c_int; - pub fn sysctlbyname(name: *c_char, + pub fn sysctlbyname(name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t, - newp: *c_void, + newp: *mut c_void, newlen: size_t) -> c_int; - pub fn sysctlnametomib(name: *c_char, + pub fn sysctlnametomib(name: *const c_char, mibp: *mut c_int, sizep: *mut size_t) -> c_int; pub fn getdtablesize() -> c_int; - pub fn madvise(addr: *c_void, len: size_t, advice: c_int) + pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; - pub fn mincore(addr: *c_void, len: size_t, vec: *c_uchar) + pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int; } } @@ -4298,7 +4325,7 @@ pub mod funcs { -> DWORD; pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn GetLastError() -> DWORD; - pub fn FindFirstFileW(fileName: *u16, findFileData: HANDLE) + pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: HANDLE) -> HANDLE; pub fn FindNextFileW(findFile: HANDLE, findFileData: HANDLE) -> BOOL; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 59bed3840a36f..b99a9d75f33e5 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -144,8 +144,8 @@ static DEFAULT_LOG_LEVEL: u32 = 1; /// logging statement should be run. static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL; -static mut DIRECTIVES: *Vec = - 0 as *Vec; +static mut DIRECTIVES: *const Vec = + 0 as *const Vec; /// Debug log level pub static DEBUG: u32 = 4; @@ -351,7 +351,7 @@ fn init() { assert!(!DIRECTIVES.is_null()); let _directives: Box> = mem::transmute(DIRECTIVES); - DIRECTIVES = 0 as *Vec; + DIRECTIVES = 0 as *const Vec; }); } } diff --git a/src/libnative/io/addrinfo.rs b/src/libnative/io/addrinfo.rs index 255c3f4bd213d..0977b55d8b978 100644 --- a/src/libnative/io/addrinfo.rs +++ b/src/libnative/io/addrinfo.rs @@ -37,19 +37,21 @@ impl GetAddrInfoRequest { ai_socktype: 0, ai_protocol: 0, ai_addrlen: 0, - ai_canonname: null(), - ai_addr: null(), - ai_next: null() + ai_canonname: mut_null(), + ai_addr: mut_null(), + ai_next: mut_null() } }); - let hint_ptr = hint.as_ref().map_or(null(), |x| x as *libc::addrinfo); + let hint_ptr = hint.as_ref().map_or(null(), |x| { + x as *const libc::addrinfo + }); let mut res = mut_null(); // Make the call let s = unsafe { - let ch = if c_host.is_null() { null() } else { c_host.with_ref(|x| x) }; - let cs = if c_serv.is_null() { null() } else { c_serv.with_ref(|x| x) }; + let ch = if c_host.is_null() { null() } else { c_host.as_ptr() }; + let cs = if c_serv.is_null() { null() } else { c_serv.as_ptr() }; getaddrinfo(ch, cs, hint_ptr, &mut res) }; @@ -87,11 +89,12 @@ impl GetAddrInfoRequest { } extern "system" { - fn getaddrinfo(node: *c_char, service: *c_char, - hints: *libc::addrinfo, res: *mut *mut libc::addrinfo) -> c_int; + fn getaddrinfo(node: *const c_char, service: *const c_char, + hints: *const libc::addrinfo, + res: *mut *mut libc::addrinfo) -> c_int; fn freeaddrinfo(res: *mut libc::addrinfo); #[cfg(not(windows))] - fn gai_strerror(errcode: c_int) -> *c_char; + fn gai_strerror(errcode: c_int) -> *const c_char; } #[cfg(windows)] diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs index b1bc36e0b05e0..9fbf3659d3f6b 100644 --- a/src/libnative/io/c_unix.rs +++ b/src/libnative/io/c_unix.rs @@ -57,12 +57,12 @@ pub static WNOHANG: libc::c_int = 1; extern { pub fn gettimeofday(timeval: *mut libc::timeval, - tzp: *libc::c_void) -> libc::c_int; + tzp: *mut libc::c_void) -> libc::c_int; pub fn select(nfds: libc::c_int, - readfds: *fd_set, - writefds: *fd_set, - errorfds: *fd_set, - timeout: *libc::timeval) -> libc::c_int; + readfds: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *mut libc::timeval) -> libc::c_int; pub fn getsockopt(sockfd: libc::c_int, level: libc::c_int, optname: libc::c_int, @@ -75,7 +75,7 @@ extern { options: libc::c_int) -> libc::pid_t; pub fn sigaction(signum: libc::c_int, - act: *sigaction, + act: *const sigaction, oldact: *mut sigaction) -> libc::c_int; pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int; diff --git a/src/libnative/io/c_win32.rs b/src/libnative/io/c_win32.rs index 1b6525c6e3877..802526c919695 100644 --- a/src/libnative/io/c_win32.rs +++ b/src/libnative/io/c_win32.rs @@ -28,7 +28,7 @@ pub struct WSADATA { pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1], pub iMaxSockets: u16, pub iMaxUdpDg: u16, - pub lpVendorInfo: *u8, + pub lpVendorInfo: *mut u8, } pub type LPWSADATA = *mut WSADATA; @@ -53,10 +53,10 @@ extern "system" { pub fn ioctlsocket(s: libc::SOCKET, cmd: libc::c_long, argp: *mut libc::c_ulong) -> libc::c_int; pub fn select(nfds: libc::c_int, - readfds: *fd_set, - writefds: *fd_set, - exceptfds: *fd_set, - timeout: *libc::timeval) -> libc::c_int; + readfds: *mut fd_set, + writefds: *mut fd_set, + exceptfds: *mut fd_set, + timeout: *mut libc::timeval) -> libc::c_int; pub fn getsockopt(sockfd: libc::SOCKET, level: libc::c_int, optname: libc::c_int, @@ -70,6 +70,7 @@ extern "system" { pub mod compat { use std::intrinsics::{atomic_store_relaxed, transmute}; + use std::iter::Iterator; use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; extern "system" { @@ -82,7 +83,8 @@ pub mod compat { // layer (after it's loaded) shouldn't be any slower than a regular DLL // call. unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) { - let module = module.to_utf16().append_one(0); + let module: Vec = module.utf16_units().collect(); + let module = module.append_one(0); symbol.with_c_str(|symbol| { let handle = GetModuleHandleW(module.as_ptr()); let func: uint = transmute(GetProcAddress(handle, symbol)); diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index edf2becc77760..ddcff2be5f340 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -68,7 +68,7 @@ impl FileDesc { pub fn inner_write(&mut self, buf: &[u8]) -> IoResult<()> { let ret = keep_going(buf, |buf, len| { unsafe { - libc::write(self.fd(), buf as *libc::c_void, + libc::write(self.fd(), buf as *const libc::c_void, len as libc::size_t) as i64 } }); @@ -91,7 +91,7 @@ impl rtio::RtioFileStream for FileDesc { } fn pread(&mut self, buf: &mut [u8], offset: u64) -> IoResult { match retry(|| unsafe { - libc::pread(self.fd(), buf.as_ptr() as *libc::c_void, + libc::pread(self.fd(), buf.as_ptr() as *mut _, buf.len() as libc::size_t, offset as libc::off_t) as libc::c_int }) { @@ -101,7 +101,7 @@ impl rtio::RtioFileStream for FileDesc { } fn pwrite(&mut self, buf: &[u8], offset: u64) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::pwrite(self.fd(), buf.as_ptr() as *libc::c_void, + libc::pwrite(self.fd(), buf.as_ptr() as *const _, buf.len() as libc::size_t, offset as libc::off_t) } as c_int)) } @@ -222,7 +222,7 @@ impl Drop for Inner { } pub struct CFile { - file: *libc::FILE, + file: *mut libc::FILE, fd: FileDesc, } @@ -231,7 +231,7 @@ impl CFile { /// /// The `CFile` takes ownership of the `FILE` pointer and will close it upon /// destruction. - pub fn new(file: *libc::FILE) -> CFile { + pub fn new(file: *mut libc::FILE) -> CFile { CFile { file: file, fd: FileDesc::new(unsafe { libc::fileno(file) }, false) @@ -263,7 +263,7 @@ impl rtio::RtioFileStream for CFile { fn write(&mut self, buf: &[u8]) -> IoResult<()> { let ret = keep_going(buf, |buf, len| { unsafe { - libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t, + libc::fwrite(buf as *const libc::c_void, 1, len as libc::size_t, self.file) as i64 } }); @@ -339,7 +339,7 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess) libc::S_IRUSR | libc::S_IWUSR), }; - match retry(|| unsafe { libc::open(path.with_ref(|p| p), flags, mode) }) { + match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) { -1 => Err(super::last_error()), fd => Ok(FileDesc::new(fd, true)), } @@ -347,7 +347,7 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess) pub fn mkdir(p: &CString, mode: uint) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::mkdir(p.with_ref(|p| p), mode as libc::mode_t) + libc::mkdir(p.as_ptr(), mode as libc::mode_t) })) } @@ -356,7 +356,7 @@ pub fn readdir(p: &CString) -> IoResult> { use libc::{opendir, readdir_r, closedir}; fn prune(root: &CString, dirs: Vec) -> Vec { - let root = unsafe { CString::new(root.with_ref(|p| p), false) }; + let root = unsafe { CString::new(root.as_ptr(), false) }; let root = Path::new(root); dirs.move_iter().filter(|path| { @@ -366,14 +366,14 @@ pub fn readdir(p: &CString) -> IoResult> { extern { fn rust_dirent_t_size() -> libc::c_int; - fn rust_list_dir_val(ptr: *mut dirent_t) -> *libc::c_char; + fn rust_list_dir_val(ptr: *mut dirent_t) -> *const libc::c_char; } let size = unsafe { rust_dirent_t_size() }; let mut buf = Vec::::with_capacity(size as uint); let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t; - let dir_ptr = p.with_ref(|buf| unsafe { opendir(buf) }); + let dir_ptr = unsafe {opendir(p.as_ptr())}; if dir_ptr as uint != 0 { let mut paths = vec!(); @@ -393,37 +393,37 @@ pub fn readdir(p: &CString) -> IoResult> { } pub fn unlink(p: &CString) -> IoResult<()> { - super::mkerr_libc(retry(|| unsafe { libc::unlink(p.with_ref(|p| p)) })) + super::mkerr_libc(retry(|| unsafe { libc::unlink(p.as_ptr()) })) } pub fn rename(old: &CString, new: &CString) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::rename(old.with_ref(|p| p), new.with_ref(|p| p)) + libc::rename(old.as_ptr(), new.as_ptr()) })) } pub fn chmod(p: &CString, mode: uint) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::chmod(p.with_ref(|p| p), mode as libc::mode_t) + libc::chmod(p.as_ptr(), mode as libc::mode_t) })) } pub fn rmdir(p: &CString) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::rmdir(p.with_ref(|p| p)) + libc::rmdir(p.as_ptr()) })) } pub fn chown(p: &CString, uid: int, gid: int) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::chown(p.with_ref(|p| p), uid as libc::uid_t, + libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })) } pub fn readlink(p: &CString) -> IoResult { - let p = p.with_ref(|p| p); - let mut len = unsafe { libc::pathconf(p, libc::_PC_NAME_MAX) }; + let p = p.as_ptr(); + let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) }; if len == -1 { len = 1024; // FIXME: read PATH_MAX from C ffi? } @@ -443,13 +443,13 @@ pub fn readlink(p: &CString) -> IoResult { pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::symlink(src.with_ref(|p| p), dst.with_ref(|p| p)) + libc::symlink(src.as_ptr(), dst.as_ptr()) })) } pub fn link(src: &CString, dst: &CString) -> IoResult<()> { super::mkerr_libc(retry(|| unsafe { - libc::link(src.with_ref(|p| p), dst.with_ref(|p| p)) + libc::link(src.as_ptr(), dst.as_ptr()) })) } @@ -489,7 +489,7 @@ fn mkstat(stat: &libc::stat) -> rtio::FileStat { pub fn stat(p: &CString) -> IoResult { let mut stat: libc::stat = unsafe { mem::zeroed() }; - match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) { + match retry(|| unsafe { libc::stat(p.as_ptr(), &mut stat) }) { 0 => Ok(mkstat(&stat)), _ => Err(super::last_error()), } @@ -497,7 +497,7 @@ pub fn stat(p: &CString) -> IoResult { pub fn lstat(p: &CString) -> IoResult { let mut stat: libc::stat = unsafe { mem::zeroed() }; - match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) { + match retry(|| unsafe { libc::lstat(p.as_ptr(), &mut stat) }) { 0 => Ok(mkstat(&stat)), _ => Err(super::last_error()), } @@ -509,7 +509,7 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> { modtime: (mtime / 1000) as libc::time_t, }; super::mkerr_libc(retry(|| unsafe { - libc::utime(p.with_ref(|p| p), &buf) + libc::utime(p.as_ptr(), &buf) })) } diff --git a/src/libnative/io/file_win32.rs b/src/libnative/io/file_win32.rs index cd9abc70a4ee8..9855360331340 100644 --- a/src/libnative/io/file_win32.rs +++ b/src/libnative/io/file_win32.rs @@ -255,7 +255,7 @@ impl Drop for Inner { pub fn to_utf16(s: &CString) -> IoResult> { match s.as_str() { - Some(s) => Ok(s.to_utf16().append_one(0)), + Some(s) => Ok(s.utf16_units().collect::>().append_one(0)), None => Err(IoError { code: libc::ERROR_INVALID_NAME as uint, extra: 0, @@ -347,7 +347,7 @@ pub fn readdir(p: &CString) -> IoResult> { use std::rt::libc_heap::malloc_raw; fn prune(root: &CString, dirs: Vec) -> Vec { - let root = unsafe { CString::new(root.with_ref(|p| p), false) }; + let root = unsafe { CString::new(root.as_ptr(), false) }; let root = Path::new(root); dirs.move_iter().filter(|path| { @@ -357,21 +357,22 @@ pub fn readdir(p: &CString) -> IoResult> { extern { fn rust_list_dir_wfd_size() -> libc::size_t; - fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16; + fn rust_list_dir_wfd_fp_buf(wfd: *mut libc::c_void) -> *const u16; } let star = Path::new(unsafe { - CString::new(p.with_ref(|p| p), false) + CString::new(p.as_ptr(), false) }).join("*"); let path = try!(to_utf16(&star.to_c_str())); unsafe { let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint); - let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE); + let find_handle = libc::FindFirstFileW(path.as_ptr(), + wfd_ptr as libc::HANDLE); if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE { let mut paths = vec!(); let mut more_files = 1 as libc::c_int; while more_files != 0 { - let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr as *c_void); + let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr as *mut c_void); if fp_buf as uint == 0 { fail!("os::list_dir() failure: got null ptr from wfd"); } else { @@ -446,7 +447,7 @@ pub fn readlink(p: &CString) -> IoResult { // without the null pointer let ret = fill_utf16_buf_and_decode(|buf, sz| unsafe { GetFinalPathNameByHandleW(handle, - buf as *u16, + buf as *const u16, sz - 1, libc::VOLUME_NAME_DOS) }); @@ -514,12 +515,12 @@ pub fn lstat(_p: &CString) -> IoResult { } pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> { - let buf = libc::utimbuf { + let mut buf = libc::utimbuf { actime: (atime / 1000) as libc::time64_t, modtime: (mtime / 1000) as libc::time64_t, }; let p = try!(to_utf16(p)); super::mkerr_libc(unsafe { - libc::wutime(p.as_ptr(), &buf) + libc::wutime(p.as_ptr(), &mut buf) }) } diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 32775e2cfb58c..f6764b8f26a79 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -132,7 +132,7 @@ fn retry(f: || -> libc::c_int) -> libc::c_int { } } -fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 { +fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 { let origamt = data.len(); let mut data = data.as_ptr(); let mut amt = origamt; diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 5dfae8d9efe64..dfc2c55cde7cb 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -105,7 +105,7 @@ fn socket(addr: rtio::SocketAddr, ty: libc::c_int) -> IoResult { fn setsockopt(fd: sock_t, opt: libc::c_int, val: libc::c_int, payload: T) -> IoResult<()> { unsafe { - let payload = &payload as *T as *libc::c_void; + let payload = &payload as *const T as *const libc::c_void; let ret = libc::setsockopt(fd, opt, val, payload, mem::size_of::() as libc::socklen_t); @@ -278,7 +278,7 @@ impl TcpStream { let ret = TcpStream::new(Inner::new(fd)); let (addr, len) = addr_to_sockaddr(addr); - let addrp = &addr as *_ as *libc::sockaddr; + let addrp = &addr as *const _ as *const libc::sockaddr; let len = len as libc::socklen_t; match timeout { @@ -369,7 +369,7 @@ impl rtio::RtioTcpStream for TcpStream { fn write(&mut self, buf: &[u8]) -> IoResult<()> { let fd = self.fd(); let dolock = || self.lock_nonblocking(); - let dowrite = |nb: bool, buf: *u8, len: uint| unsafe { + let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::send(fd, buf as *mut libc::c_void, @@ -456,7 +456,7 @@ impl TcpListener { let ret = TcpListener { inner: Inner::new(fd) }; let (addr, len) = addr_to_sockaddr(addr); - let addrp = &addr as *_ as *libc::sockaddr; + let addrp = &addr as *const _ as *const libc::sockaddr; let len = len as libc::socklen_t; // On platforms with Berkeley-derived sockets, this allows @@ -564,7 +564,7 @@ impl UdpSocket { }; let (addr, len) = addr_to_sockaddr(addr); - let addrp = &addr as *_ as *libc::sockaddr; + let addrp = &addr as *const _ as *const libc::sockaddr; let len = len as libc::socklen_t; match unsafe { libc::bind(fd, addrp, len) } { @@ -630,7 +630,7 @@ impl rtio::RtioSocket for UdpSocket { #[cfg(unix)] type msglen_t = libc::size_t; impl rtio::RtioUdpSocket for UdpSocket { - fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> { + fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> { let fd = self.fd(); let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; let storagep = &mut storage as *mut _ as *mut libc::sockaddr; @@ -652,17 +652,17 @@ impl rtio::RtioUdpSocket for UdpSocket { }) } - fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> { + fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> { let (dst, dstlen) = addr_to_sockaddr(dst); - let dstp = &dst as *_ as *libc::sockaddr; + let dstp = &dst as *const _ as *const libc::sockaddr; let dstlen = dstlen as libc::socklen_t; let fd = self.fd(); let dolock = || self.lock_nonblocking(); - let dowrite = |nb, buf: *u8, len: uint| unsafe { + let dowrite = |nb, buf: *const u8, len: uint| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::sendto(fd, - buf as *libc::c_void, + buf as *const libc::c_void, len as msglen_t, flags, dstp, @@ -842,7 +842,7 @@ pub fn write(fd: sock_t, buf: &[u8], write_everything: bool, lock: || -> T, - write: |bool, *u8, uint| -> i64) -> IoResult { + write: |bool, *const u8, uint| -> i64) -> IoResult { let mut ret = -1; let mut written = 0; if deadline == 0 { diff --git a/src/libnative/io/pipe_unix.rs b/src/libnative/io/pipe_unix.rs index db0d1743c7279..b5b2065f996ed 100644 --- a/src/libnative/io/pipe_unix.rs +++ b/src/libnative/io/pipe_unix.rs @@ -78,7 +78,7 @@ fn connect(addr: &CString, ty: libc::c_int, timeout: Option) -> IoResult { let (addr, len) = try!(addr_to_sockaddr_un(addr)); let inner = Inner::new(try!(unix_socket(ty))); - let addrp = &addr as *_ as *libc::sockaddr; + let addrp = &addr as *const _ as *const libc::sockaddr; let len = len as libc::socklen_t; match timeout { @@ -98,9 +98,9 @@ fn connect(addr: &CString, ty: libc::c_int, fn bind(addr: &CString, ty: libc::c_int) -> IoResult { let (addr, len) = try!(addr_to_sockaddr_un(addr)); let inner = Inner::new(try!(unix_socket(ty))); - let addrp = &addr as *libc::sockaddr_storage; + let addrp = &addr as *const _; match unsafe { - libc::bind(inner.fd, addrp as *libc::sockaddr, len as libc::socklen_t) + libc::bind(inner.fd, addrp as *const _, len as libc::socklen_t) } { -1 => Err(super::last_error()), _ => Ok(inner) @@ -166,7 +166,7 @@ impl rtio::RtioPipe for UnixStream { fn write(&mut self, buf: &[u8]) -> IoResult<()> { let fd = self.fd(); let dolock = || self.lock_nonblocking(); - let dowrite = |nb: bool, buf: *u8, len: uint| unsafe { + let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::send(fd, buf as *mut libc::c_void, @@ -278,7 +278,7 @@ impl Drop for UnixListener { // careful to unlink the path before we close the file descriptor to // prevent races where we unlink someone else's path. unsafe { - let _ = libc::unlink(self.path.with_ref(|p| p)); + let _ = libc::unlink(self.path.as_ptr()); } } } diff --git a/src/libnative/io/pipe_win32.rs b/src/libnative/io/pipe_win32.rs index 5d9ddb1f59c15..da713e3f2a931 100644 --- a/src/libnative/io/pipe_win32.rs +++ b/src/libnative/io/pipe_win32.rs @@ -152,7 +152,7 @@ impl Drop for Inner { } } -unsafe fn pipe(name: *u16, init: bool) -> libc::HANDLE { +unsafe fn pipe(name: *const u16, init: bool) -> libc::HANDLE { libc::CreateNamedPipeW( name, libc::PIPE_ACCESS_DUPLEX | @@ -210,7 +210,7 @@ pub struct UnixStream { } impl UnixStream { - fn try_connect(p: *u16) -> Option { + fn try_connect(p: *const u16) -> Option { // Note that most of this is lifted from the libuv implementation. // The idea is that if we fail to open a pipe in read/write mode // that we try afterwards in just read or just write diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index 59a075f22b28b..6fab73115cf9a 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -43,7 +43,7 @@ pub struct Process { /// A handle to the process - on unix this will always be NULL, but on /// windows it will be a HANDLE to the process, which will prevent the /// pid being re-used until the handle is closed. - handle: *(), + handle: *mut (), /// None until finish() is called. exit_code: Option, @@ -269,7 +269,7 @@ unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> { struct SpawnProcessResult { pid: pid_t, - handle: *(), + handle: *mut (), } #[cfg(windows)] @@ -294,6 +294,8 @@ fn spawn_process_os(cfg: ProcessConfig, use libc::funcs::extra::msvcrt::get_osfhandle; use std::mem; + use std::iter::Iterator; + use std::str::StrSlice; if cfg.gid.is_some() || cfg.uid.is_some() { return Err(IoError { @@ -328,7 +330,8 @@ fn spawn_process_os(cfg: ProcessConfig, lpSecurityDescriptor: ptr::mut_null(), bInheritHandle: 1, }; - let filename = "NUL".to_utf16().append_one(0); + let filename: Vec = "NUL".utf16_units().collect(); + let filename = filename.append_one(0); *slot = libc::CreateFileW(filename.as_ptr(), access, libc::FILE_SHARE_READ | @@ -371,7 +374,8 @@ fn spawn_process_os(cfg: ProcessConfig, with_envp(cfg.env, |envp| { with_dirp(cfg.cwd, |dirp| { - let mut cmd_str = cmd_str.to_utf16().append_one(0); + let mut cmd_str: Vec = cmd_str.as_slice().utf16_units().collect(); + cmd_str = cmd_str.append_one(0); let created = CreateProcessW(ptr::null(), cmd_str.as_mut_ptr(), ptr::mut_null(), @@ -403,7 +407,7 @@ fn spawn_process_os(cfg: ProcessConfig, Ok(SpawnProcessResult { pid: pi.dwProcessId as pid_t, - handle: pi.hProcess as *() + handle: pi.hProcess as *mut () }) } } @@ -515,14 +519,14 @@ fn spawn_process_os(cfg: ProcessConfig, } #[cfg(target_os = "macos")] - unsafe fn set_environ(envp: *c_void) { - extern { fn _NSGetEnviron() -> *mut *c_void; } + unsafe fn set_environ(envp: *const c_void) { + extern { fn _NSGetEnviron() -> *mut *const c_void; } *_NSGetEnviron() = envp; } #[cfg(not(target_os = "macos"))] - unsafe fn set_environ(envp: *c_void) { - extern { static mut environ: *c_void; } + unsafe fn set_environ(envp: *const c_void) { + extern { static mut environ: *const c_void; } environ = envp; } @@ -531,7 +535,7 @@ fn spawn_process_os(cfg: ProcessConfig, assert_eq!(ret, 0); } - let dirp = cfg.cwd.map(|c| c.with_ref(|p| p)).unwrap_or(ptr::null()); + let dirp = cfg.cwd.map(|c| c.as_ptr()).unwrap_or(ptr::null()); let cfg = unsafe { mem::transmute::>(cfg) @@ -568,7 +572,7 @@ fn spawn_process_os(cfg: ProcessConfig, Err(..) => { Ok(SpawnProcessResult { pid: pid, - handle: ptr::null() + handle: ptr::mut_null() }) } Ok(..) => fail!("short read on the cloexec pipe"), @@ -633,7 +637,7 @@ fn spawn_process_os(cfg: ProcessConfig, } else { libc::O_RDWR }; - devnull.with_ref(|p| libc::open(p, flags, 0)) + libc::open(devnull.as_ptr(), flags, 0) } Some(obj) => { let fd = obj.fd(); @@ -668,17 +672,18 @@ fn spawn_process_os(cfg: ProcessConfig, } match cfg.uid { Some(u) => { - // When dropping privileges from root, the `setgroups` call will - // remove any extraneous groups. If we don't call this, then - // even though our uid has dropped, we may still have groups - // that enable us to do super-user things. This will fail if we - // aren't root, so don't bother checking the return value, this - // is just done as an optimistic privilege dropping function. + // When dropping privileges from root, the `setgroups` call + // will remove any extraneous groups. If we don't call this, + // then even though our uid has dropped, we may still have + // groups that enable us to do super-user things. This will + // fail if we aren't root, so don't bother checking the + // return value, this is just done as an optimistic + // privilege dropping function. extern { fn setgroups(ngroups: libc::c_int, - ptr: *libc::c_void) -> libc::c_int; + ptr: *const libc::c_void) -> libc::c_int; } - let _ = setgroups(0, 0 as *libc::c_void); + let _ = setgroups(0, 0 as *const libc::c_void); if libc::setuid(u as libc::uid_t) != 0 { fail(&mut output); @@ -698,23 +703,24 @@ fn spawn_process_os(cfg: ProcessConfig, if !envp.is_null() { set_environ(envp); } - let _ = execvp(*argv, argv); + let _ = execvp(*argv, argv as *mut _); fail(&mut output); }) }) } #[cfg(unix)] -fn with_argv(prog: &CString, args: &[CString], cb: proc(**libc::c_char) -> T) -> T { - let mut ptrs: Vec<*libc::c_char> = Vec::with_capacity(args.len()+1); +fn with_argv(prog: &CString, args: &[CString], + cb: proc(*const *const libc::c_char) -> T) -> T { + let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1); // Convert the CStrings into an array of pointers. Note: the // lifetime of the various CStrings involved is guaranteed to be // larger than the lifetime of our invocation of cb, but this is // technically unsafe as the callback could leak these pointers // out of our scope. - ptrs.push(prog.with_ref(|buf| buf)); - ptrs.extend(args.iter().map(|tmp| tmp.with_ref(|buf| buf))); + ptrs.push(prog.as_ptr()); + ptrs.extend(args.iter().map(|tmp| tmp.as_ptr())); // Add a terminating null pointer (required by libc). ptrs.push(ptr::null()); @@ -723,7 +729,8 @@ fn with_argv(prog: &CString, args: &[CString], cb: proc(**libc::c_char) -> T) } #[cfg(unix)] -fn with_envp(env: Option<&[(CString, CString)]>, cb: proc(*c_void) -> T) -> T { +fn with_envp(env: Option<&[(CString, CString)]>, + cb: proc(*const c_void) -> T) -> T { // On posixy systems we can pass a char** for envp, which is a // null-terminated array of "k=v\0" strings. Since we must create // these strings locally, yet expose a raw pointer to them, we @@ -742,13 +749,13 @@ fn with_envp(env: Option<&[(CString, CString)]>, cb: proc(*c_void) -> T) -> T } // As with `with_argv`, this is unsafe, since cb could leak the pointers. - let mut ptrs: Vec<*libc::c_char> = + let mut ptrs: Vec<*const libc::c_char> = tmps.iter() - .map(|tmp| tmp.as_ptr() as *libc::c_char) + .map(|tmp| tmp.as_ptr() as *const libc::c_char) .collect(); ptrs.push(ptr::null()); - cb(ptrs.as_ptr() as *c_void) + cb(ptrs.as_ptr() as *const c_void) } _ => cb(ptr::null()) } @@ -767,7 +774,7 @@ fn with_envp(env: Option<&[(CString, CString)]>, cb: |*mut c_void| -> T) -> T let kv = format!("{}={}", pair.ref0().as_str().unwrap(), pair.ref1().as_str().unwrap()); - blk.push_all(kv.to_utf16().as_slice()); + blk.extend(kv.as_slice().utf16_units()); blk.push(0); } @@ -780,12 +787,14 @@ fn with_envp(env: Option<&[(CString, CString)]>, cb: |*mut c_void| -> T) -> T } #[cfg(windows)] -fn with_dirp(d: Option<&CString>, cb: |*u16| -> T) -> T { +fn with_dirp(d: Option<&CString>, cb: |*const u16| -> T) -> T { match d { Some(dir) => { let dir_str = dir.as_str() .expect("expected workingdirectory to be utf-8 encoded"); - let dir_str = dir_str.to_utf16().append_one(0); + let dir_str: Vec = dir_str.utf16_units().collect(); + let dir_str = dir_str.append_one(0); + cb(dir_str.as_ptr()) }, None => cb(ptr::null()) @@ -793,14 +802,14 @@ fn with_dirp(d: Option<&CString>, cb: |*u16| -> T) -> T { } #[cfg(windows)] -fn free_handle(handle: *()) { +fn free_handle(handle: *mut ()) { assert!(unsafe { libc::CloseHandle(mem::transmute(handle)) != 0 }) } #[cfg(unix)] -fn free_handle(_handle: *()) { +fn free_handle(_handle: *mut ()) { // unix has no process handle object, just a pid } @@ -1014,15 +1023,16 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult { let now = ::io::timer::now(); let ms = if now < deadline {deadline - now} else {0}; tv = util::ms_to_timeval(ms); - (&tv as *_, idx) + (&mut tv as *mut _, idx) } - None => (ptr::null(), -1), + None => (ptr::mut_null(), -1), }; // Wait for something to happen c::fd_set(&mut set, input); c::fd_set(&mut set, read_fd); - match unsafe { c::select(max, &set, ptr::null(), ptr::null(), p) } { + match unsafe { c::select(max, &mut set, ptr::mut_null(), + ptr::mut_null(), p) } { // interrupted, retry -1 if os::errno() == libc::EINTR as int => continue, @@ -1132,9 +1142,9 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult { // which will wake up the other end at some point, so we just allow this // signal to be coalesced with the pending signals on the pipe. extern fn sigchld_handler(_signum: libc::c_int) { - let mut msg = 1; + let msg = 1i; match unsafe { - libc::write(WRITE_FD, &mut msg as *mut _ as *libc::c_void, 1) + libc::write(WRITE_FD, &msg as *const _ as *const libc::c_void, 1) } { 1 => {} -1 if util::wouldblock() => {} // see above comments diff --git a/src/libnative/io/timer_unix.rs b/src/libnative/io/timer_unix.rs index 304ff9738356e..8d6563bafad63 100644 --- a/src/libnative/io/timer_unix.rs +++ b/src/libnative/io/timer_unix.rs @@ -88,7 +88,7 @@ pub enum Req { pub fn now() -> u64 { unsafe { let mut now: libc::timeval = mem::zeroed(); - assert_eq!(c::gettimeofday(&mut now, ptr::null()), 0); + assert_eq!(c::gettimeofday(&mut now, ptr::mut_null()), 0); return (now.tv_sec as u64) * 1000 + (now.tv_usec as u64) / 1000; } } @@ -146,7 +146,7 @@ fn helper(input: libc::c_int, messages: Receiver, _: int) { 'outer: loop { let timeout = if active.len() == 0 { // Empty array? no timeout (wait forever for the next request) - ptr::null() + ptr::mut_null() } else { let now = now(); // If this request has already expired, then signal it and go @@ -162,12 +162,13 @@ fn helper(input: libc::c_int, messages: Receiver, _: int) { let tm = active.get(0).target - now; timeout.tv_sec = (tm / 1000) as libc::time_t; timeout.tv_usec = ((tm % 1000) * 1000) as libc::suseconds_t; - &timeout as *libc::timeval + &mut timeout as *mut libc::timeval }; c::fd_set(&mut set, input); match unsafe { - c::select(input + 1, &set, ptr::null(), ptr::null(), timeout) + c::select(input + 1, &mut set, ptr::mut_null(), + ptr::mut_null(), timeout) } { // timed out 0 => signal(&mut active, &mut dead), diff --git a/src/libnative/io/timer_win32.rs b/src/libnative/io/timer_win32.rs index 9be09c6de0762..1e5594126b10a 100644 --- a/src/libnative/io/timer_win32.rs +++ b/src/libnative/io/timer_win32.rs @@ -141,7 +141,7 @@ impl rtio::RtioTimer for Timer { // 100ns intervals, so we multiply by 10^4. let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER; assert_eq!(unsafe { - imp::SetWaitableTimer(self.obj, &due, 0, ptr::null(), + imp::SetWaitableTimer(self.obj, &due, 0, ptr::mut_null(), ptr::mut_null(), 0) }, 1); @@ -154,7 +154,7 @@ impl rtio::RtioTimer for Timer { // see above for the calculation let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER; assert_eq!(unsafe { - imp::SetWaitableTimer(self.obj, &due, 0, ptr::null(), + imp::SetWaitableTimer(self.obj, &due, 0, ptr::mut_null(), ptr::mut_null(), 0) }, 1); @@ -169,7 +169,7 @@ impl rtio::RtioTimer for Timer { let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER; assert_eq!(unsafe { imp::SetWaitableTimer(self.obj, &due, msecs as libc::LONG, - ptr::null(), ptr::mut_null(), 0) + ptr::mut_null(), ptr::mut_null(), 0) }, 1); unsafe { HELPER.send(NewTimer(self.obj, cb, false)) } @@ -188,20 +188,20 @@ mod imp { use libc::{LPSECURITY_ATTRIBUTES, BOOL, LPCSTR, HANDLE, LARGE_INTEGER, LONG, LPVOID, DWORD, c_void}; - pub type PTIMERAPCROUTINE = *c_void; + pub type PTIMERAPCROUTINE = *mut c_void; extern "system" { pub fn CreateWaitableTimerA(lpTimerAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, lpTimerName: LPCSTR) -> HANDLE; pub fn SetWaitableTimer(hTimer: HANDLE, - pDueTime: *LARGE_INTEGER, + pDueTime: *const LARGE_INTEGER, lPeriod: LONG, pfnCompletionRoutine: PTIMERAPCROUTINE, lpArgToCompletionRoutine: LPVOID, fResume: BOOL) -> BOOL; pub fn WaitForMultipleObjects(nCount: DWORD, - lpHandles: *HANDLE, + lpHandles: *const HANDLE, bWaitAll: BOOL, dwMilliseconds: DWORD) -> DWORD; pub fn WaitForSingleObject(hHandle: HANDLE, diff --git a/src/libnative/io/util.rs b/src/libnative/io/util.rs index a3c5349fa4582..31ba2223082d5 100644 --- a/src/libnative/io/util.rs +++ b/src/libnative/io/util.rs @@ -90,7 +90,7 @@ pub fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> { // See http://developerweb.net/viewtopic.php?id=3196 for where this is // derived from. pub fn connect_timeout(fd: net::sock_t, - addrp: *libc::sockaddr, + addrp: *const libc::sockaddr, len: libc::socklen_t, timeout_ms: u64) -> IoResult<()> { use std::os; @@ -145,16 +145,16 @@ pub fn connect_timeout(fd: net::sock_t, // Recalculate the timeout each iteration (it is generally // undefined what the value of the 'tv' is after select // returns EINTR). - let tv = ms_to_timeval(timeout - (::io::timer::now() - start)); - c::select(fd + 1, ptr::null(), set as *mut _ as *_, - ptr::null(), &tv) + let mut tv = ms_to_timeval(timeout - (::io::timer::now() - start)); + c::select(fd + 1, ptr::mut_null(), set as *mut _, + ptr::mut_null(), &mut tv) }) } #[cfg(windows)] fn await(_fd: net::sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int { - let tv = ms_to_timeval(timeout); - unsafe { c::select(1, ptr::null(), &*set, ptr::null(), &tv) } + let mut tv = ms_to_timeval(timeout); + unsafe { c::select(1, ptr::mut_null(), set, ptr::mut_null(), &mut tv) } } } @@ -163,25 +163,25 @@ pub fn await(fd: net::sock_t, deadline: Option, let mut set: c::fd_set = unsafe { mem::zeroed() }; c::fd_set(&mut set, fd); let (read, write) = match status { - Readable => (&set as *_, ptr::null()), - Writable => (ptr::null(), &set as *_), + Readable => (&mut set as *mut _, ptr::mut_null()), + Writable => (ptr::mut_null(), &mut set as *mut _), }; let mut tv: libc::timeval = unsafe { mem::zeroed() }; match retry(|| { let now = ::io::timer::now(); let tvp = match deadline { - None => ptr::null(), + None => ptr::mut_null(), Some(deadline) => { // If we're past the deadline, then pass a 0 timeout to // select() so we can poll the status let ms = if deadline < now {0} else {deadline - now}; tv = ms_to_timeval(ms); - &tv as *_ + &mut tv as *mut _ } }; let n = if cfg!(windows) {1} else {fd as libc::c_int + 1}; - let r = unsafe { c::select(n, read, write, ptr::null(), tvp) }; + let r = unsafe { c::select(n, read, write, ptr::mut_null(), tvp) }; r }) { -1 => Err(last_error()), diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index ade7a479d1e15..2e43ddba6449c 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -20,7 +20,9 @@ //! extern crate native; //! //! #[start] -//! fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) } +//! fn start(argc: int, argv: *const *const u8) -> int { +//! native::start(argc, argv, main) +//! } //! //! fn main() { //! // this code is running on the main OS thread @@ -55,7 +57,6 @@ #![deny(unused_result, unused_must_use)] #![allow(non_camel_case_types, deprecated)] -#![allow(unknown_features)] // NOTE: remove after a stage0 snap #![feature(default_type_params, lang_items)] // NB this crate explicitly does *not* allow glob imports, please seriously @@ -84,7 +85,7 @@ static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20); #[lang = "start"] #[cfg(not(test))] -pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { +pub fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { use std::mem; start(argc, argv, proc() { let main: extern "Rust" fn() = unsafe { mem::transmute(main) }; @@ -101,9 +102,9 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { /// /// This function will only return once *all* native threads in the system have /// exited. -pub fn start(argc: int, argv: **u8, main: proc()) -> int { +pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int { let something_around_the_top_of_the_stack = 1; - let addr = &something_around_the_top_of_the_stack as *int; + let addr = &something_around_the_top_of_the_stack as *const int; let my_stack_top = addr as uint; // FIXME #11359 we just assume that this thread has a stack of a diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 0b863d9f69401..7ba588ac21c48 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -81,7 +81,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) { // which our stack started). Thread::spawn_stack(stack, proc() { let something_around_the_top_of_the_stack = 1; - let addr = &something_around_the_top_of_the_stack as *int; + let addr = &something_around_the_top_of_the_stack as *const int; let my_stack = addr as uint; unsafe { stack::record_stack_bounds(my_stack - stack + 1024, my_stack); @@ -198,7 +198,7 @@ impl rt::Runtime for Ops { cur_task.put_runtime(self); unsafe { - let cur_task_dupe = &*cur_task as *Task; + let cur_task_dupe = &mut *cur_task as *mut Task; let task = BlockedTask::block(cur_task); if times == 1 { diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 06e4792cdcccf..cc3753def59f4 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -91,8 +91,8 @@ impl Eq for BigUint {} impl PartialOrd for BigUint { #[inline] - fn lt(&self, other: &BigUint) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &BigUint) -> Option { + Some(self.cmp(other)) } } @@ -215,7 +215,7 @@ impl Sub for BigUint { let zeros = ZERO_VEC.iter().cycle(); let (a, b) = (self.data.iter().chain(zeros.clone()), other.data.iter().chain(zeros)); - let mut borrow = 0; + let mut borrow = 0i; let diff: Vec = a.take(new_len).zip(b).map(|(ai, bi)| { let (hi, lo) = BigDigit::from_doublebigdigit( BigDigit::base @@ -816,8 +816,8 @@ impl Eq for BigInt {} impl PartialOrd for BigInt { #[inline] - fn lt(&self, other: &BigInt) -> bool { - self.cmp(other) == Less + fn partial_cmp(&self, other: &BigInt) -> Option { + Some(self.cmp(other)) } } diff --git a/src/libnum/rational.rs b/src/libnum/rational.rs index 971b6b1b51b2d..9a455edf2c086 100644 --- a/src/libnum/rational.rs +++ b/src/libnum/rational.rs @@ -193,7 +193,8 @@ macro_rules! cmp_impl { }; } cmp_impl!(impl PartialEq, eq, ne) -cmp_impl!(impl PartialOrd, lt, gt, le, ge) +cmp_impl!(impl PartialOrd, lt -> bool, gt -> bool, le -> bool, ge -> bool, + partial_cmp -> Option) cmp_impl!(impl Eq, ) cmp_impl!(impl Ord, cmp -> cmp::Ordering) diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 6caa936636a71..134e7af507010 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -389,10 +389,10 @@ impl Isaac64Rng { } }} ); - rngstepp!(0, 21); - rngstepn!(1, 5); - rngstepp!(2, 12); - rngstepn!(3, 33); + rngstepp!(0u, 21); + rngstepn!(1u, 5); + rngstepp!(2u, 12); + rngstepn!(3u, 33); } } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 6195756e4c082..593b9785d475a 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -111,7 +111,7 @@ pub trait Rng { // (3) adds more `unsafe` that needs to be checked, (4) // probably doesn't give much performance gain if // optimisations are on. - let mut count = 0; + let mut count = 0i; let mut num = 0; for byte in dest.mut_iter() { if count == 0 { diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs index 3dd054cee9d1e..77433877ec668 100644 --- a/src/librand/rand_impls.rs +++ b/src/librand/rand_impls.rs @@ -203,6 +203,8 @@ tuple_impl!{A, B, C, D, E, F, G} tuple_impl!{A, B, C, D, E, F, G, H} tuple_impl!{A, B, C, D, E, F, G, H, I} tuple_impl!{A, B, C, D, E, F, G, H, I, J} +tuple_impl!{A, B, C, D, E, F, G, H, I, J, K} +tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L} impl Rand for Option { #[inline] diff --git a/src/libregex/parse/mod.rs b/src/libregex/parse/mod.rs index 2fea75746be73..9cde40c196088 100644 --- a/src/libregex/parse/mod.rs +++ b/src/libregex/parse/mod.rs @@ -770,7 +770,7 @@ impl<'a> Parser<'a> { } let start = self.chari; let mut flags = self.flags; - let mut sign = 1; + let mut sign = 1i; let mut saw_flag = false; loop { try!(self.noteof("expected non-empty set of flags or closing ')'")) diff --git a/src/librlibc/lib.rs b/src/librlibc/lib.rs index 144479e882d8a..8c7bf3496eef1 100644 --- a/src/librlibc/lib.rs +++ b/src/librlibc/lib.rs @@ -27,7 +27,6 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/0.11.0/")] #![feature(intrinsics)] -#![allow(unknown_features)] // NOTE: remove after stage0 snapshot #![no_std] #![experimental] @@ -43,31 +42,36 @@ // implementations below. If pointer arithmetic is done through integers the // optimizations start to break down. extern "rust-intrinsic" { - fn offset(dst: *T, offset: int) -> *T; + fn offset(dst: *const T, offset: int) -> *const T; } #[no_mangle] -pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *u8, n: uint) -> *mut u8 { +pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, + n: uint) -> *mut u8 { let mut i = 0; while i < n { - *(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int); + *(offset(dest as *const u8, i as int) as *mut u8) = + *offset(src, i as int); i += 1; } return dest; } #[no_mangle] -pub unsafe extern "C" fn memmove(dest: *mut u8, src: *u8, n: uint) -> *mut u8 { - if src < dest as *u8 { // copy from end +pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, + n: uint) -> *mut u8 { + if src < dest as *const u8 { // copy from end let mut i = n; while i != 0 { i -= 1; - *(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int); + *(offset(dest as *const u8, i as int) as *mut u8) = + *offset(src, i as int); } } else { // copy from beginning let mut i = 0; while i < n { - *(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int); + *(offset(dest as *const u8, i as int) as *mut u8) = + *offset(src, i as int); i += 1; } } @@ -78,14 +82,14 @@ pub unsafe extern "C" fn memmove(dest: *mut u8, src: *u8, n: uint) -> *mut u8 { pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 { let mut i = 0; while i < n { - *(offset(s as *u8, i as int) as *mut u8) = c as u8; + *(offset(s as *const u8, i as int) as *mut u8) = c as u8; i += 1; } return s; } #[no_mangle] -pub unsafe extern "C" fn memcmp(s1: *u8, s2: *u8, n: uint) -> i32 { +pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 { let mut i = 0; while i < n { let a = *offset(s1, i as int); diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 42e699fb6919b..17f29639601dd 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -412,7 +412,7 @@ pub mod write { { let add = |arg: &str| { let s = arg.to_c_str(); - llvm_args.push(s.with_ref(|p| p)); + llvm_args.push(s.as_ptr()); llvm_c_strs.push(s); }; add("rustc"); // fake program name @@ -657,8 +657,8 @@ pub fn sanitize(s: &str) -> String { // Underscore-qualify anything that didn't start as an ident. if result.len() > 0u && - result.as_slice()[0] != '_' as u8 && - ! char::is_XID_start(result.as_slice()[0] as char) { + result.as_bytes()[0] != '_' as u8 && + ! char::is_XID_start(result.as_bytes()[0] as char) { return format!("_{}", result.as_slice()); } @@ -737,9 +737,9 @@ pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems, let extra2 = id % EXTRA_CHARS.len(); let id = id / EXTRA_CHARS.len(); let extra3 = id % EXTRA_CHARS.len(); - hash.push_char(EXTRA_CHARS[extra1] as char); - hash.push_char(EXTRA_CHARS[extra2] as char); - hash.push_char(EXTRA_CHARS[extra3] as char); + hash.push_char(EXTRA_CHARS.as_bytes()[extra1] as char); + hash.push_char(EXTRA_CHARS.as_bytes()[extra2] as char); + hash.push_char(EXTRA_CHARS.as_bytes()[extra3] as char); exported_name(path, hash.as_slice(), diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 7449622366fc2..b9ae9530f8e1c 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -82,7 +82,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, (), |()| unsafe { if !llvm::LLVMRustLinkInExternalBitcode(llmod, - ptr as *libc::c_char, + ptr as *const libc::c_char, bc.len() as libc::size_t) { link::llvm_err(sess, format!("failed to load bc of `{}`", @@ -94,10 +94,11 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // Internalize everything but the reachable symbols of the current module let cstrs: Vec<::std::c_str::CString> = reachable.iter().map(|s| s.as_slice().to_c_str()).collect(); - let arr: Vec<*i8> = cstrs.iter().map(|c| c.with_ref(|p| p)).collect(); + let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect(); let ptr = arr.as_ptr(); unsafe { - llvm::LLVMRustRunRestrictionPass(llmod, ptr as **libc::c_char, + llvm::LLVMRustRunRestrictionPass(llmod, + ptr as *const *const libc::c_char, arr.len() as libc::size_t); } diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index d6f1bfeb9ef1c..d07e74493be96 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -255,45 +255,45 @@ pub enum CodeGenModel { // Opaque pointer types pub enum Module_opaque {} -pub type ModuleRef = *Module_opaque; +pub type ModuleRef = *mut Module_opaque; pub enum Context_opaque {} -pub type ContextRef = *Context_opaque; +pub type ContextRef = *mut Context_opaque; pub enum Type_opaque {} -pub type TypeRef = *Type_opaque; +pub type TypeRef = *mut Type_opaque; pub enum Value_opaque {} -pub type ValueRef = *Value_opaque; +pub type ValueRef = *mut Value_opaque; pub enum BasicBlock_opaque {} -pub type BasicBlockRef = *BasicBlock_opaque; +pub type BasicBlockRef = *mut BasicBlock_opaque; pub enum Builder_opaque {} -pub type BuilderRef = *Builder_opaque; +pub type BuilderRef = *mut Builder_opaque; pub enum ExecutionEngine_opaque {} -pub type ExecutionEngineRef = *ExecutionEngine_opaque; +pub type ExecutionEngineRef = *mut ExecutionEngine_opaque; pub enum MemoryBuffer_opaque {} -pub type MemoryBufferRef = *MemoryBuffer_opaque; +pub type MemoryBufferRef = *mut MemoryBuffer_opaque; pub enum PassManager_opaque {} -pub type PassManagerRef = *PassManager_opaque; +pub type PassManagerRef = *mut PassManager_opaque; pub enum PassManagerBuilder_opaque {} -pub type PassManagerBuilderRef = *PassManagerBuilder_opaque; +pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque; pub enum Use_opaque {} -pub type UseRef = *Use_opaque; +pub type UseRef = *mut Use_opaque; pub enum TargetData_opaque {} -pub type TargetDataRef = *TargetData_opaque; +pub type TargetDataRef = *mut TargetData_opaque; pub enum ObjectFile_opaque {} -pub type ObjectFileRef = *ObjectFile_opaque; +pub type ObjectFileRef = *mut ObjectFile_opaque; pub enum SectionIterator_opaque {} -pub type SectionIteratorRef = *SectionIterator_opaque; +pub type SectionIteratorRef = *mut SectionIterator_opaque; pub enum Pass_opaque {} -pub type PassRef = *Pass_opaque; +pub type PassRef = *mut Pass_opaque; pub enum TargetMachine_opaque {} -pub type TargetMachineRef = *TargetMachine_opaque; +pub type TargetMachineRef = *mut TargetMachine_opaque; pub enum Archive_opaque {} -pub type ArchiveRef = *Archive_opaque; +pub type ArchiveRef = *mut Archive_opaque; pub mod debuginfo { use super::{ValueRef}; pub enum DIBuilder_opaque {} - pub type DIBuilderRef = *DIBuilder_opaque; + pub type DIBuilderRef = *mut DIBuilder_opaque; pub type DIDescriptor = ValueRef; pub type DIScope = DIDescriptor; @@ -354,30 +354,30 @@ pub mod llvm { pub fn LLVMContextCreate() -> ContextRef; pub fn LLVMContextDispose(C: ContextRef); pub fn LLVMGetMDKindIDInContext(C: ContextRef, - Name: *c_char, + Name: *const c_char, SLen: c_uint) -> c_uint; /* Create and destroy modules. */ - pub fn LLVMModuleCreateWithNameInContext(ModuleID: *c_char, + pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef; pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; pub fn LLVMDisposeModule(M: ModuleRef); /** Data layout. See Module::getDataLayout. */ - pub fn LLVMGetDataLayout(M: ModuleRef) -> *c_char; - pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *c_char); + pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char; + pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char); /** Target triple. See Module::getTargetTriple. */ - pub fn LLVMGetTarget(M: ModuleRef) -> *c_char; - pub fn LLVMSetTarget(M: ModuleRef, Triple: *c_char); + pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char; + pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char); /** See Module::dump. */ pub fn LLVMDumpModule(M: ModuleRef); /** See Module::setModuleInlineAsm. */ - pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *c_char); + pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char); /** See llvm::LLVMTypeKind::getTypeID. */ pub fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind; @@ -405,18 +405,18 @@ pub mod llvm { /* Operations on function types */ pub fn LLVMFunctionType(ReturnType: TypeRef, - ParamTypes: *TypeRef, + ParamTypes: *const TypeRef, ParamCount: c_uint, IsVarArg: Bool) -> TypeRef; pub fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool; pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef; pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint; - pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *TypeRef); + pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *const TypeRef); /* Operations on struct types */ pub fn LLVMStructTypeInContext(C: ContextRef, - ElementTypes: *TypeRef, + ElementTypes: *const TypeRef, ElementCount: c_uint, Packed: Bool) -> TypeRef; @@ -436,7 +436,7 @@ pub mod llvm { pub fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint; pub fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint; pub fn LLVMGetPointerToGlobal(EE: ExecutionEngineRef, V: ValueRef) - -> *(); + -> *const (); pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint; /* Operations on other types */ @@ -446,8 +446,8 @@ pub mod llvm { /* Operations on all values */ pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef; - pub fn LLVMGetValueName(Val: ValueRef) -> *c_char; - pub fn LLVMSetValueName(Val: ValueRef, Name: *c_char); + pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char; + pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char); pub fn LLVMDumpValue(Val: ValueRef); pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef); pub fn LLVMHasMetadata(Val: ValueRef) -> c_int; @@ -482,32 +482,32 @@ pub mod llvm { /* Operations on metadata */ pub fn LLVMMDStringInContext(C: ContextRef, - Str: *c_char, + Str: *const c_char, SLen: c_uint) -> ValueRef; pub fn LLVMMDNodeInContext(C: ContextRef, - Vals: *ValueRef, + Vals: *const ValueRef, Count: c_uint) -> ValueRef; pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, - Str: *c_char, + Str: *const c_char, Val: ValueRef); /* Operations on scalar constants */ pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; - pub fn LLVMConstIntOfString(IntTy: TypeRef, Text: *c_char, Radix: u8) + pub fn LLVMConstIntOfString(IntTy: TypeRef, Text: *const c_char, Radix: u8) -> ValueRef; pub fn LLVMConstIntOfStringAndSize(IntTy: TypeRef, - Text: *c_char, + Text: *const c_char, SLen: c_uint, Radix: u8) -> ValueRef; pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef; - pub fn LLVMConstRealOfString(RealTy: TypeRef, Text: *c_char) + pub fn LLVMConstRealOfString(RealTy: TypeRef, Text: *const c_char) -> ValueRef; pub fn LLVMConstRealOfStringAndSize(RealTy: TypeRef, - Text: *c_char, + Text: *const c_char, SLen: c_uint) -> ValueRef; pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong; @@ -516,21 +516,21 @@ pub mod llvm { /* Operations on composite constants */ pub fn LLVMConstStringInContext(C: ContextRef, - Str: *c_char, + Str: *const c_char, Length: c_uint, DontNullTerminate: Bool) -> ValueRef; pub fn LLVMConstStructInContext(C: ContextRef, - ConstantVals: *ValueRef, + ConstantVals: *const ValueRef, Count: c_uint, Packed: Bool) -> ValueRef; pub fn LLVMConstArray(ElementTy: TypeRef, - ConstantVals: *ValueRef, + ConstantVals: *const ValueRef, Length: c_uint) -> ValueRef; - pub fn LLVMConstVector(ScalarConstantVals: *ValueRef, Size: c_uint) + pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint) -> ValueRef; /* Constant expressions */ @@ -593,11 +593,11 @@ pub mod llvm { pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; pub fn LLVMConstGEP(ConstantVal: ValueRef, - ConstantIndices: *ValueRef, + ConstantIndices: *const ValueRef, NumIndices: c_uint) -> ValueRef; pub fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, - ConstantIndices: *ValueRef, + ConstantIndices: *const ValueRef, NumIndices: c_uint) -> ValueRef; pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) @@ -654,17 +654,17 @@ pub mod llvm { MaskConstant: ValueRef) -> ValueRef; pub fn LLVMConstExtractValue(AggConstant: ValueRef, - IdxList: *c_uint, + IdxList: *const c_uint, NumIdx: c_uint) -> ValueRef; pub fn LLVMConstInsertValue(AggConstant: ValueRef, ElementValueConstant: ValueRef, - IdxList: *c_uint, + IdxList: *const c_uint, NumIdx: c_uint) -> ValueRef; pub fn LLVMConstInlineAsm(Ty: TypeRef, - AsmString: *c_char, - Constraints: *c_char, + AsmString: *const c_char, + Constraints: *const c_char, HasSideEffects: Bool, IsAlignStack: Bool) -> ValueRef; @@ -677,8 +677,8 @@ pub mod llvm { pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool; pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint; pub fn LLVMSetLinkage(Global: ValueRef, Link: c_uint); - pub fn LLVMGetSection(Global: ValueRef) -> *c_char; - pub fn LLVMSetSection(Global: ValueRef, Section: *c_char); + pub fn LLVMGetSection(Global: ValueRef) -> *const c_char; + pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char); pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint; pub fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint); pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint; @@ -686,14 +686,14 @@ pub mod llvm { /* Operations on global variables */ - pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *c_char) + pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; pub fn LLVMAddGlobalInAddressSpace(M: ModuleRef, Ty: TypeRef, - Name: *c_char, + Name: *const c_char, AddressSpace: c_uint) -> ValueRef; - pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *c_char) -> ValueRef; + pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef; pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef; pub fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef; pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef; @@ -711,37 +711,37 @@ pub mod llvm { pub fn LLVMAddAlias(M: ModuleRef, Ty: TypeRef, Aliasee: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; /* Operations on functions */ pub fn LLVMAddFunction(M: ModuleRef, - Name: *c_char, + Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; - pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *c_char) -> ValueRef; + pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef; pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef; pub fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef; pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef; pub fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef; pub fn LLVMDeleteFunction(Fn: ValueRef); pub fn LLVMGetOrInsertFunction(M: ModuleRef, - Name: *c_char, + Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; pub fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint; pub fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint; pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint); - pub fn LLVMGetGC(Fn: ValueRef) -> *c_char; - pub fn LLVMSetGC(Fn: ValueRef, Name: *c_char); + pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char; + pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char); pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t); - pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *c_char); - pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *c_char); + pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char); + pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char); pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong; /* Operations on parameters */ pub fn LLVMCountParams(Fn: ValueRef) -> c_uint; - pub fn LLVMGetParams(Fn: ValueRef, Params: *ValueRef); + pub fn LLVMGetParams(Fn: ValueRef, Params: *const ValueRef); pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef; pub fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef; pub fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef; @@ -759,7 +759,7 @@ pub mod llvm { pub fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef; pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef; pub fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint; - pub fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *ValueRef); + pub fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *const ValueRef); pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef; pub fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef; pub fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef; @@ -768,11 +768,11 @@ pub mod llvm { pub fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, - Name: *c_char) + Name: *const c_char) -> BasicBlockRef; pub fn LLVMInsertBasicBlockInContext(C: ContextRef, BB: BasicBlockRef, - Name: *c_char) + Name: *const c_char) -> BasicBlockRef; pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef); @@ -816,8 +816,8 @@ pub mod llvm { /* Operations on phi nodes */ pub fn LLVMAddIncoming(PhiNode: ValueRef, - IncomingValues: *ValueRef, - IncomingBlocks: *BasicBlockRef, + IncomingValues: *const ValueRef, + IncomingBlocks: *const BasicBlockRef, Count: c_uint); pub fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint; pub fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint) @@ -839,7 +839,7 @@ pub mod llvm { pub fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef); pub fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef, Instr: ValueRef, - Name: *c_char); + Name: *const c_char); pub fn LLVMDisposeBuilder(Builder: BuilderRef); pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef); @@ -852,7 +852,7 @@ pub mod llvm { pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef; pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef; pub fn LLVMBuildAggregateRet(B: BuilderRef, - RetVals: *ValueRef, + RetVals: *const ValueRef, N: c_uint) -> ValueRef; pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef; @@ -872,17 +872,17 @@ pub mod llvm { -> ValueRef; pub fn LLVMBuildInvoke(B: BuilderRef, Fn: ValueRef, - Args: *ValueRef, + Args: *const ValueRef, NumArgs: c_uint, Then: BasicBlockRef, Catch: BasicBlockRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildLandingPad(B: BuilderRef, Ty: TypeRef, PersFn: ValueRef, NumClauses: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef; pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef; @@ -905,164 +905,164 @@ pub mod llvm { pub fn LLVMBuildAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildNSWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildNUWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildNSWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildNUWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildNSWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildNUWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildUDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildExactSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildURem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildShl(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildLShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildAShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildAnd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildOr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildXor(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildBinOp(B: BuilderRef, Op: Opcode, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *c_char) + pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) + pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) + pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *c_char) + pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *c_char) + pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; /* Memory */ - pub fn LLVMBuildMalloc(B: BuilderRef, Ty: TypeRef, Name: *c_char) + pub fn LLVMBuildMalloc(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildArrayMalloc(B: BuilderRef, Ty: TypeRef, Val: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; - pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *c_char) + pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildArrayAlloca(B: BuilderRef, Ty: TypeRef, Val: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef; pub fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) @@ -1070,125 +1070,125 @@ pub mod llvm { pub fn LLVMBuildGEP(B: BuilderRef, Pointer: ValueRef, - Indices: *ValueRef, + Indices: *const ValueRef, NumIndices: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildInBoundsGEP(B: BuilderRef, Pointer: ValueRef, - Indices: *ValueRef, + Indices: *const ValueRef, NumIndices: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildStructGEP(B: BuilderRef, Pointer: ValueRef, Idx: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildGlobalString(B: BuilderRef, - Str: *c_char, - Name: *c_char) + Str: *const c_char, + Name: *const c_char) -> ValueRef; pub fn LLVMBuildGlobalStringPtr(B: BuilderRef, - Str: *c_char, - Name: *c_char) + Str: *const c_char, + Name: *const c_char) -> ValueRef; /* Casts */ pub fn LLVMBuildTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildZExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFPToUI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFPToSI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildUIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFPTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFPExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildPtrToInt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildIntToPtr(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildZExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildTruncOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildCast(B: BuilderRef, Op: Opcode, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) -> ValueRef; + Name: *const c_char) -> ValueRef; pub fn LLVMBuildPointerCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildIntCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFPCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; /* Comparisons */ @@ -1196,78 +1196,78 @@ pub mod llvm { Op: c_uint, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildFCmp(B: BuilderRef, Op: c_uint, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; /* Miscellaneous instructions */ - pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *c_char) + pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildCall(B: BuilderRef, Fn: ValueRef, - Args: *ValueRef, + Args: *const ValueRef, NumArgs: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildSelect(B: BuilderRef, If: ValueRef, Then: ValueRef, Else: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildVAArg(B: BuilderRef, list: ValueRef, Ty: TypeRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildExtractElement(B: BuilderRef, VecVal: ValueRef, Index: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildInsertElement(B: BuilderRef, VecVal: ValueRef, EltVal: ValueRef, Index: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildShuffleVector(B: BuilderRef, V1: ValueRef, V2: ValueRef, Mask: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildExtractValue(B: BuilderRef, AggVal: ValueRef, Index: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; pub fn LLVMBuildInsertValue(B: BuilderRef, AggVal: ValueRef, EltVal: ValueRef, Index: c_uint, - Name: *c_char) + Name: *const c_char) -> ValueRef; - pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *c_char) + pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *c_char) + pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, - Name: *c_char) + Name: *const c_char) -> ValueRef; /* Atomic Operations */ pub fn LLVMBuildAtomicLoad(B: BuilderRef, PointerVal: ValueRef, - Name: *c_char, + Name: *const c_char, Order: AtomicOrdering, Alignment: c_uint) -> ValueRef; @@ -1302,10 +1302,10 @@ pub mod llvm { pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef; /** Writes a module to the specified path. Returns 0 on success. */ - pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *c_char) -> c_int; + pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int; /** Creates target data from a target layout string. */ - pub fn LLVMCreateTargetData(StringRep: *c_char) -> TargetDataRef; + pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef; /// Adds the target data to the given pass manager. The pass manager /// references the target data only weakly. pub fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef); @@ -1464,21 +1464,21 @@ pub mod llvm { /** Returns the current section size. */ pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong; /** Returns the current section contents as a string buffer. */ - pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *c_char; + pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char; /** Reads the given file and returns it as a memory buffer. Use LLVMDisposeMemoryBuffer() to get rid of it. */ - pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *c_char) + pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char) -> MemoryBufferRef; /** Borrows the contents of the memory buffer (doesn't copy it) */ - pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *c_char, + pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char, InputDataLength: size_t, - BufferName: *c_char, + BufferName: *const c_char, RequiresNull: Bool) -> MemoryBufferRef; - pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *c_char, + pub fn LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: *const c_char, InputDataLength: size_t, - BufferName: *c_char) + BufferName: *const c_char) -> MemoryBufferRef; pub fn LLVMIsMultithreaded() -> Bool; @@ -1486,20 +1486,20 @@ pub mod llvm { /** Returns a string describing the last error caused by an LLVMRust* call. */ - pub fn LLVMRustGetLastError() -> *c_char; + pub fn LLVMRustGetLastError() -> *const c_char; /// Print the pass timings since static dtors aren't picking them up. pub fn LLVMRustPrintPassTimings(); - pub fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef; + pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef; pub fn LLVMStructSetBody(StructTy: TypeRef, - ElementTypes: *TypeRef, + ElementTypes: *const TypeRef, ElementCount: c_uint, Packed: Bool); pub fn LLVMConstNamedStruct(S: TypeRef, - ConstantVals: *ValueRef, + ConstantVals: *const ValueRef, Count: c_uint) -> ValueRef; @@ -1508,8 +1508,8 @@ pub mod llvm { /** Prepares inline assembly. */ pub fn LLVMInlineAsm(Ty: TypeRef, - AsmString: *c_char, - Constraints: *c_char, + AsmString: *const c_char, + Constraints: *const c_char, SideEffects: Bool, AlignStack: Bool, Dialect: c_uint) @@ -1518,7 +1518,7 @@ pub mod llvm { pub static LLVMRustDebugMetadataVersion: u32; pub fn LLVMRustAddModuleFlag(M: ModuleRef, - name: *c_char, + name: *const c_char, value: u32); pub fn LLVMDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; @@ -1529,17 +1529,17 @@ pub mod llvm { pub fn LLVMDIBuilderCreateCompileUnit(Builder: DIBuilderRef, Lang: c_uint, - File: *c_char, - Dir: *c_char, - Producer: *c_char, + File: *const c_char, + Dir: *const c_char, + Producer: *const c_char, isOptimized: bool, - Flags: *c_char, + Flags: *const c_char, RuntimeVer: c_uint, - SplitName: *c_char); + SplitName: *const c_char); pub fn LLVMDIBuilderCreateFile(Builder: DIBuilderRef, - Filename: *c_char, - Directory: *c_char) + Filename: *const c_char, + Directory: *const c_char) -> DIFile; pub fn LLVMDIBuilderCreateSubroutineType(Builder: DIBuilderRef, @@ -1549,8 +1549,8 @@ pub mod llvm { pub fn LLVMDIBuilderCreateFunction(Builder: DIBuilderRef, Scope: DIDescriptor, - Name: *c_char, - LinkageName: *c_char, + Name: *const c_char, + LinkageName: *const c_char, File: DIFile, LineNo: c_uint, Ty: DIType, @@ -1565,7 +1565,7 @@ pub mod llvm { -> DISubprogram; pub fn LLVMDIBuilderCreateBasicType(Builder: DIBuilderRef, - Name: *c_char, + Name: *const c_char, SizeInBits: c_ulonglong, AlignInBits: c_ulonglong, Encoding: c_uint) @@ -1575,12 +1575,12 @@ pub mod llvm { PointeeTy: DIType, SizeInBits: c_ulonglong, AlignInBits: c_ulonglong, - Name: *c_char) + Name: *const c_char) -> DIDerivedType; pub fn LLVMDIBuilderCreateStructType(Builder: DIBuilderRef, Scope: DIDescriptor, - Name: *c_char, + Name: *const c_char, File: DIFile, LineNumber: c_uint, SizeInBits: c_ulonglong, @@ -1590,12 +1590,12 @@ pub mod llvm { Elements: DIArray, RunTimeLang: c_uint, VTableHolder: ValueRef, - UniqueId: *c_char) + UniqueId: *const c_char) -> DICompositeType; pub fn LLVMDIBuilderCreateMemberType(Builder: DIBuilderRef, Scope: DIDescriptor, - Name: *c_char, + Name: *const c_char, File: DIFile, LineNo: c_uint, SizeInBits: c_ulonglong, @@ -1615,8 +1615,8 @@ pub mod llvm { pub fn LLVMDIBuilderCreateStaticVariable(Builder: DIBuilderRef, Context: DIDescriptor, - Name: *c_char, - LinkageName: *c_char, + Name: *const c_char, + LinkageName: *const c_char, File: DIFile, LineNo: c_uint, Ty: DIType, @@ -1628,7 +1628,7 @@ pub mod llvm { pub fn LLVMDIBuilderCreateLocalVariable(Builder: DIBuilderRef, Tag: c_uint, Scope: DIDescriptor, - Name: *c_char, + Name: *const c_char, File: DIFile, LineNo: c_uint, Ty: DIType, @@ -1657,7 +1657,7 @@ pub mod llvm { -> DISubrange; pub fn LLVMDIBuilderGetOrCreateArray(Builder: DIBuilderRef, - Ptr: *DIDescriptor, + Ptr: *const DIDescriptor, Count: c_uint) -> DIArray; @@ -1674,13 +1674,13 @@ pub mod llvm { -> ValueRef; pub fn LLVMDIBuilderCreateEnumerator(Builder: DIBuilderRef, - Name: *c_char, + Name: *const c_char, Val: c_ulonglong) -> ValueRef; pub fn LLVMDIBuilderCreateEnumerationType(Builder: DIBuilderRef, Scope: ValueRef, - Name: *c_char, + Name: *const c_char, File: ValueRef, LineNumber: c_uint, SizeInBits: c_ulonglong, @@ -1691,7 +1691,7 @@ pub mod llvm { pub fn LLVMDIBuilderCreateUnionType(Builder: DIBuilderRef, Scope: ValueRef, - Name: *c_char, + Name: *const c_char, File: ValueRef, LineNumber: c_uint, SizeInBits: c_ulonglong, @@ -1699,14 +1699,14 @@ pub mod llvm { Flags: c_uint, Elements: ValueRef, RunTimeLang: c_uint, - UniqueId: *c_char) + UniqueId: *const c_char) -> ValueRef; pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool); pub fn LLVMDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef, Scope: ValueRef, - Name: *c_char, + Name: *const c_char, Ty: ValueRef, File: ValueRef, LineNo: c_uint, @@ -1720,25 +1720,25 @@ pub mod llvm { pub fn LLVMDIBuilderCreateComplexVariable(Builder: DIBuilderRef, Tag: c_uint, Scope: ValueRef, - Name: *c_char, + Name: *const c_char, File: ValueRef, LineNo: c_uint, Ty: ValueRef, - AddrOps: *ValueRef, + AddrOps: *const ValueRef, AddrOpsCount: c_uint, ArgNo: c_uint) -> ValueRef; pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef, Scope: ValueRef, - Name: *c_char, + Name: *const c_char, File: ValueRef, LineNo: c_uint) -> ValueRef; pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef); - pub fn LLVMTypeToString(Type: TypeRef) -> *c_char; - pub fn LLVMValueToString(value_ref: ValueRef) -> *c_char; + pub fn LLVMTypeToString(Type: TypeRef) -> *const c_char; + pub fn LLVMValueToString(value_ref: ValueRef) -> *const c_char; pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef; @@ -1760,10 +1760,10 @@ pub mod llvm { pub fn LLVMInitializeMipsAsmPrinter(); pub fn LLVMInitializeMipsAsmParser(); - pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *c_char) -> bool; - pub fn LLVMRustCreateTargetMachine(Triple: *c_char, - CPU: *c_char, - Features: *c_char, + pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *const c_char) -> bool; + pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, + CPU: *const c_char, + Features: *const c_char, Model: CodeGenModel, Reloc: RelocMode, Level: CodeGenOptLevel, @@ -1785,27 +1785,27 @@ pub mod llvm { pub fn LLVMRustWriteOutputFile(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef, - Output: *c_char, + Output: *const c_char, FileType: FileType) -> bool; pub fn LLVMRustPrintModule(PM: PassManagerRef, M: ModuleRef, - Output: *c_char); - pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: **c_char); + Output: *const c_char); + pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); - pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *c_char); + pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool); pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef, - bc: *c_char, + bc: *const c_char, len: size_t) -> bool; pub fn LLVMRustRunRestrictionPass(M: ModuleRef, - syms: **c_char, + syms: *const *const c_char, len: size_t); pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); - pub fn LLVMRustOpenArchive(path: *c_char) -> ArchiveRef; - pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *c_char, - out_len: *mut size_t) -> *c_char; + pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef; + pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *const c_char, + out_len: *mut size_t) -> *const c_char; pub fn LLVMRustDestroyArchive(AR: ArchiveRef); pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef); @@ -1813,7 +1813,7 @@ pub mod llvm { pub fn LLVMVersionMinor() -> c_int; pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, - data: *mut *c_char) -> c_int; + data: *mut *const c_char) -> c_int; } } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 5078ae80d75c1..30296cb318617 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -30,7 +30,7 @@ use middle::def::*; use middle::trans::adt; // for `adt::is_ffi_safe` use middle::typeck::astconv::ast_ty_to_ty; use middle::typeck::infer; -use middle::{typeck, ty, def, pat_util}; +use middle::{typeck, ty, def, pat_util, stability}; use util::ppaux::{ty_to_str}; use util::nodemap::NodeSet; use lint::{Context, LintPass, LintArray}; @@ -391,8 +391,8 @@ pub struct HeapMemory; impl HeapMemory { fn check_heap_type(&self, cx: &Context, span: Span, ty: ty::t) { - let mut n_box = 0; - let mut n_uniq = 0; + let mut n_box = 0i; + let mut n_uniq = 0i; ty::fold_ty(cx.tcx, ty, |t| { match ty::get(t).sty { ty::ty_box(_) => { @@ -975,14 +975,52 @@ declare_lint!(UNNECESSARY_PARENS, Warn, pub struct UnnecessaryParens; impl UnnecessaryParens { - fn check_unnecessary_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str) { + fn check_unnecessary_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str, + struct_lit_needs_parens: bool) { match value.node { - ast::ExprParen(_) => { - cx.span_lint(UNNECESSARY_PARENS, value.span, - format!("unnecessary parentheses around {}", msg).as_slice()) + ast::ExprParen(ref inner) => { + let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); + if !necessary { + cx.span_lint(UNNECESSARY_PARENS, value.span, + format!("unnecessary parentheses around {}", + msg).as_slice()) + } } _ => {} } + + /// Expressions that syntatically contain an "exterior" struct + /// literal i.e. not surrounded by any parens or other + /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo + /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X { + /// y: 1 }) == foo` does not. + fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { + match value.node { + ast::ExprStruct(..) => true, + + ast::ExprAssign(ref lhs, ref rhs) | + ast::ExprAssignOp(_, ref lhs, ref rhs) | + ast::ExprBinary(_, ref lhs, ref rhs) => { + // X { y: 1 } + X { y: 2 } + contains_exterior_struct_lit(&**lhs) || + contains_exterior_struct_lit(&**rhs) + } + ast::ExprUnary(_, ref x) | + ast::ExprCast(ref x, _) | + ast::ExprField(ref x, _, _) | + ast::ExprIndex(ref x, _) => { + // &X { y: 1 }, X { y: 1 }.y + contains_exterior_struct_lit(&**x) + } + + ast::ExprMethodCall(_, _, ref exprs) => { + // X { y: 1 }.bar(...) + contains_exterior_struct_lit(&**exprs.get(0)) + } + + _ => false + } + } } } @@ -992,16 +1030,16 @@ impl LintPass for UnnecessaryParens { } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - let (value, msg) = match e.node { - ast::ExprIf(cond, _, _) => (cond, "`if` condition"), - ast::ExprWhile(cond, _) => (cond, "`while` condition"), - ast::ExprMatch(head, _) => (head, "`match` head expression"), - ast::ExprRet(Some(value)) => (value, "`return` value"), - ast::ExprAssign(_, value) => (value, "assigned value"), - ast::ExprAssignOp(_, _, value) => (value, "assigned value"), + let (value, msg, struct_lit_needs_parens) = match e.node { + ast::ExprIf(cond, _, _) => (cond, "`if` condition", true), + ast::ExprWhile(cond, _) => (cond, "`while` condition", true), + ast::ExprMatch(head, _) => (head, "`match` head expression", true), + ast::ExprRet(Some(value)) => (value, "`return` value", false), + ast::ExprAssign(_, value) => (value, "assigned value", false), + ast::ExprAssignOp(_, _, value) => (value, "assigned value", false), _ => return }; - self.check_unnecessary_parens_core(cx, &*value, msg); + self.check_unnecessary_parens_core(cx, &*value, msg, struct_lit_needs_parens); } fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { @@ -1015,7 +1053,7 @@ impl LintPass for UnnecessaryParens { }, _ => return }; - self.check_unnecessary_parens_core(cx, &*value, msg); + self.check_unnecessary_parens_core(cx, &*value, msg, false); } } @@ -1388,11 +1426,7 @@ impl LintPass for Stability { Some(method) => { match method.origin { typeck::MethodStatic(def_id) => { - // If this implements a trait method, get def_id - // of the method inside trait definition. - // Otherwise, use the current def_id (which refers - // to the method inside impl). - ty::trait_method_of_method(cx.tcx, def_id).unwrap_or(def_id) + def_id } typeck::MethodParam(typeck::MethodParam { trait_id: trait_id, @@ -1416,8 +1450,7 @@ impl LintPass for Stability { // check anything for crate-local usage. if ast_util::is_local(id) { return } - let stability = cx.tcx.stability.borrow_mut().lookup(&cx.tcx.sess.cstore, id); - + let stability = stability::lookup(cx.tcx, id); let (lint, label) = match stability { // no stability attributes == Unstable None => (UNSTABLE, "unmarked"), diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5aa10b5ab8e8a..8896a068baa76 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -176,7 +176,7 @@ pub struct LintId { impl PartialEq for LintId { fn eq(&self, other: &LintId) -> bool { - (self.lint as *Lint) == (other.lint as *Lint) + (self.lint as *const Lint) == (other.lint as *const Lint) } } @@ -184,7 +184,7 @@ impl Eq for LintId { } impl hash::Hash for LintId { fn hash(&self, state: &mut S) { - let ptr = self.lint as *Lint; + let ptr = self.lint as *const Lint; ptr.hash(state); } } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index f5ce8cda8c4a6..78a29b52bdf5b 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -181,7 +181,7 @@ fn item_sized(item: ebml::Doc) -> ast::Sized { fn item_method_sort(item: ebml::Doc) -> char { let mut ret = 'r'; reader::tagged_docs(item, tag_item_trait_method_sort, |doc| { - ret = doc.as_str_slice()[0] as char; + ret = doc.as_str_slice().as_bytes()[0] as char; false }); ret @@ -757,13 +757,13 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ { let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self); let string = explicit_self_doc.as_str_slice(); - let explicit_self_kind = string[0]; + let explicit_self_kind = string.as_bytes()[0]; match explicit_self_kind as char { 's' => ast::SelfStatic, 'v' => ast::SelfValue, '~' => ast::SelfUniq, // FIXME(#4846) expl. region - '&' => ast::SelfRegion(None, get_mutability(string[1])), + '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1])), _ => fail!("unknown self type code: `{}`", explicit_self_kind as char) } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index b606ba3b87a53..96284f8de261a 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -24,6 +24,7 @@ use middle::ty::{node_id_to_type, lookup_item_type}; use middle::astencode; use middle::ty; use middle::typeck; +use middle::stability; use middle; use util::nodemap::{NodeMap, NodeSet}; @@ -328,7 +329,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, encode_visibility(ebml_w, variant.node.vis); encode_attributes(ebml_w, variant.node.attrs.as_slice()); - let stab = ecx.tcx.stability.borrow().lookup_local(variant.node.id); + let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id)); encode_stability(ebml_w, stab); match variant.node.kind { @@ -592,7 +593,9 @@ fn encode_info_for_mod(ecx: &EncodeContext, encode_path(ebml_w, path.clone()); encode_visibility(ebml_w, vis); - encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(id)); + + let stab = stability::lookup(ecx.tcx, ast_util::local_def(id)); + encode_stability(ebml_w, stab); // Encode the reexports of this module, if this module is public. if vis == Public { @@ -722,7 +725,8 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext, encode_symbol(ecx, ebml_w, ctor_id); } - encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(ctor_id)); + let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id)); + encode_stability(ebml_w, stab); // indicate that this is a tuple struct ctor, because downstream users will normally want // the tuple struct definition, but without this there is no way for them to tell that @@ -768,7 +772,7 @@ fn encode_info_for_method(ecx: &EncodeContext, encode_method_ty_fields(ecx, ebml_w, m); encode_parent_item(ebml_w, local_def(parent_id)); - let stab = ecx.tcx.stability.borrow().lookup_local(m.def_id.node); + let stab = stability::lookup(ecx.tcx, m.def_id); encode_stability(ebml_w, stab); // The type for methods gets encoded twice, which is unfortunate. @@ -915,10 +919,10 @@ fn encode_info_for_item(ecx: &EncodeContext, } debug!("encoding info for item at {}", - ecx.tcx.sess.codemap().span_to_str(item.span)); + tcx.sess.codemap().span_to_str(item.span)); let def_id = local_def(item.id); - let stab = tcx.stability.borrow().lookup_local(item.id); + let stab = stability::lookup(tcx, ast_util::local_def(item.id)); match item.node { ItemStatic(_, m, _) => { @@ -1206,7 +1210,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_method_ty_fields(ecx, ebml_w, &*method_ty); encode_parent_item(ebml_w, def_id); - let stab = tcx.stability.borrow().lookup_local(method_def_id.node); + let stab = stability::lookup(tcx, method_def_id); encode_stability(ebml_w, stab); let elem = ast_map::PathName(method_ty.ident.name); @@ -1308,7 +1312,7 @@ fn my_visit_expr(_e: &Expr) { } fn my_visit_item(i: &Item, ebml_w: &mut Encoder, - ecx_ptr: *int, + ecx_ptr: *const int, index: &mut Vec>) { let mut ebml_w = unsafe { ebml_w.unsafe_clone() }; // See above @@ -1320,7 +1324,7 @@ fn my_visit_item(i: &Item, fn my_visit_foreign_item(ni: &ForeignItem, ebml_w: &mut Encoder, - ecx_ptr:*int, + ecx_ptr:*const int, index: &mut Vec>) { // See above let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) }; @@ -1341,7 +1345,7 @@ fn my_visit_foreign_item(ni: &ForeignItem, struct EncodeVisitor<'a,'b> { ebml_w_for_visit_item: &'a mut Encoder<'b>, - ecx_ptr:*int, + ecx_ptr:*const int, index: &'a mut Vec>, } @@ -1386,7 +1390,7 @@ fn encode_info_for_items(ecx: &EncodeContext, Public); // See comment in `encode_side_tables_for_ii` in astencode - let ecx_ptr: *int = unsafe { mem::transmute(ecx) }; + let ecx_ptr: *const int = unsafe { mem::transmute(ecx) }; visit::walk_crate(&mut EncodeVisitor { index: &mut index, ecx_ptr: ecx_ptr, diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index eca0432229e2f..ccab76ca6f012 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -545,14 +545,15 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result write_tag_and_id for Encoder<'a> { } struct SideTableEncodingIdVisitor<'a,'b> { - ecx_ptr: *libc::c_void, + ecx_ptr: *const libc::c_void, new_ebml_w: &'a mut Encoder<'b>, } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 156b884006772..e7457f370d9ad 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -399,7 +399,7 @@ struct DeadVisitor<'a> { impl<'a> DeadVisitor<'a> { fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool { let (is_named, has_leading_underscore) = match node.ident() { - Some(ref ident) => (true, token::get_ident(*ident).get()[0] == ('_' as u8)), + Some(ref ident) => (true, token::get_ident(*ident).get().as_bytes()[0] == ('_' as u8)), _ => (false, false) }; let field_type = ty::node_id_to_type(self.tcx, node.id); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index f09af6ea4416e..5c09466cd9682 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -360,7 +360,8 @@ fn visit_fn(ir: &mut IrMaps, let mut fn_maps = IrMaps::new(ir.tcx); unsafe { - debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(&fn_maps)); + debug!("creating fn_maps: {}", + transmute::<&IrMaps, *const IrMaps>(&fn_maps)); } for arg in decl.inputs.iter() { @@ -1510,7 +1511,7 @@ impl<'a> Liveness<'a> { fn should_warn(&self, var: Variable) -> Option { let name = self.ir.variable_name(var); - if name.len() == 0 || name.as_slice()[0] == ('_' as u8) { + if name.len() == 0 || name.as_bytes()[0] == ('_' as u8) { None } else { Some(name) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d26ccc40d3ac1..e1a2a5741fbe1 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -126,7 +126,6 @@ pub enum FieldName { #[deriving(Clone, PartialEq, Eq, Hash)] pub enum ElementKind { VecElement, - StrElement, OtherElement, } @@ -794,7 +793,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { //! - `derefs`: the deref number to be used for //! the implicit index deref, if any (see above) - let element_ty = match ty::index(base_cmt.ty) { + let element_ty = match ty::array_element_ty(base_cmt.ty) { Some(ref mt) => mt.ty, None => { self.tcx().sess.span_bug( @@ -1137,9 +1136,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { cat_interior(_, InteriorElement(VecElement)) => { "vec content".to_string() } - cat_interior(_, InteriorElement(StrElement)) => { - "str content".to_string() - } cat_interior(_, InteriorElement(OtherElement)) => { "indexed content".to_string() } @@ -1320,7 +1316,6 @@ fn element_kind(t: ty::t) -> ElementKind { ty::ty_rptr(_, ty::mt{ty:ty, ..}) | ty::ty_uniq(ty) => match ty::get(ty).sty { ty::ty_vec(_, None) => VecElement, - ty::ty_str => StrElement, _ => OtherElement }, ty::ty_vec(..) => VecElement, diff --git a/src/librustc/middle/save/span_utils.rs b/src/librustc/middle/save/span_utils.rs index e646827fa23dd..57006d5e72b9b 100644 --- a/src/librustc/middle/save/span_utils.rs +++ b/src/librustc/middle/save/span_utils.rs @@ -90,7 +90,7 @@ impl<'a> SpanUtils<'a> { let mut result = None; let mut toks = self.retokenise_span(span); - let mut bracket_count = 0; + let mut bracket_count = 0u; loop { let ts = toks.next_token(); if ts.tok == token::EOF { @@ -113,7 +113,7 @@ impl<'a> SpanUtils<'a> { // Return the span for the first identifier in the path. pub fn span_for_first_ident(&self, span: Span) -> Option { let mut toks = self.retokenise_span(span); - let mut bracket_count = 0; + let mut bracket_count = 0u; loop { let ts = toks.next_token(); if ts.tok == token::EOF { @@ -139,7 +139,7 @@ impl<'a> SpanUtils<'a> { let mut toks = self.retokenise_span(span); let mut prev = toks.next_token(); let mut result = None; - let mut bracket_count = 0; + let mut bracket_count = 0u; let mut last_span = None; while prev.tok != token::EOF { last_span = None; @@ -187,7 +187,7 @@ impl<'a> SpanUtils<'a> { let mut toks = self.retokenise_span(span); let mut prev = toks.next_token(); let mut result = None; - let mut bracket_count = 0; + let mut bracket_count = 0u; loop { let next = toks.next_token(); @@ -232,7 +232,7 @@ impl<'a> SpanUtils<'a> { let mut toks = self.retokenise_span(span); // We keep track of how many brackets we're nested in - let mut bracket_count = 0; + let mut bracket_count = 0i; loop { let ts = toks.next_token(); if ts.tok == token::EOF { @@ -291,7 +291,7 @@ impl<'a> SpanUtils<'a> { let mut next = toks.next_token(); let mut stored_val = false; let mut found_val = false; - let mut bracket_count = 0; + let mut bracket_count = 0u; while next.tok != token::EOF { if bracket_count == 1 { if next.tok == tok2 { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index fc76648ec5524..ac17bd0750352 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -20,7 +20,8 @@ use syntax::ast::{Generics, StructDef, Ident}; use syntax::ast_util::is_local; use syntax::attr::Stability; use syntax::visit::{FnKind, FkMethod, Visitor}; -use metadata::{cstore, csearch}; +use middle::ty; +use metadata::csearch; /// A stability index, giving the stability level for items and methods. pub struct Index { @@ -105,21 +106,24 @@ impl Index { attr::find_stability(krate.attrs.as_slice())); annotator.index } +} - /// Lookup the stability for a node, loading external crate - /// metadata as necessary. - pub fn lookup(&mut self, cstore: &cstore::CStore, id: DefId) -> Option { - if is_local(id) { - self.lookup_local(id.node) - } else { - let stab = csearch::get_stability(cstore, id); - self.extern_cache.insert(id, stab.clone()); +/// Lookup the stability for a node, loading external crate +/// metadata as necessary. +pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option { + // is this definition the implementation of a trait method? + match ty::trait_method_of_method(tcx, id) { + Some(trait_method_id) if trait_method_id != id => { + lookup(tcx, trait_method_id) + } + _ if is_local(id) => { + tcx.stability.borrow().local.find_copy(&id.node) + } + _ => { + let stab = csearch::get_stability(&tcx.sess.cstore, id); + let mut index = tcx.stability.borrow_mut(); + (*index).extern_cache.insert(id, stab.clone()); stab } } - - /// Lookup the stability for a local node without loading any external crates - pub fn lookup_local(&self, id: NodeId) -> Option { - self.local.find_copy(&id) - } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 5e7284dbfd1de..0cd3b6e7d7918 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -44,7 +44,7 @@ impl HomogeneousTuple3 for (T, T, T) { fn as_slice<'a>(&'a self) -> &'a [T] { unsafe { - let ptr: *T = mem::transmute(self); + let ptr: *const T = mem::transmute(self); let slice = raw::Slice { data: ptr, len: 3 }; mem::transmute(slice) } @@ -52,7 +52,7 @@ impl HomogeneousTuple3 for (T, T, T) { fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { unsafe { - let ptr: *T = mem::transmute(self); + let ptr: *const T = mem::transmute(self); let slice = raw::Slice { data: ptr, len: 3 }; mem::transmute(slice) } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 210de1946c9e6..75271804b7911 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1220,7 +1220,7 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>, // - new_fn_ctxt // - trans_args -fn arg_kind(cx: &FunctionContext, t: ty::t) -> datum::Rvalue { +pub fn arg_kind(cx: &FunctionContext, t: ty::t) -> datum::Rvalue { use middle::trans::datum::{ByRef, ByValue}; datum::Rvalue { diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index e04454d4a68d0..e1c02f543bf9e 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -453,7 +453,7 @@ pub fn StructGEP(cx: &Block, pointer: ValueRef, idx: uint) -> ValueRef { } } -pub fn GlobalString(cx: &Block, _str: *c_char) -> ValueRef { +pub fn GlobalString(cx: &Block, _str: *const c_char) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); @@ -462,7 +462,7 @@ pub fn GlobalString(cx: &Block, _str: *c_char) -> ValueRef { } } -pub fn GlobalStringPtr(cx: &Block, _str: *c_char) -> ValueRef { +pub fn GlobalStringPtr(cx: &Block, _str: *const c_char) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); @@ -577,7 +577,8 @@ pub fn TruncOrBitCast(cx: &Block, val: ValueRef, dest_ty: Type) -> ValueRef { } } -pub fn Cast(cx: &Block, op: Opcode, val: ValueRef, dest_ty: Type, _: *u8) +pub fn Cast(cx: &Block, op: Opcode, val: ValueRef, dest_ty: Type, + _: *const u8) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } @@ -636,7 +637,8 @@ pub fn EmptyPhi(cx: &Block, ty: Type) -> ValueRef { } } -pub fn Phi(cx: &Block, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef { +pub fn Phi(cx: &Block, ty: Type, vals: &[ValueRef], + bbs: &[BasicBlockRef]) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } B(cx).phi(ty, vals, bbs) @@ -672,7 +674,7 @@ pub fn add_comment(cx: &Block, text: &str) { B(cx).add_comment(text) } -pub fn InlineAsmCall(cx: &Block, asm: *c_char, cons: *c_char, +pub fn InlineAsmCall(cx: &Block, asm: *const c_char, cons: *const c_char, inputs: &[ValueRef], output: Type, volatile: bool, alignstack: bool, dia: AsmDialect) -> ValueRef { diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs index 4078268c6a5d8..a9c1adac3d7cf 100644 --- a/src/librustc/middle/trans/builder.rs +++ b/src/librustc/middle/trans/builder.rs @@ -31,9 +31,9 @@ pub struct Builder<'a> { // This is a really awful way to get a zero-length c-string, but better (and a // lot more efficient) than doing str::as_c_str("", ...) every time. -pub fn noname() -> *c_char { +pub fn noname() -> *const c_char { static cnull: c_char = 0; - &cnull as *c_char + &cnull as *const c_char } impl<'a> Builder<'a> { @@ -159,6 +159,14 @@ impl<'a> Builder<'a> { attributes: &[(uint, u64)]) -> ValueRef { self.count_insn("invoke"); + + debug!("Invoke {} with args ({})", + self.ccx.tn.val_to_str(llfn), + args.iter() + .map(|&v| self.ccx.tn.val_to_str(v)) + .collect::>() + .connect(", ")); + unsafe { let v = llvm::LLVMBuildInvoke(self.llbuilder, llfn, @@ -564,14 +572,14 @@ impl<'a> Builder<'a> { } } - pub fn global_string(&self, _str: *c_char) -> ValueRef { + pub fn global_string(&self, _str: *const c_char) -> ValueRef { self.count_insn("globalstring"); unsafe { llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname()) } } - pub fn global_string_ptr(&self, _str: *c_char) -> ValueRef { + pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef { self.count_insn("globalstringptr"); unsafe { llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname()) @@ -774,7 +782,7 @@ impl<'a> Builder<'a> { } } - pub fn inline_asm_call(&self, asm: *c_char, cons: *c_char, + pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, inputs: &[ValueRef], output: Type, volatile: bool, alignstack: bool, dia: AsmDialect) -> ValueRef { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 8b484e90898c9..116b2e6b421b8 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -16,7 +16,9 @@ * closure. */ +use arena::TypedArena; use back::abi; +use back::link; use driver::session; use lib::llvm::ValueRef; use lib::llvm::llvm; @@ -33,28 +35,26 @@ use middle::trans::cleanup::CleanupMethods; use middle::trans::common; use middle::trans::common::*; use middle::trans::datum::*; -use middle::trans::datum::Datum; +use middle::trans::datum::{Datum, KindOps}; use middle::trans::expr; use middle::trans::glue; use middle::trans::inline; +use middle::trans::foreign; use middle::trans::meth; use middle::trans::monomorphize; +use middle::trans::type_::Type; use middle::trans::type_of; -use middle::trans::foreign; use middle::ty; use middle::typeck; use middle::typeck::coherence::make_substs_for_receiver_types; use middle::typeck::MethodCall; use util::ppaux::Repr; -use middle::trans::type_::Type; - +use std::gc::Gc; use syntax::ast; use synabi = syntax::abi; use syntax::ast_map; -use std::gc::Gc; - pub struct MethodData { pub llfn: ValueRef, pub llself: ValueRef, @@ -224,6 +224,134 @@ fn resolve_default_method_vtables(bcx: &Block, param_vtables } +/// Translates the adapter that deconstructs a `Box` object into +/// `Trait` so that a by-value self method can be called. +pub fn trans_unboxing_shim(bcx: &Block, + llshimmedfn: ValueRef, + method: &ty::Method, + method_id: ast::DefId, + substs: subst::Substs) + -> ValueRef { + let _icx = push_ctxt("trans_unboxing_shim"); + let ccx = bcx.ccx(); + let tcx = bcx.tcx(); + + // Transform the self type to `Box`. + let self_type = *method.fty.sig.inputs.get(0); + let boxed_self_type = ty::mk_uniq(tcx, self_type); + let boxed_function_type = ty::FnSig { + binder_id: method.fty.sig.binder_id, + inputs: method.fty.sig.inputs.iter().enumerate().map(|(i, typ)| { + if i == 0 { + boxed_self_type + } else { + *typ + } + }).collect(), + output: method.fty.sig.output, + variadic: false, + }; + let boxed_function_type = ty::BareFnTy { + fn_style: method.fty.fn_style, + abi: method.fty.abi, + sig: boxed_function_type, + }; + let boxed_function_type = + ty::mk_bare_fn(tcx, boxed_function_type).subst(tcx, &substs); + let function_type = + ty::mk_bare_fn(tcx, method.fty.clone()).subst(tcx, &substs); + + let function_name = tcx.map.with_path(method_id.node, |path| { + link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim") + }); + let llfn = decl_internal_rust_fn(ccx, + boxed_function_type, + function_name.as_slice()); + + let block_arena = TypedArena::new(); + let empty_param_substs = param_substs::empty(); + let return_type = ty::ty_fn_ret(boxed_function_type); + let fcx = new_fn_ctxt(ccx, + llfn, + -1, + false, + return_type, + &empty_param_substs, + None, + &block_arena); + init_function(&fcx, false, return_type); + + // Create the substituted versions of the self type. + let mut bcx = fcx.entry_bcx.borrow().clone().unwrap(); + let arg_scope = fcx.push_custom_cleanup_scope(); + let arg_scope_id = cleanup::CustomScope(arg_scope); + let boxed_arg_types = ty::ty_fn_args(boxed_function_type); + let boxed_self_type = *boxed_arg_types.get(0); + let arg_types = ty::ty_fn_args(function_type); + let self_type = *arg_types.get(0); + let boxed_self_kind = arg_kind(&fcx, boxed_self_type); + + // Create a datum for self. + let llboxedself = unsafe { + llvm::LLVMGetParam(fcx.llfn, fcx.arg_pos(0) as u32) + }; + let llboxedself = Datum::new(llboxedself, + boxed_self_type, + boxed_self_kind); + let boxed_self = + unpack_datum!(bcx, + llboxedself.to_lvalue_datum_in_scope(bcx, + "boxedself", + arg_scope_id)); + + // This `Load` is needed because lvalue data are always by-ref. + let llboxedself = Load(bcx, boxed_self.val); + + let llself = if type_is_immediate(ccx, self_type) { + let llboxedself = Load(bcx, llboxedself); + immediate_rvalue(llboxedself, self_type) + } else { + let llself = rvalue_scratch_datum(bcx, self_type, "self"); + memcpy_ty(bcx, llself.val, llboxedself, self_type); + llself + }; + + // Make sure we don't free the box twice! + boxed_self.kind.post_store(bcx, boxed_self.val, boxed_self_type); + + // Schedule a cleanup to free the box. + fcx.schedule_free_value(arg_scope_id, + llboxedself, + cleanup::HeapExchange, + self_type); + + // Now call the function. + let mut llshimmedargs = vec!(llself.val); + for i in range(1, arg_types.len()) { + llshimmedargs.push(unsafe { + llvm::LLVMGetParam(fcx.llfn, fcx.arg_pos(i) as u32) + }); + } + bcx = trans_call_inner(bcx, + None, + function_type, + |bcx, _| { + Callee { + bcx: bcx, + data: Fn(llshimmedfn), + } + }, + ArgVals(llshimmedargs.as_slice()), + match fcx.llretptr.get() { + None => None, + Some(llretptr) => Some(expr::SaveIn(llretptr)), + }).bcx; + + bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope); + finish_fn(&fcx, bcx); + + llfn +} pub fn trans_fn_ref_with_vtables( bcx: &Block, // diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index a1923022e7b17..b1577a6abfe14 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -471,7 +471,7 @@ impl<'a> Block<'a> { } pub fn to_str(&self) -> String { - let blk: *Block = self; + let blk: *const Block = self; format!("[block {}]", blk) } } @@ -568,7 +568,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va } let sc = llvm::LLVMConstStringInContext(cx.llcx, - s.get().as_ptr() as *c_char, + s.get().as_ptr() as *const c_char, s.get().len() as c_uint, !null_terminated as Bool); @@ -636,7 +636,7 @@ pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef { pub fn C_bytes(ccx: &CrateContext, bytes: &[u8]) -> ValueRef { unsafe { - let ptr = bytes.as_ptr() as *c_char; + let ptr = bytes.as_ptr() as *const c_char; return llvm::LLVMConstStringInContext(ccx.llcx, ptr, bytes.len() as c_uint, True); } } diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 68c6f1752bdfe..6387ec791bab9 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -221,8 +221,8 @@ impl CrateContext { llvm_insns: RefCell::new(HashMap::new()), fn_stats: RefCell::new(Vec::new()), }, - int_type: Type::from_ref(ptr::null()), - opaque_vec_type: Type::from_ref(ptr::null()), + int_type: Type::from_ref(ptr::mut_null()), + opaque_vec_type: Type::from_ref(ptr::mut_null()), builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)), uses_gc: false, dbg_cx: dbg_cx, diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index e7895a1bb9a6d..400babb39f82c 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -805,7 +805,7 @@ pub fn create_global_var_metadata(cx: &CrateContext, type_metadata, is_local_to_unit, global, - ptr::null()); + ptr::mut_null()); } }) }); @@ -980,7 +980,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) { } }; - if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() { + if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::mut_null() { cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \ Referenced variable location is not an alloca!"); } @@ -1221,7 +1221,7 @@ pub fn create_function_debug_context(cx: &CrateContext, cx.sess().opts.optimize != config::No, llfn, template_parameters, - ptr::null()) + ptr::mut_null()) } }) }); @@ -1257,7 +1257,7 @@ pub fn create_function_debug_context(cx: &CrateContext, // Return type -- llvm::DIBuilder wants this at index 0 match fn_decl.output.node { ast::TyNil => { - signature.push(ptr::null()); + signature.push(ptr::mut_null()); } _ => { assert_type_for_node_id(cx, fn_ast_id, error_span); @@ -1328,7 +1328,7 @@ pub fn create_function_debug_context(cx: &CrateContext, file_metadata, name, actual_self_type_metadata, - ptr::null(), + ptr::mut_null(), 0, 0) } @@ -1361,7 +1361,7 @@ pub fn create_function_debug_context(cx: &CrateContext, file_metadata, name, actual_type_metadata, - ptr::null(), + ptr::mut_null(), 0, 0) } @@ -1433,24 +1433,23 @@ fn compile_unit_metadata(cx: &CrateContext) { let producer = format!("rustc version {}", (option_env!("CFG_VERSION")).expect("CFG_VERSION")); - compile_unit_name.with_ref(|compile_unit_name| { - work_dir.as_vec().with_c_str(|work_dir| { - producer.with_c_str(|producer| { - "".with_c_str(|flags| { - "".with_c_str(|split_name| { - unsafe { - llvm::LLVMDIBuilderCreateCompileUnit( - debug_context(cx).builder, - DW_LANG_RUST, - compile_unit_name, - work_dir, - producer, - cx.sess().opts.optimize != config::No, - flags, - 0, - split_name); - } - }) + let compile_unit_name = compile_unit_name.as_ptr(); + work_dir.as_vec().with_c_str(|work_dir| { + producer.with_c_str(|producer| { + "".with_c_str(|flags| { + "".with_c_str(|split_name| { + unsafe { + llvm::LLVMDIBuilderCreateCompileUnit( + debug_context(cx).builder, + DW_LANG_RUST, + compile_unit_name, + work_dir, + producer, + cx.sess().opts.optimize != config::No, + flags, + 0, + split_name); + } }) }) }) @@ -2374,7 +2373,7 @@ fn prepare_enum_metadata(cx: &CrateContext, bytes_to_bits(enum_type_size), bytes_to_bits(enum_type_align), 0, // Flags - ptr::null(), + ptr::mut_null(), 0, // RuntimeLang unique_type_id_str) } @@ -2554,10 +2553,10 @@ fn create_struct_stub(cx: &CrateContext, bytes_to_bits(struct_size), bytes_to_bits(struct_align), 0, - ptr::null(), + ptr::mut_null(), empty_array, 0, - ptr::null(), + ptr::mut_null(), unique_type_id) }) }) @@ -2855,7 +2854,7 @@ fn subroutine_type_metadata(cx: &CrateContext, // return type signature_metadata.push(match ty::get(signature.output).sty { - ty::ty_nil => ptr::null(), + ty::ty_nil => ptr::mut_null(), _ => type_metadata(cx, signature.output, span) }); @@ -3153,7 +3152,8 @@ fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) { KnownLocation { scope, line, .. } => { let col = 0u; // Always set the column to zero like Clang and GCC debug!("setting debug location to {} {}", line, col); - let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()]; + let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), + scope, ptr::mut_null()]; unsafe { metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext, elements.as_ptr(), @@ -3162,7 +3162,7 @@ fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) { } UnknownLocation => { debug!("clearing debug location "); - metadata_node = ptr::null(); + metadata_node = ptr::mut_null(); } }; @@ -3771,7 +3771,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc node.scope, - None => ptr::null() + None => ptr::mut_null() }; let namespace_name = token::get_name(name); let scope = namespace_name.get().with_c_str(|namespace_name| { @@ -3781,7 +3781,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc(bcx: &'a Block<'a>, auto_ref(bcx, datum, expr) } - fn auto_borrow_obj<'a>(bcx: &'a Block<'a>, + fn auto_borrow_obj<'a>(mut bcx: &'a Block<'a>, expr: &ast::Expr, source_datum: Datum) -> DatumBlock<'a, Expr> { @@ -285,7 +285,11 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, let target_obj_ty = expr_ty_adjusted(bcx, expr); debug!("auto_borrow_obj(target={})", target_obj_ty.repr(tcx)); - let mut datum = source_datum.to_expr_datum(); + // Arrange cleanup, if not already done. This is needed in + // case we are auto-borrowing a Box to &Trait + let datum = unpack_datum!( + bcx, source_datum.to_lvalue_datum(bcx, "autoborrowobj", expr.id)); + let mut datum = datum.to_expr_datum(); datum.ty = target_obj_ty; DatumBlock::new(bcx, datum) } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index fcd6c7e293ea2..488dc6d99e35c 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -957,7 +957,11 @@ pub fn lltype_for_foreign_fn(ccx: &CrateContext, ty: ty::t) -> Type { fn add_argument_attributes(tys: &ForeignTypes, llfn: ValueRef) { - let mut i = if tys.fn_ty.ret_ty.is_indirect() { 1 } else { 0 }; + let mut i = if tys.fn_ty.ret_ty.is_indirect() { + 1i + } else { + 0i + }; match tys.fn_ty.ret_ty.attr { Some(attr) => unsafe { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 85660cd2eb540..e1d43c5240059 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -492,14 +492,24 @@ fn emit_vtable_methods(bcx: &Block, m.repr(tcx), substs.repr(tcx)); if m.generics.has_type_params(subst::FnSpace) || - ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) - { + ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) { debug!("(making impl vtable) method has self or type params: {}", token::get_ident(ident)); C_null(Type::nil(ccx).ptr_to()) } else { - trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), - substs.clone(), vtables.clone()) + let mut fn_ref = trans_fn_ref_with_vtables(bcx, + m_id, + ExprId(0), + substs.clone(), + vtables.clone()); + if m.explicit_self == ast::SelfValue { + fn_ref = trans_unboxing_shim(bcx, + fn_ref, + &*m, + m_id, + substs.clone()); + } + fn_ref } }).collect() } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 01e3af8a3d79f..79630be7c5e08 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -158,7 +158,7 @@ pub struct creader_cache_key { pub type creader_cache = RefCell>; pub struct intern_key { - sty: *sty, + sty: *const sty, } // NB: Do not replace this with #[deriving(PartialEq)]. The automatically-derived @@ -409,7 +409,7 @@ enum t_opaque {} #[allow(raw_pointer_deriving)] #[deriving(Clone, PartialEq, Eq, Hash)] -pub struct t { inner: *t_opaque } +pub struct t { inner: *const t_opaque } impl fmt::Show for t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1216,7 +1216,7 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t { flags: flags, }; - let sty_ptr = &t.sty as *sty; + let sty_ptr = &t.sty as *const sty; let key = intern_key { sty: sty_ptr, @@ -1227,7 +1227,7 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t { cx.next_id.set(cx.next_id.get() + 1); unsafe { - mem::transmute::<*sty, t>(sty_ptr) + mem::transmute::<*const sty, t>(sty_ptr) } } @@ -1533,7 +1533,7 @@ pub fn type_is_self(ty: t) -> bool { } } -fn type_is_slice(ty:t) -> bool { +fn type_is_slice(ty: t) -> bool { match get(ty).sty { ty_rptr(_, mt) => match get(mt.ty).sty { ty_vec(_, None) | ty_str => true, @@ -1543,6 +1543,18 @@ fn type_is_slice(ty:t) -> bool { } } +pub fn type_is_vec(ty: t) -> bool { + match get(ty).sty { + ty_vec(..) => true, + ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) | + ty_box(t) | ty_uniq(t) => match get(t).sty { + ty_vec(_, None) => true, + _ => false + }, + _ => false + } +} + pub fn type_is_structural(ty: t) -> bool { match get(ty).sty { ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) | @@ -1560,7 +1572,7 @@ pub fn type_is_simd(cx: &ctxt, ty: t) -> bool { pub fn sequence_element_type(cx: &ctxt, ty: t) -> t { match get(ty).sty { - ty_vec(mt, Some(_)) => mt.ty, + ty_vec(mt, _) => mt.ty, ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) | ty_box(t) | ty_uniq(t) => match get(t).sty { ty_vec(mt, None) => mt.ty, @@ -2551,6 +2563,21 @@ pub fn deref(t: t, explicit: bool) -> Option { // Returns the type of t[i] pub fn index(t: t) -> Option { + match get(t).sty { + ty_vec(mt, Some(_)) => Some(mt), + ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) | + ty_box(t) | ty_uniq(t) => match get(t).sty { + ty_vec(mt, None) => Some(mt), + _ => None, + }, + _ => None + } +} + +// Returns the type of elements contained within an 'array-like' type. +// This is exactly the same as the above, except it supports strings, +// which can't actually be indexed. +pub fn array_element_ty(t: t) -> Option { match get(t).sty { ty_vec(mt, Some(_)) => Some(mt), ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) | diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 67437da44c5d6..60ce9508dc46b 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -318,6 +318,9 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt, for field in fields.iter() { match field_map.find_mut(&field.ident.name) { Some(&(_, true)) => { + // Check the pattern anyway, so that attempts to look + // up its type won't fail + check_pat(pcx, &*field.pat, ty::mk_err()); tcx.sess.span_err(span, format!("field `{}` bound twice in pattern", token::get_ident(field.ident)).as_slice()); diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 4270ff1e7952d..c3b2756bdbff2 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -271,7 +271,9 @@ fn construct_transformed_self_ty_for_object( tcx.sess.span_bug(span, "static method for object type receiver"); } ast::SelfValue => { - ty::mk_err() // error reported in `enforce_object_limitations()` + let tr = ty::mk_trait(tcx, trait_def_id, obj_substs, + ty::empty_builtin_bounds()); + ty::mk_uniq(tcx, tr) } ast::SelfRegion(..) | ast::SelfUniq => { let transformed_self_ty = *method_ty.fty.sig.inputs.get(0); @@ -1225,14 +1227,7 @@ impl<'a> LookupContext<'a> { through an object"); } - ast::SelfValue => { // reason (a) above - self.tcx().sess.span_err( - self.span, - "cannot call a method with a by-value receiver \ - through an object"); - } - - ast::SelfRegion(..) | ast::SelfUniq => {} + ast::SelfValue | ast::SelfRegion(..) | ast::SelfUniq => {} } // reason (a) above @@ -1302,7 +1297,26 @@ impl<'a> LookupContext<'a> { } SelfValue => { - rcvr_matches_ty(self.fcx, rcvr_ty, candidate) + debug!("(is relevant?) explicit self is by-value"); + match ty::get(rcvr_ty).sty { + ty::ty_uniq(typ) => { + match ty::get(typ).sty { + ty::ty_trait(box ty::TyTrait { + def_id: self_did, + .. + }) => { + rcvr_matches_object(self_did, candidate) || + rcvr_matches_ty(self.fcx, + rcvr_ty, + candidate) + } + _ => { + rcvr_matches_ty(self.fcx, rcvr_ty, candidate) + } + } + } + _ => rcvr_matches_ty(self.fcx, rcvr_ty, candidate) + } } SelfRegion(_, m) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 0b35eab5679f0..5e675242688af 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1146,24 +1146,9 @@ fn check_cast(fcx: &FnCtxt, .span_err(span, "cannot cast as `bool`, compare with zero instead"); } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) { - fn is_vec(t: ty::t) -> bool { - match ty::get(t).sty { - ty::ty_vec(..) => true, - ty::ty_ptr(ty::mt{ty: t, ..}) | - ty::ty_rptr(_, ty::mt{ty: t, ..}) | - ty::ty_box(t) | - ty::ty_uniq(t) => { - match ty::get(t).sty { - ty::ty_vec(_, None) => true, - _ => false, - } - } - _ => false - } - } fn types_compatible(fcx: &FnCtxt, sp: Span, t1: ty::t, t2: ty::t) -> bool { - if !is_vec(t1) { + if !ty::type_is_vec(t1) { // If the type being casted from is not a vector, this special // case does not apply. return false @@ -1262,7 +1247,7 @@ impl<'a> RegionScope for infer::InferCtxt<'a> { impl<'a> FnCtxt<'a> { pub fn tag(&self) -> String { - format!("{}", self as *FnCtxt) + format!("{}", self as *const FnCtxt) } pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t { @@ -2779,10 +2764,30 @@ fn check_expr_with_unifier(fcx: &FnCtxt, fcx.write_ty(id, enum_type); } + type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t); + + fn check_fn_for_vec_elements_expected(fcx: &FnCtxt, + expected: Expectation) + -> (ExprCheckerWithTy, ty::t) { + let tcx = fcx.ccx.tcx; + let (coerce, t) = match expected { + // If we're given an expected type, we can try to coerce to it + ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)), + // Otherwise we just leave the type to be resolved later + _ => (false, fcx.infcx().next_ty_var()) + }; + if coerce { + (check_expr_coercable_to_type, t) + } else { + (check_expr_has_type, t) + } + } + let tcx = fcx.ccx.tcx; let id = expr.id; match expr.node { ast::ExprVstore(ev, vst) => { + let (check, t) = check_fn_for_vec_elements_expected(fcx, expected); let typ = match ev.node { ast::ExprVec(ref args) => { let mutability = match vst { @@ -2791,9 +2796,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt, }; let mut any_error = false; let mut any_bot = false; - let t: ty::t = fcx.infcx().next_ty_var(); for e in args.iter() { - check_expr_has_type(fcx, &**e, t); + check(fcx, &**e, t); let arg_t = fcx.expr_ty(&**e); if ty::type_is_error(arg_t) { any_error = true; @@ -2821,8 +2825,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, ast::ExprVstoreMutSlice => ast::MutMutable, _ => ast::MutImmutable, }; - let t = fcx.infcx().next_ty_var(); - check_expr_has_type(fcx, &**element, t); + check(fcx, &**element, t); let arg_t = fcx.expr_ty(&**element); if ty::type_is_error(arg_t) { ty::mk_err() @@ -3211,9 +3214,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt, check_cast(fcx, &**e, &**t, id, expr.span); } ast::ExprVec(ref args) => { - let t: ty::t = fcx.infcx().next_ty_var(); + let (check, t) = check_fn_for_vec_elements_expected(fcx, expected); for e in args.iter() { - check_expr_has_type(fcx, &**e, t); + check(fcx, &**e, t); } let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable}, Some(args.len())); @@ -3222,8 +3225,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt, ast::ExprRepeat(ref element, ref count_expr) => { check_expr_has_type(fcx, &**count_expr, ty::mk_uint()); let count = ty::eval_repeat_count(fcx, &**count_expr); - let t: ty::t = fcx.infcx().next_ty_var(); - check_expr_has_type(fcx, &**element, t); + let (check, t) = check_fn_for_vec_elements_expected(fcx, expected); + check(fcx, &**element, t); let element_ty = fcx.expr_ty(&**element); if ty::type_is_error(element_ty) { fcx.write_error(id); @@ -3805,7 +3808,15 @@ pub fn check_enum_variants(ccx: &CrateCtxt, let inh = blank_inherited_fields(ccx); let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id); - let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id()); + let declty = match hint { + attr::ReprAny | attr::ReprExtern => ty::mk_int(), + attr::ReprInt(_, attr::SignedInt(ity)) => { + ty::mk_mach_int(ity) + } + attr::ReprInt(_, attr::UnsignedInt(ity)) => { + ty::mk_mach_uint(ity) + } + }; check_const_with_ty(&fcx, e.span, &*e, declty); // check_expr (from check_const pass) doesn't guarantee // that the expression is in a form that eval_const_expr can diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 7612add9b0570..33e0d0331be6c 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -352,17 +352,15 @@ fn search_for_vtable(vcx: &VtableContext, // the next impl. // // FIXME: document a bit more what this means - // - // FIXME(#5781) this should be mk_eqty not mk_subty let TypeAndSubsts { substs: substs, ty: for_ty } = impl_self_ty(vcx, span, impl_did); - match infer::mk_subty(vcx.infcx, - false, - infer::RelateSelfType(span), - ty, - for_ty) { + match infer::mk_eqty(vcx.infcx, + false, + infer::RelateSelfType(span), + ty, + for_ty) { Err(_) => continue, Ok(()) => () } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 844a37d366ee5..f374f1dc26795 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -84,16 +84,13 @@ pub trait Combine { fn tys(&self, a: ty::t, b: ty::t) -> cres; fn tps(&self, - space: subst::ParamSpace, + _: subst::ParamSpace, as_: &[ty::t], bs: &[ty::t]) - -> cres> - { - // FIXME(#5781) -- In general, we treat variance a bit wrong - // here. For historical reasons, we treat Self as - // contravariant and other tps as invariant. Both are wrong: - // Self may or may not be contravariant, and other tps do not - // need to be invariant. + -> cres> { + // FIXME -- In general, we treat variance a bit wrong + // here. For historical reasons, we treat tps and Self + // as invariant. This is overly conservative. if as_.len() != bs.len() { return Err(ty::terr_ty_param_size(expected_found(self, @@ -101,24 +98,11 @@ pub trait Combine { bs.len()))); } - match space { - subst::SelfSpace => { - result::fold(as_ - .iter() - .zip(bs.iter()) - .map(|(a, b)| self.contratys(*a, *b)), - Vec::new(), - |mut v, a| { v.push(a); v }) - } - - subst::TypeSpace | subst::FnSpace => { - try!(result::fold_(as_ - .iter() - .zip(bs.iter()) - .map(|(a, b)| eq_tys(self, *a, *b)))); - Ok(Vec::from_slice(as_)) - } - } + try!(result::fold_(as_ + .iter() + .zip(bs.iter()) + .map(|(a, b)| eq_tys(self, *a, *b)))); + Ok(Vec::from_slice(as_)) } fn substs(&self, diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 197a2370eff9e..bc02297b5b1f3 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -247,9 +247,13 @@ pub enum fixup_err { pub fn fixup_err_to_str(f: fixup_err) -> String { match f { - unresolved_int_ty(_) => "unconstrained integral type".to_string(), + unresolved_int_ty(_) => { + "cannot determine the type of this integer; add a suffix to \ + specify the type explicitly".to_string() + } unresolved_float_ty(_) => { - "unconstrained floating point type".to_string() + "cannot determine the type of this number; add a suffix to specify \ + the type explicitly".to_string() } unresolved_ty(_) => "unconstrained type".to_string(), cyclic_ty(_) => "cyclic type of infinite size".to_string(), diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index ed6ea6c96775e..adfbe9de2d5bf 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -52,14 +52,12 @@ use middle::ty::{type_is_bot, IntType, UintType}; use middle::ty; use middle::ty_fold; use middle::typeck::infer::{Bounds, cyclic_ty, fixup_err, fres, InferCtxt}; -use middle::typeck::infer::unresolved_ty; -use middle::typeck::infer::unify::Root; +use middle::typeck::infer::{unresolved_float_ty, unresolved_int_ty}; +use middle::typeck::infer::{unresolved_ty}; use syntax::codemap::Span; use util::common::indent; use util::ppaux::{Repr, ty_to_str}; -use syntax::ast; - pub static resolve_nested_tvar: uint = 0b0000000001; pub static resolve_rvar: uint = 0b0000000010; pub static resolve_ivar: uint = 0b0000000100; @@ -83,21 +81,18 @@ pub struct ResolveState<'a> { err: Option, v_seen: Vec , type_depth: uint, - span: Option, } pub fn resolver<'a>(infcx: &'a InferCtxt, modes: uint, - span: Option) - -> ResolveState<'a> -{ + _: Option) + -> ResolveState<'a> { ResolveState { infcx: infcx, modes: modes, err: None, v_seen: Vec::new(), type_depth: 0, - span: span } } @@ -258,24 +253,10 @@ impl<'a> ResolveState<'a> { Some(UintType(t)) => ty::mk_mach_uint(t), None => { if self.should(force_ivar) { - // As a last resort, default to int and emit an error. - let ty = ty::mk_int(); - table.borrow_mut().set( - tcx, node.key, Root(Some(IntType(ast::TyI)), node.rank)); - - match self.span { - Some(sp) => { - self.infcx.tcx.sess.span_err( - sp, - "cannot determine the type of this integer; add \ - a suffix to specify the type explicitly"); - } - None => { } - } - ty - } else { - ty::mk_int_var(self.infcx.tcx, vid) + // As a last resort, emit an error. + self.err = Some(unresolved_int_ty(vid)); } + ty::mk_int_var(self.infcx.tcx, vid) } } } @@ -292,24 +273,10 @@ impl<'a> ResolveState<'a> { Some(t) => ty::mk_mach_float(t), None => { if self.should(force_fvar) { - // As a last resort, default to f64 and emit an error. - let ty = ty::mk_f64(); - table.borrow_mut().set( - tcx, node.key, Root(Some(ast::TyF64), node.rank)); - - match self.span { - Some(sp) => { - self.infcx.tcx.sess.span_err( - sp, - "cannot determine the type of this number; add \ - a suffix to specify the type explicitly"); - } - None => { } - } - ty - } else { - ty::mk_float_var(self.infcx.tcx, vid) + // As a last resort, emit an error. + self.err = Some(unresolved_float_ty(vid)); } + ty::mk_float_var(self.infcx.tcx, vid) } } } diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 3731990e61faa..0a60a5ce0e9fa 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -78,8 +78,8 @@ receiver position from being called via an object.) #### Trait variance and vtable resolution But traits aren't only used with objects. They're also used when -deciding whether a given impl satisfies a given trait bound (or should -be -- FIXME #5781). To set the scene here, imagine I had a function: +deciding whether a given impl satisfies a given trait bound. To set the +scene here, imagine I had a function: fn convertAll>(v: &[T]) { ... diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 7d74b8c729652..79d0690653faf 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -129,7 +129,7 @@ impl<'a> PluginLoader<'a> { let registrar = match lib.symbol(symbol.as_slice()) { Ok(registrar) => { - mem::transmute::<*u8,PluginRegistrarFun>(registrar) + mem::transmute::<*mut u8,PluginRegistrarFun>(registrar) } // again fatal if we can't register macros Err(err) => self.sess.span_fatal(vi.span, err.as_slice()) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1de6ff8f03b5f..fa353652fe1ec 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -355,7 +355,12 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String { ty_float(t) => ast_util::float_ty_to_str(t).to_string(), ty_box(typ) => format!("Gc<{}>", ty_to_str(cx, typ)), ty_uniq(typ) => format!("Box<{}>", ty_to_str(cx, typ)), - ty_ptr(ref tm) => format!("*{}", mt_to_str(cx, tm)), + ty_ptr(ref tm) => { + format!("*{} {}", match tm.mutbl { + ast::MutMutable => "mut", + ast::MutImmutable => "const", + }, ty_to_str(cx, tm.ty)) + } ty_rptr(r, ref tm) => { let mut buf = region_ptr_to_str(cx, r); buf.push_str(mt_to_str(cx, tm).as_slice()); diff --git a/src/librustc/util/sha2.rs b/src/librustc/util/sha2.rs index e9891533ac8bf..bfd3deb0f2dcd 100644 --- a/src/librustc/util/sha2.rs +++ b/src/librustc/util/sha2.rs @@ -34,7 +34,7 @@ fn read_u32v_be(dst: &mut[u32], input: &[u8]) { assert!(dst.len() * 4 == input.len()); unsafe { let mut x = dst.unsafe_mut_ref(0) as *mut _ as *mut u32; - let mut y = input.unsafe_ref(0) as *_ as *u32; + let mut y = input.unsafe_ref(0) as *const _ as *const u32; for _ in range(0, dst.len()) { *x = to_be32(*y); x = x.offset(1); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d243c61ddaff8..2d498e7f302d3 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,6 +18,7 @@ use rustc::metadata::csearch; use rustc::metadata::decoder; use rustc::middle::def; use rustc::middle::ty; +use rustc::middle::stability; use core; use doctree; @@ -102,6 +103,7 @@ fn try_inline_def(cx: &core::DocContext, attrs: load_attrs(tcx, did), inner: inner, visibility: Some(ast::Public), + stability: stability::lookup(tcx, did).clean(), def_id: did, }); Some(ret) @@ -317,6 +319,7 @@ fn build_impl(cx: &core::DocContext, name: None, attrs: attrs, visibility: Some(ast::Inherited), + stability: stability::lookup(tcx, did).clean(), def_id: did, }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d7bbb439dbb77..87151708812e5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -29,6 +29,7 @@ use rustc::middle::def; use rustc::middle::subst; use rustc::middle::subst::VecPerParamSpace; use rustc::middle::ty; +use rustc::middle::stability; use std::rc::Rc; use std::u32; @@ -44,6 +45,17 @@ pub static SCHEMA_VERSION: &'static str = "0.8.3"; mod inline; +// load the current DocContext from TLD +fn get_cx() -> Gc { + *super::ctxtkey.get().unwrap() +} + +// extract the stability index for a node from TLD, if possible +fn get_stability(def_id: ast::DefId) -> Option { + get_cx().tcx_opt().and_then(|tcx| stability::lookup(tcx, def_id)) + .map(|stab| stab.clean()) +} + pub trait Clean { fn clean(&self) -> T; } @@ -97,7 +109,7 @@ pub struct Crate { impl<'a> Clean for visit_ast::RustdocVisitor<'a> { fn clean(&self) -> Crate { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let mut externs = Vec::new(); cx.sess().cstore.iter_crate_data(|n, meta| { @@ -158,6 +170,7 @@ impl<'a> Clean for visit_ast::RustdocVisitor<'a> { name: Some(prim.to_url_str().to_string()), attrs: Vec::new(), visibility: None, + stability: None, def_id: ast_util::local_def(prim.to_node_id()), inner: PrimitiveItem(prim), }; @@ -193,25 +206,18 @@ pub struct ExternalCrate { impl Clean for cstore::crate_metadata { fn clean(&self) -> ExternalCrate { let mut primitives = Vec::new(); - let cx = super::ctxtkey.get().unwrap(); - match cx.maybe_typed { - core::Typed(ref tcx) => { - csearch::each_top_level_item_of_crate(&tcx.sess.cstore, - self.cnum, - |def, _, _| { - let did = match def { - decoder::DlDef(def::DefMod(did)) => did, - _ => return - }; - let attrs = inline::load_attrs(tcx, did); - match Primitive::find(attrs.as_slice()) { - Some(prim) => primitives.push(prim), - None => {} - } - }); - } - core::NotTyped(..) => {} - } + get_cx().tcx_opt().map(|tcx| { + csearch::each_top_level_item_of_crate(&tcx.sess.cstore, + self.cnum, + |def, _, _| { + let did = match def { + decoder::DlDef(def::DefMod(did)) => did, + _ => return + }; + let attrs = inline::load_attrs(tcx, did); + Primitive::find(attrs.as_slice()).map(|prim| primitives.push(prim)); + }) + }); ExternalCrate { name: self.name.to_string(), attrs: decoder::get_crate_attributes(self.data()).clean(), @@ -233,6 +239,7 @@ pub struct Item { pub inner: ItemEnum, pub visibility: Option, pub def_id: ast::DefId, + pub stability: Option, } impl Item { @@ -380,6 +387,7 @@ impl Clean for doctree::Module { attrs: self.attrs.clean(), source: where.clean(), visibility: self.vis.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: ModuleItem(Module { is_crate: self.is_crate, @@ -465,9 +473,8 @@ impl Clean for ast::TyParam { impl Clean for ty::TypeParameterDef { fn clean(&self) -> TyParam { - let cx = super::ctxtkey.get().unwrap(); - cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id, - self.ident.clean()); + get_cx().external_typarams.borrow_mut().get_mut_ref() + .insert(self.def_id, self.ident.clean()); TyParam { name: self.ident.clean(), did: self.def_id, @@ -515,7 +522,7 @@ fn external_path(name: &str, substs: &subst::Substs) -> Path { impl Clean for ty::BuiltinBound { fn clean(&self) -> TyParamBound { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let tcx = match cx.maybe_typed { core::Typed(ref tcx) => tcx, core::NotTyped(_) => return RegionBound, @@ -550,7 +557,7 @@ impl Clean for ty::BuiltinBound { impl Clean for ty::TraitRef { fn clean(&self) -> TyParamBound { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let tcx = match cx.maybe_typed { core::Typed(ref tcx) => tcx, core::NotTyped(_) => return RegionBound, @@ -709,8 +716,9 @@ impl Clean for ast::Method { name: Some(self.ident.clean()), attrs: self.attrs.clean().move_iter().collect(), source: self.span.clean(), - def_id: ast_util::local_def(self.id.clone()), + def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: get_stability(ast_util::local_def(self.id)), inner: MethodItem(Method { generics: self.generics.clean(), self_: self.explicit_self.node.clean(), @@ -749,6 +757,7 @@ impl Clean for ast::TypeMethod { source: self.span.clean(), def_id: ast_util::local_def(self.id), visibility: None, + stability: get_stability(ast_util::local_def(self.id)), inner: TyMethodItem(TyMethod { fn_style: self.fn_style.clone(), decl: decl, @@ -792,6 +801,7 @@ impl Clean for doctree::Function { attrs: self.attrs.clean(), source: self.where.clean(), visibility: self.vis.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: FunctionItem(Function { decl: self.decl.clean(), @@ -854,14 +864,10 @@ impl Clean for ast::FnDecl { impl<'a> Clean for (ast::DefId, &'a ty::FnSig) { fn clean(&self) -> FnDecl { - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tcx) => tcx, - core::NotTyped(_) => unreachable!(), - }; + let cx = get_cx(); let (did, sig) = *self; let mut names = if did.node != 0 { - csearch::get_method_arg_names(&tcx.sess.cstore, did).move_iter() + csearch::get_method_arg_names(&cx.tcx().sess.cstore, did).move_iter() } else { Vec::new().move_iter() }.peekable(); @@ -932,6 +938,7 @@ impl Clean for doctree::Trait { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: TraitItem(Trait { methods: self.methods.clean(), generics: self.generics.clean(), @@ -985,11 +992,7 @@ impl Clean for ast::TraitMethod { impl Clean for ty::Method { fn clean(&self) -> Item { - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tcx) => tcx, - core::NotTyped(_) => unreachable!(), - }; + let cx = get_cx(); let (self_, sig) = match self.explicit_self { ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()), s => { @@ -1015,8 +1018,9 @@ impl Clean for ty::Method { Item { name: Some(self.ident.clean()), visibility: Some(ast::Inherited), + stability: get_stability(self.def_id), def_id: self.def_id, - attrs: inline::load_attrs(tcx, self.def_id), + attrs: inline::load_attrs(cx.tcx(), self.def_id), source: Span::empty(), inner: TyMethodItem(TyMethod { fn_style: self.fty.fn_style, @@ -1261,12 +1265,7 @@ impl Clean for ty::t { ty::ty_struct(did, ref substs) | ty::ty_enum(did, ref substs) | ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => { - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tycx) => tycx, - core::NotTyped(_) => unreachable!(), - }; - let fqn = csearch::get_item_path(tcx, did); + let fqn = csearch::get_item_path(get_cx().tcx(), did); let fqn: Vec = fqn.move_iter().map(|i| { i.to_str() }).collect(); @@ -1277,8 +1276,8 @@ impl Clean for ty::t { }; let path = external_path(fqn.last().unwrap().to_str().as_slice(), substs); - cx.external_paths.borrow_mut().get_mut_ref().insert(did, - (fqn, kind)); + get_cx().external_paths.borrow_mut().get_mut_ref() + .insert(did, (fqn, kind)); ResolvedPath { path: path, typarams: None, @@ -1318,6 +1317,7 @@ impl Clean for ast::StructField { attrs: self.node.attrs.clean().move_iter().collect(), source: self.span.clean(), visibility: Some(vis), + stability: get_stability(ast_util::local_def(self.node.id)), def_id: ast_util::local_def(self.node.id), inner: StructFieldItem(TypedStructField(self.node.ty.clean())), } @@ -1332,17 +1332,14 @@ impl Clean for ty::field_ty { } else { Some(self.name) }; - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tycx) => tycx, - core::NotTyped(_) => unreachable!(), - }; - let ty = ty::lookup_item_type(tcx, self.id); + let cx = get_cx(); + let ty = ty::lookup_item_type(cx.tcx(), self.id); Item { name: name.clean(), - attrs: inline::load_attrs(tcx, self.id), + attrs: inline::load_attrs(cx.tcx(), self.id), source: Span::empty(), visibility: Some(self.vis), + stability: get_stability(self.id), def_id: self.id, inner: StructFieldItem(TypedStructField(ty.ty.clean())), } @@ -1373,6 +1370,7 @@ impl Clean for doctree::Struct { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: StructItem(Struct { struct_type: self.struct_type, generics: self.generics.clean(), @@ -1418,6 +1416,7 @@ impl Clean for doctree::Enum { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: EnumItem(Enum { variants: self.variants.clean(), generics: self.generics.clean(), @@ -1439,6 +1438,7 @@ impl Clean for doctree::Variant { attrs: self.attrs.clean(), source: self.where.clean(), visibility: self.vis.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: VariantItem(Variant { kind: self.kind.clean(), @@ -1450,11 +1450,7 @@ impl Clean for doctree::Variant { impl Clean for ty::VariantInfo { fn clean(&self) -> Item { // use syntax::parse::token::special_idents::unnamed_field; - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tycx) => tycx, - core::NotTyped(_) => fail!("tcx not present"), - }; + let cx = get_cx(); let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) { None | Some([]) if self.args.len() == 0 => CLikeVariant, None | Some([]) => { @@ -1470,6 +1466,7 @@ impl Clean for ty::VariantInfo { name: Some(name.clean()), attrs: Vec::new(), visibility: Some(ast::Public), + stability: get_stability(self.id), // FIXME: this is not accurate, we need an id for // the specific field but we're using the id // for the whole variant. Nothing currently @@ -1485,11 +1482,12 @@ impl Clean for ty::VariantInfo { }; Item { name: Some(self.name.clean()), - attrs: inline::load_attrs(tcx, self.id), + attrs: inline::load_attrs(cx.tcx(), self.id), source: Span::empty(), visibility: Some(ast::Public), def_id: self.id, inner: VariantItem(Variant { kind: kind }), + stability: None, } } } @@ -1626,6 +1624,7 @@ impl Clean for doctree::Typedef { source: self.where.clean(), def_id: ast_util::local_def(self.id.clone()), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: TypedefItem(Typedef { type_: self.ty.clean(), generics: self.gen.clean(), @@ -1675,6 +1674,7 @@ impl Clean for doctree::Static { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: StaticItem(Static { type_: self.type_.clean(), mutability: self.mutability.clean(), @@ -1720,6 +1720,7 @@ impl Clean for doctree::Impl { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: ImplItem(Impl { generics: self.generics.clean(), trait_: self.trait_.clean(), @@ -1754,6 +1755,7 @@ impl Clean> for ast::ViewItem { source: self.span.clean(), def_id: ast_util::local_def(0), visibility: self.vis.clean(), + stability: None, inner: ViewItemItem(ViewItem { inner: node.clean() }), } }; @@ -1895,6 +1897,7 @@ impl Clean for ast::ForeignItem { source: self.span.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: None, inner: inner, } } @@ -1977,7 +1980,7 @@ fn name_from_pat(p: &ast::Pat) -> String { /// Given a Type, resolve it using the def_map fn resolve_type(path: Path, tpbs: Option>, id: ast::NodeId) -> Type { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let tycx = match cx.maybe_typed { core::Typed(ref tycx) => tycx, // If we're extracting tests, this return value doesn't matter. @@ -2012,7 +2015,7 @@ fn resolve_type(path: Path, tpbs: Option>, def::DefTyParamBinder(i) => return TyParamBinder(i), _ => {} }; - let did = register_def(&**cx, def); + let did = register_def(&*cx, def); ResolvedPath { path: path, typarams: tpbs, did: did } } @@ -2051,13 +2054,9 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource { } fn resolve_def(id: ast::NodeId) -> Option { - let cx = super::ctxtkey.get().unwrap(); - match cx.maybe_typed { - core::Typed(ref tcx) => { - tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def)) - } - core::NotTyped(_) => None - } + get_cx().tcx_opt().and_then(|tcx| { + tcx.def_map.borrow().find(&id).map(|&def| register_def(&*get_cx(), def)) + }) } #[deriving(Clone, Encodable, Decodable)] @@ -2072,6 +2071,7 @@ impl Clean for doctree::Macro { attrs: self.attrs.clean(), source: self.where.clean(), visibility: ast::Public.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: MacroItem(Macro { source: self.where.to_src(), @@ -2079,3 +2079,19 @@ impl Clean for doctree::Macro { } } } + +#[deriving(Clone, Encodable, Decodable)] +pub struct Stability { + pub level: attr::StabilityLevel, + pub text: String +} + +impl Clean for attr::Stability { + fn clean(&self) -> Stability { + Stability { + level: self.level, + text: self.text.as_ref().map_or("".to_string(), + |interned| interned.get().to_string()), + } + } +} diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ba0161da7e664..245b2d162a77b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,7 +10,7 @@ use rustc; use rustc::{driver, middle}; -use rustc::middle::privacy; +use rustc::middle::{privacy, ty}; use rustc::lint; use syntax::ast; @@ -26,6 +26,7 @@ use visit_ast::RustdocVisitor; use clean; use clean::Clean; +/// Are we generating documentation (`Typed`) or tests (`NotTyped`)? pub enum MaybeTyped { Typed(middle::ty::ctxt), NotTyped(driver::session::Session) @@ -52,6 +53,18 @@ impl DocContext { NotTyped(ref sess) => sess } } + + pub fn tcx_opt<'a>(&'a self) -> Option<&'a ty::ctxt> { + match self.maybe_typed { + Typed(ref tcx) => Some(tcx), + NotTyped(_) => None + } + } + + pub fn tcx<'a>(&'a self) -> &'a ty::ctxt { + let tcx_opt = self.tcx_opt(); + tcx_opt.expect("tcx not present") + } } pub struct CrateAnalysis { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index b8a2a6195b7a5..313f1c81c79e8 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -14,6 +14,7 @@ use syntax; use syntax::codemap::Span; use syntax::ast; +use syntax::attr; use syntax::ast::{Ident, NodeId}; use std::gc::Gc; @@ -32,6 +33,7 @@ pub struct Module { pub statics: Vec, pub traits: Vec, pub vis: ast::Visibility, + pub stab: Option, pub impls: Vec, pub foreigns: Vec, pub view_items: Vec, @@ -45,6 +47,7 @@ impl Module { name : name, id: 0, vis: ast::Inherited, + stab: None, where_outer: syntax::codemap::DUMMY_SP, where_inner: syntax::codemap::DUMMY_SP, attrs : Vec::new(), @@ -83,6 +86,7 @@ pub enum TypeBound { pub struct Struct { pub vis: ast::Visibility, + pub stab: Option, pub id: NodeId, pub struct_type: StructType, pub name: Ident, @@ -94,6 +98,7 @@ pub struct Struct { pub struct Enum { pub vis: ast::Visibility, + pub stab: Option, pub variants: Vec, pub generics: ast::Generics, pub attrs: Vec, @@ -108,6 +113,7 @@ pub struct Variant { pub kind: ast::VariantKind, pub id: ast::NodeId, pub vis: ast::Visibility, + pub stab: Option, pub where: Span, } @@ -117,6 +123,7 @@ pub struct Function { pub id: NodeId, pub name: Ident, pub vis: ast::Visibility, + pub stab: Option, pub fn_style: ast::FnStyle, pub where: Span, pub generics: ast::Generics, @@ -130,6 +137,7 @@ pub struct Typedef { pub attrs: Vec, pub where: Span, pub vis: ast::Visibility, + pub stab: Option, } pub struct Static { @@ -139,6 +147,7 @@ pub struct Static { pub name: Ident, pub attrs: Vec, pub vis: ast::Visibility, + pub stab: Option, pub id: ast::NodeId, pub where: Span, } @@ -152,6 +161,7 @@ pub struct Trait { pub id: ast::NodeId, pub where: Span, pub vis: ast::Visibility, + pub stab: Option, } pub struct Impl { @@ -162,6 +172,7 @@ pub struct Impl { pub attrs: Vec, pub where: Span, pub vis: ast::Visibility, + pub stab: Option, pub id: ast::NodeId, } @@ -170,6 +181,7 @@ pub struct Macro { pub id: ast::NodeId, pub attrs: Vec, pub where: Span, + pub stab: Option, } pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType { diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs new file mode 100644 index 0000000000000..0931f132c0214 --- /dev/null +++ b/src/librustdoc/externalfiles.rs @@ -0,0 +1,70 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{io, str}; + +#[deriving(Clone)] +pub struct ExternalHtml{ + pub in_header: String, + pub before_content: String, + pub after_content: String +} + +impl ExternalHtml { + pub fn load(in_header: &[String], before_content: &[String], after_content: &[String]) + -> Option { + match (load_external_files(in_header), + load_external_files(before_content), + load_external_files(after_content)) { + (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml { + in_header: ih, + before_content: bc, + after_content: ac + }), + _ => None + } + } +} + +pub fn load_string(input: &Path) -> io::IoResult> { + let mut f = try!(io::File::open(input)); + let d = try!(f.read_to_end()); + Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string())) +} + +macro_rules! load_or_return { + ($input: expr, $cant_read: expr, $not_utf8: expr) => { + { + let input = Path::new($input); + match ::externalfiles::load_string(&input) { + Err(e) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: {}", input.display(), e); + return $cant_read; + } + Ok(None) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: not UTF-8", input.display()); + return $not_utf8; + } + Ok(Some(s)) => s + } + } + } +} + +pub fn load_external_files(names: &[String]) -> Option { + let mut out = String::new(); + for name in names.iter() { + out.push_str(load_or_return!(name.as_slice(), None, None).as_slice()); + out.push_char('\n'); + } + Some(out) +} diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 800e7f065f1e6..f07c016367634 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -104,7 +104,7 @@ mod imp { l_sysid: 0, }; let ret = unsafe { - libc::fcntl(fd, os::F_SETLKW, &flock as *os::flock) + libc::fcntl(fd, os::F_SETLKW, &flock as *const os::flock) }; if ret == -1 { unsafe { libc::close(fd); } @@ -125,7 +125,7 @@ mod imp { l_sysid: 0, }; unsafe { - libc::fcntl(self.fd, os::F_SETLK, &flock as *os::flock); + libc::fcntl(self.fd, os::F_SETLK, &flock as *const os::flock); libc::close(self.fd); } } @@ -162,7 +162,8 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let p_16 = p.as_str().unwrap().to_utf16().append_one(0); + let p_16: Vec = p.as_str().unwrap().utf16_units().collect(); + let p_16 = p_16.append_one(0); let handle = unsafe { libc::CreateFileW(p_16.as_ptr(), libc::FILE_GENERIC_READ | diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 77b12aec97b41..60853f450ab32 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -19,7 +19,7 @@ pub trait DocFolder { /// don't override! fn fold_item_recur(&mut self, item: Item) -> Option { - let Item { attrs, name, source, visibility, def_id, inner } = item; + let Item { attrs, name, source, visibility, def_id, inner, stability } = item; let inner = inner; let inner = match inner { StructItem(mut i) => { @@ -83,7 +83,7 @@ pub trait DocFolder { }; Some(Item { attrs: attrs, name: name, source: source, inner: inner, - visibility: visibility, def_id: def_id }) + visibility: visibility, stability: stability, def_id: def_id }) } fn fold_mod(&mut self, m: Module) -> Module { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 1173f6eb5b8b4..9677b9004cdf1 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -37,6 +37,10 @@ pub struct FnStyleSpace(pub ast::FnStyle); pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); /// Similar to VisSpace, but used for mutability pub struct MutableSpace(pub clean::Mutability); +/// Wrapper struct for properly emitting the stability level. +pub struct Stability<'a>(pub &'a Option); +/// Wrapper struct for emitting the stability level concisely. +pub struct ConciseStability<'a>(pub &'a Option); impl VisSpace { pub fn get(&self) -> Option { @@ -185,7 +189,7 @@ fn path(w: &mut fmt::Formatter, path: &clean::Path, print_all: bool, let mut generics = String::new(); let last = path.segments.last().unwrap(); if last.lifetimes.len() > 0 || last.types.len() > 0 { - let mut counter = 0; + let mut counter = 0u; generics.push_str("<"); for lifetime in last.lifetimes.iter() { if counter > 0 { generics.push_str(", "); } @@ -596,3 +600,34 @@ impl fmt::Show for MutableSpace { } } } + +impl<'a> fmt::Show for Stability<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Stability(stab) = *self; + match *stab { + Some(ref stability) => { + write!(f, "{lvl}", + lvl = stability.level.to_str(), + reason = stability.text) + } + None => Ok(()) + } + } +} + +impl<'a> fmt::Show for ConciseStability<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ConciseStability(stab) = *self; + match *stab { + Some(ref stability) => { + write!(f, "", + lvl = stability.level.to_str(), + colon = if stability.text.len() > 0 { ": " } else { "" }, + reason = stability.text) + } + None => { + write!(f, "") + } + } + } +} diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 61a2d3c5d9cc8..aa298d07780bf 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -11,10 +11,13 @@ use std::fmt; use std::io; +use externalfiles::ExternalHtml; + #[deriving(Clone)] pub struct Layout { pub logo: String, pub favicon: String, + pub external_html: ExternalHtml, pub krate: String, pub playground_url: String, } @@ -44,6 +47,7 @@ r##" {favicon} + {in_header} + {before_content} +