]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15310 : pcwalton/rust/tests-for-12223, r=brson
authorbors <bors@rust-lang.org>
Wed, 2 Jul 2014 12:06:34 +0000 (12:06 +0000)
committerbors <bors@rust-lang.org>
Wed, 2 Jul 2014 12:06:34 +0000 (12:06 +0000)
still in scope".

This issue was fixed by PR #12828 and #5781. All that was left was to
add tests.

Closes #12223.

43 files changed:
src/doc/guide.md
src/doc/intro.md
src/etc/licenseck.py
src/etc/vim/syntax/rust.vim
src/liballoc/rc.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcore/str.rs
src/libgetopts/lib.rs
src/libnative/io/net.rs
src/librustc/back/link.rs
src/librustc/metadata/decoder.rs
src/librustc/middle/dead.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/librustrt/rtio.rs
src/librustuv/homing.rs
src/librustuv/net.rs
src/libstd/collections/hashmap.rs
src/libstd/hash.rs [new file with mode: 0644]
src/libstd/io/fs.rs
src/libstd/io/net/udp.rs
src/libstd/lib.rs
src/libstd/path/windows.rs
src/libsyntax/diagnostic.rs
src/libsyntax/parse/lexer/mod.rs
src/libtime/lib.rs
src/libuuid/lib.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-mandelbrot.rs
src/test/compile-fail/integral-indexing.rs
src/test/compile-fail/str-idx.rs [new file with mode: 0644]
src/test/run-fail/str-overrun.rs
src/test/run-pass/estr-slice.rs
src/test/run-pass/estr-uniq.rs
src/test/run-pass/issue-11205.rs [new file with mode: 0644]
src/test/run-pass/str-concat.rs
src/test/run-pass/str-idx.rs [deleted file]
src/test/run-pass/task-comm-16.rs
src/test/run-pass/trait-bounds-in-arc.rs
src/test/run-pass/utf8.rs

index 4577c5a86d77582d18c8f9bf19e243d1a6ddb439..0fc9671c4db292c4bcc05baa38eea38c1a52c261 100644 (file)
@@ -413,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!
+<std macros>:2:23: 2:77 note: expansion site
+<std macros>: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
 
@@ -451,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
index 10fd39c841bd658e12062378e33883945b1637ac..e8928cb55056c519d65faa4d65d8c220eba5fd46 100644 (file)
@@ -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'
index c2f56c6a807091386da84c035b90583d7e39e99c..2110f19bf86d1c27cf657ed4ed1ecd9a85ce34f8 100644 (file)
@@ -44,6 +44,7 @@ exceptions = [
     "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
index d8f00ac6b30facb057958d4dcbcefdef9e474912..a15bd3ca60ff1c7e484b10e1997a1fb525a8bd09 100644 (file)
@@ -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
 
index 83cc4a0b6620df31d0a83f73a03b7ba2ff92b9b4..d97bce39c2de947693943229e618881f7bd5bfe7 100644 (file)
@@ -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.
 //
 
 /*! 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<Owner>
+    // ...other fields
+}
+
+fn main() {
+    // Create a reference counted Owner.
+    let gadget_owner : Rc<Owner> = 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<Vec<Weak<Gadget>>>
+    // ...other fields
+}
+
+struct Gadget {
+    id: int,
+    owner: Rc<Owner>
+    // ...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<Owner> = 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<Gadget>.  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.
+}
+```
 
 */
 
index aa2b38cfa9ddc5543a3f17f5f5b15ebfe25e80f5..fd8ce11d0b5a4bfdfc0256a830edff57445a8229 100644 (file)
@@ -1569,8 +1569,8 @@ fn vec_str_conversions() {
         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);
index 6d1fc43a4f1fd2d1e4b44799bbaa132ea6fd7c42..936e60388a66ae8223cca470b4f837d626399bfc 100644 (file)
@@ -222,7 +222,7 @@ pub unsafe fn pop_byte(&mut self) -> Option<u8> {
             return None
         }
 
-        let byte = self.as_slice()[len - 1];
+        let byte = self.as_bytes()[len - 1];
         self.vec.set_len(len - 1);
         Some(byte)
     }
index b336c57efa07228ad8d6d54518b3e6af46904079..94df7a5a6c2d9c7548a089e8e949fbc32936f226 100644 (file)
@@ -1743,7 +1743,7 @@ fn lines(&self) -> CharSplits<'a, char> {
     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 }
         })
     }
@@ -1867,26 +1867,26 @@ fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &'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};
         }
@@ -1899,23 +1899,25 @@ fn char_range_at_reverse(&self, start: uint) -> CharRange {
         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};
         }
index 240f5c007fa24290f372e87e451bac1796cb9bfe..0e525bc46e7c8b124226b32c65210d6ed3f4afca 100644 (file)
@@ -370,7 +370,7 @@ pub fn opt_default(&self, nm: &str, def: &str) -> Option<String> {
 }
 
 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<uint> {
@@ -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 {
index 395c063e706f11d8494d11fa36901ebd2815f9a6..dfc2c55cde7cb511bb79303ed6942d7b69f1572f 100644 (file)
@@ -630,7 +630,7 @@ fn socket_name(&mut self) -> IoResult<rtio::SocketAddr> {
 #[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,7 +652,7 @@ fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
         })
     }
 
-    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 *const _ as *const libc::sockaddr;
         let dstlen = dstlen as libc::socklen_t;
index b4af291b7eae67ae4275bf7fba70449fb6decde7..17f29639601dd72455e0e7e38202970df8f3a298 100644 (file)
@@ -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(),
index f5ce8cda8c4a6d1b35f00a77c4304701a74e263e..78a29b52bdf5bc45974f05b5adf5bfe4ffc7d88b 100644 (file)
@@ -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_mutability(ch: u8) -> ast::Mutability {
     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)
     }
 }
index 156b8840067720b29fe8b29112d19e304fb24098..e7457f370d9adea16253276cb4fa5bc0b9224758 100644 (file)
@@ -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);
index 77cb5f667fd000c9b7fbe57655718d4181ea901c..5c09466cd96820bdfb686760caf70ba973302ba7 100644 (file)
@@ -1511,7 +1511,7 @@ fn check_lvalue(&mut self, expr: &Expr) {
 
     fn should_warn(&self, var: Variable) -> Option<String> {
         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)
index d26ccc40d3ac11d9421b9a37e0ce7b500e74d961..e1a2a5741fbe1b0d0e03ba62c41dd7666e647f6e 100644 (file)
@@ -126,7 +126,6 @@ pub enum FieldName {
 #[deriving(Clone, PartialEq, Eq, Hash)]
 pub enum ElementKind {
     VecElement,
-    StrElement,
     OtherElement,
 }
 
@@ -794,7 +793,7 @@ pub fn cat_index<N:ast_node>(&self,
         //! - `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 @@ pub fn cmt_to_str(&self, cmt: &cmt_) -> String {
           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,
index 8d84d089c01b2adff75514cf313a74df9196d7b6..79630be7c5e0840c21dfdf99228ed5bbede7f7ac 100644 (file)
@@ -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<mt> {
 
 // Returns the type of t[i]
 pub fn index(t: t) -> Option<mt> {
+    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<mt> {
     match get(t).sty {
         ty_vec(mt, Some(_)) => Some(mt),
         ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
index d808120db99ba8cad928fc1c117fe373db489580..5e675242688afc435f02b86f6bbdf33bac92d93d 100644 (file)
@@ -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
@@ -2779,10 +2764,30 @@ fn check_struct_enum_variant(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_struct_enum_variant(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_struct_enum_variant(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_struct_enum_variant(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_struct_enum_variant(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);
index a68d453b77d89e48011f826e883dfcc0e6e5abd8..0205f2405f9ce8e1345f214a103e39fad5cde3b3 100644 (file)
@@ -269,8 +269,8 @@ pub trait RtioSocket {
 }
 
 pub trait RtioUdpSocket : RtioSocket {
-    fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
-    fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
+    fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
+    fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
 
     fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
     fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
index 644ac4e45f6569e62ee82b890fd0f23d3898e5a0..91614763ce52f4ed669fe0a7c25dd367ef0f2451 100644 (file)
@@ -197,13 +197,13 @@ fn test_homing_read() {
             let listener = UdpWatcher::bind(local_loop(), addr2);
             tx.send((listener.unwrap(), addr1));
             let mut listener = UdpWatcher::bind(local_loop(), addr1).unwrap();
-            listener.sendto([1, 2, 3, 4], addr2).ok().unwrap();
+            listener.send_to([1, 2, 3, 4], addr2).ok().unwrap();
         });
 
         let task = pool.task(TaskOpts::new(), proc() {
             let (mut watcher, addr) = rx.recv();
             let mut buf = [0, ..10];
-            assert!(watcher.recvfrom(buf).ok().unwrap() == (4, addr));
+            assert!(watcher.recv_from(buf).ok().unwrap() == (4, addr));
         });
         pool.spawn_sched().send(sched::TaskFromFriend(task));
 
index edecb8475e9d136b285d31481d224784086899a8..ddcaeccbc190f9927235259a31b0f3fddba16032 100644 (file)
@@ -540,7 +540,7 @@ fn socket_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
 }
 
 impl rtio::RtioUdpSocket for UdpWatcher {
-    fn recvfrom(&mut self, buf: &mut [u8])
+    fn recv_from(&mut self, buf: &mut [u8])
         -> Result<(uint, rtio::SocketAddr), IoError>
     {
         let loop_ = self.uv_loop();
@@ -607,7 +607,7 @@ fn recvfrom(&mut self, buf: &mut [u8])
         }
     }
 
-    fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
+    fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
         let m = self.fire_homing_missile();
         let loop_ = self.uv_loop();
         let guard = try!(self.write_access.grant(m));
@@ -960,7 +960,7 @@ fn udp_recv_ip4() {
                 Ok(mut w) => {
                     tx.send(());
                     let mut buf = [0u8, ..10];
-                    match w.recvfrom(buf) {
+                    match w.recv_from(buf) {
                         Ok((10, addr)) => assert!(addr == client),
                         e => fail!("{:?}", e),
                     }
@@ -976,7 +976,7 @@ fn udp_recv_ip4() {
         let mut w = match UdpWatcher::bind(local_loop(), client) {
             Ok(w) => w, Err(e) => fail!("{:?}", e)
         };
-        match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
+        match w.send_to([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
             Ok(()) => {}, Err(e) => fail!("{:?}", e)
         }
     }
@@ -992,7 +992,7 @@ fn udp_recv_ip6() {
                 Ok(mut w) => {
                     tx.send(());
                     let mut buf = [0u8, ..10];
-                    match w.recvfrom(buf) {
+                    match w.recv_from(buf) {
                         Ok((10, addr)) => assert!(addr == client),
                         e => fail!("{:?}", e),
                     }
@@ -1008,7 +1008,7 @@ fn udp_recv_ip6() {
         let mut w = match UdpWatcher::bind(local_loop(), client) {
             Ok(w) => w, Err(e) => fail!("{:?}", e)
         };
-        match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
+        match w.send_to([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
             Ok(()) => {}, Err(e) => fail!("{:?}", e)
         }
     }
@@ -1057,16 +1057,16 @@ fn test_udp_twice() {
         spawn(proc() {
             let mut client = UdpWatcher::bind(local_loop(), client_addr).unwrap();
             rx.recv();
-            assert!(client.sendto([1], server_addr).is_ok());
-            assert!(client.sendto([2], server_addr).is_ok());
+            assert!(client.send_to([1], server_addr).is_ok());
+            assert!(client.send_to([2], server_addr).is_ok());
         });
 
         let mut server = UdpWatcher::bind(local_loop(), server_addr).unwrap();
         tx.send(());
         let mut buf1 = [0];
         let mut buf2 = [0];
-        let (nread1, src1) = server.recvfrom(buf1).ok().unwrap();
-        let (nread2, src2) = server.recvfrom(buf2).ok().unwrap();
+        let (nread1, src1) = server.recv_from(buf1).ok().unwrap();
+        let (nread2, src2) = server.recv_from(buf2).ok().unwrap();
         assert_eq!(nread1, 1);
         assert_eq!(nread2, 1);
         assert!(src1 == client_addr);
@@ -1098,10 +1098,10 @@ fn test_udp_many_read() {
             let mut buf = [1];
             while buf[0] == 1 {
                 // send more data
-                assert!(server_out.sendto(msg, client_in_addr).is_ok());
+                assert!(server_out.send_to(msg, client_in_addr).is_ok());
                 total_bytes_sent += msg.len();
                 // check if the client has received enough
-                let res = server_in.recvfrom(buf);
+                let res = server_in.recv_from(buf);
                 assert!(res.is_ok());
                 let (nread, src) = res.ok().unwrap();
                 assert_eq!(nread, 1);
@@ -1120,9 +1120,9 @@ fn test_udp_many_read() {
         let mut buf = [0, .. 2048];
         while total_bytes_recv < MAX {
             // ask for more
-            assert!(client_out.sendto([1], server_in_addr).is_ok());
+            assert!(client_out.send_to([1], server_in_addr).is_ok());
             // wait for data
-            let res = client_in.recvfrom(buf);
+            let res = client_in.recv_from(buf);
             assert!(res.is_ok());
             let (nread, src) = res.ok().unwrap();
             assert!(src == server_out_addr);
@@ -1132,7 +1132,7 @@ fn test_udp_many_read() {
             }
         }
         // tell the server we're done
-        assert!(client_out.sendto([0], server_in_addr).is_ok());
+        assert!(client_out.send_to([0], server_in_addr).is_ok());
     }
 
     #[test]
index b94141748d57fe2561cc14a4a20fb43ace1338ca..7c01a0342edc71b30bbcaf89597f1bfc10240b4c 100644 (file)
 use default::Default;
 use fmt::Show;
 use fmt;
-use hash::{Hash, Hasher, sip};
+use hash::{Hash, Hasher, RandomSipHasher};
 use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable};
 use iter::{range, range_inclusive, FromIterator};
 use iter;
 use mem::replace;
 use num;
 use option::{Some, None, Option};
-use rand::Rng;
-use rand;
 use result::{Ok, Err};
 
 mod table {
@@ -733,7 +731,7 @@ fn reserve(&mut self, new_capacity: uint) {
 /// }
 /// ```
 #[deriving(Clone)]
-pub struct HashMap<K, V, H = sip::SipHasher> {
+pub struct HashMap<K, V, H = RandomSipHasher> {
     // All hashes are keyed on these values, to prevent hash collision attacks.
     hasher: H,
 
@@ -1033,18 +1031,17 @@ fn pop(&mut self, k: &K) -> Option<V> {
 
 }
 
-impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
+impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
     /// Create an empty HashMap.
-    pub fn new() -> HashMap<K, V, sip::SipHasher> {
+    #[inline]
+    pub fn new() -> HashMap<K, V, RandomSipHasher> {
         HashMap::with_capacity(INITIAL_CAPACITY)
     }
 
     /// Creates an empty hash map with the given initial capacity.
-    pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
-        let mut r = rand::task_rng();
-        let r0 = r.gen();
-        let r1 = r.gen();
-        let hasher = sip::SipHasher::new_with_keys(r0, r1);
+    #[inline]
+    pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> {
+        let hasher = RandomSipHasher::new();
         HashMap::with_capacity_and_hasher(capacity, hasher)
     }
 }
@@ -1053,6 +1050,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// Creates an empty hashmap which will use the given hasher to hash keys.
     ///
     /// The creates map has the default initial capacity.
+    #[inline]
     pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
         HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
@@ -1064,6 +1062,7 @@ pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
     /// is designed to allow HashMaps to be resistant to attacks that
     /// cause many collisions and very poor performance. Setting it
     /// manually using this function can expose a DoS attack vector.
+    #[inline]
     pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
         let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity));
         HashMap {
@@ -1489,7 +1488,7 @@ fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
 /// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
 /// requires that the elements implement the `Eq` and `Hash` traits.
 #[deriving(Clone)]
-pub struct HashSet<T, H = sip::SipHasher> {
+pub struct HashSet<T, H = RandomSipHasher> {
     map: HashMap<T, (), H>
 }
 
@@ -1529,15 +1528,17 @@ fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
     fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
 }
 
-impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
+impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
     /// Create an empty HashSet
-    pub fn new() -> HashSet<T, sip::SipHasher> {
+    #[inline]
+    pub fn new() -> HashSet<T, RandomSipHasher> {
         HashSet::with_capacity(INITIAL_CAPACITY)
     }
 
     /// Create an empty HashSet with space for at least `n` elements in
     /// the hash table.
-    pub fn with_capacity(capacity: uint) -> HashSet<T, sip::SipHasher> {
+    #[inline]
+    pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> {
         HashSet { map: HashMap::with_capacity(capacity) }
     }
 }
@@ -1547,6 +1548,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// keys.
     ///
     /// The hash set is also created with the default initial capacity.
+    #[inline]
     pub fn with_hasher(hasher: H) -> HashSet<T, H> {
         HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
@@ -1558,6 +1560,7 @@ pub fn with_hasher(hasher: H) -> HashSet<T, H> {
     /// is designed to allow `HashSet`s to be resistant to attacks that
     /// cause many collisions and very poor performance. Setting it
     /// manually using this function can expose a DoS attack vector.
+    #[inline]
     pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
         HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
     }
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
new file mode 100644 (file)
index 0000000..2cc7e70
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Generic hashing support.
+ *
+ * This module provides a generic way to compute the hash of a value. The
+ * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
+ *
+ * # Example
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ *
+ * #[deriving(Hash)]
+ * struct Person {
+ *     id: uint,
+ *     name: String,
+ *     phone: u64,
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) != hash::hash(&person2));
+ * ```
+ *
+ * If you need more control over how a value is hashed, you need to implement
+ * the trait `Hash`:
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ * use std::hash::sip::SipState;
+ *
+ * struct Person {
+ *     id: uint,
+ *     name: String,
+ *     phone: u64,
+ * }
+ *
+ * impl Hash for Person {
+ *     fn hash(&self, state: &mut SipState) {
+ *         self.id.hash(state);
+ *         self.phone.hash(state);
+ *     }
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) == hash::hash(&person2));
+ * ```
+ */
+
+pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};
+
+use default::Default;
+use rand::Rng;
+use rand;
+
+/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes
+/// initialized with random keys.
+#[deriving(Clone)]
+pub struct RandomSipHasher {
+    hasher: sip::SipHasher,
+}
+
+impl RandomSipHasher {
+    /// Construct a new `RandomSipHasher` that is initialized with random keys.
+    #[inline]
+    pub fn new() -> RandomSipHasher {
+        let mut r = rand::task_rng();
+        let r0 = r.gen();
+        let r1 = r.gen();
+        RandomSipHasher {
+            hasher: sip::SipHasher::new_with_keys(r0, r1),
+        }
+    }
+}
+
+impl Hasher<sip::SipState> for RandomSipHasher {
+    #[inline]
+    fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
+        self.hasher.hash(value)
+    }
+}
+
+impl Default for RandomSipHasher {
+    #[inline]
+    fn default() -> RandomSipHasher {
+        RandomSipHasher::new()
+    }
+}
index bc8447dfa2ee9dcfc8161f0cb7c9879f38048b64..e7f26c7bd910e5d21d61de30a703734684f9f1a4 100644 (file)
@@ -1206,8 +1206,8 @@ pub fn tmpdir() -> TempDir {
         let mut cur = [0u8, .. 2];
         for f in files {
             let stem = f.filestem_str().unwrap();
-            let root = stem[0] - ('0' as u8);
-            let name = stem[1] - ('0' as u8);
+            let root = stem.as_bytes()[0] - ('0' as u8);
+            let name = stem.as_bytes()[1] - ('0' as u8);
             assert!(cur[root as uint] < name);
             cur[root as uint] = name;
         }
index 5f6de52f86632ba9bfe07267c1bbc82c80935646..cd78898d46bb82c22c73b54f39f8d3a3bfc3e516 100644 (file)
 /// };
 ///
 /// let mut buf = [0, ..10];
-/// match socket.recvfrom(buf) {
+/// match socket.recv_from(buf) {
 ///     Ok((amt, src)) => {
 ///         // Send a reply to the socket we received data from
 ///         let buf = buf.mut_slice_to(amt);
 ///         buf.reverse();
-///         socket.sendto(buf, src);
+///         socket.send_to(buf, src);
 ///     }
 ///     Err(e) => println!("couldn't receive a datagram: {}", e)
 /// }
@@ -72,9 +72,9 @@ pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
 
     /// Receives data from the socket. On success, returns the number of bytes
     /// read and the address from whence the data came.
-    pub fn recvfrom(&mut self, buf: &mut [u8])
+    pub fn recv_from(&mut self, buf: &mut [u8])
                     -> IoResult<(uint, SocketAddr)> {
-        match self.obj.recvfrom(buf) {
+        match self.obj.recv_from(buf) {
             Ok((amt, rtio::SocketAddr { ip, port })) => {
                 Ok((amt, SocketAddr { ip: super::from_rtio(ip), port: port }))
             }
@@ -82,15 +82,28 @@ pub fn recvfrom(&mut self, buf: &mut [u8])
         }
     }
 
+    #[allow(missing_doc)]
+    #[deprecated = "renamed to `recv_from`"]
+    pub fn recvfrom(&mut self, buf: &mut [u8])
+                    -> IoResult<(uint, SocketAddr)> {
+        self.recv_from(buf)
+    }
+
     /// Sends data on the socket to the given address. Returns nothing on
     /// success.
-    pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
-        self.obj.sendto(buf, rtio::SocketAddr {
+    pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
+        self.obj.send_to(buf, rtio::SocketAddr {
             ip: super::to_rtio(dst.ip),
             port: dst.port,
         }).map_err(IoError::from_rtio_error)
     }
 
+    #[allow(missing_doc)]
+    #[deprecated = "renamed to `send_to`"]
+    pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
+        self.send_to(buf, dst)
+    }
+
     /// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
     /// traits to receive and send data from the same address. This transfers
     /// ownership of the socket to the stream.
@@ -225,7 +238,7 @@ impl Reader for UdpStream {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let peer = self.connected_to;
         self.as_socket(|sock| {
-            match sock.recvfrom(buf) {
+            match sock.recv_from(buf) {
                 Ok((_nread, src)) if src != peer => Ok(0),
                 Ok((nread, _src)) => Ok(nread),
                 Err(e) => Err(e),
@@ -237,7 +250,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 impl Writer for UdpStream {
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         let connected_to = self.connected_to;
-        self.as_socket(|sock| sock.sendto(buf, connected_to))
+        self.as_socket(|sock| sock.send_to(buf, connected_to))
     }
 }
 
@@ -266,7 +279,7 @@ mod test {
             match UdpSocket::bind(client_ip) {
                 Ok(ref mut client) => {
                     rx1.recv();
-                    client.sendto([99], server_ip).unwrap()
+                    client.send_to([99], server_ip).unwrap()
                 }
                 Err(..) => fail!()
             }
@@ -277,7 +290,7 @@ mod test {
             Ok(ref mut server) => {
                 tx1.send(());
                 let mut buf = [0];
-                match server.recvfrom(buf) {
+                match server.recv_from(buf) {
                     Ok((nread, src)) => {
                         assert_eq!(nread, 1);
                         assert_eq!(buf[0], 99);
@@ -300,7 +313,7 @@ mod test {
             match UdpSocket::bind(client_ip) {
                 Ok(ref mut client) => {
                     rx.recv();
-                    client.sendto([99], server_ip).unwrap()
+                    client.send_to([99], server_ip).unwrap()
                 }
                 Err(..) => fail!()
             }
@@ -310,7 +323,7 @@ mod test {
             Ok(ref mut server) => {
                 tx.send(());
                 let mut buf = [0];
-                match server.recvfrom(buf) {
+                match server.recv_from(buf) {
                     Ok((nread, src)) => {
                         assert_eq!(nread, 1);
                         assert_eq!(buf[0], 99);
@@ -429,9 +442,9 @@ pub fn socket_name(addr: SocketAddr) {
         spawn(proc() {
             let mut sock2 = sock2;
             let mut buf = [0, 0];
-            assert_eq!(sock2.recvfrom(buf), Ok((1, addr1)));
+            assert_eq!(sock2.recv_from(buf), Ok((1, addr1)));
             assert_eq!(buf[0], 1);
-            sock2.sendto([2], addr1).unwrap();
+            sock2.send_to([2], addr1).unwrap();
         });
 
         let sock3 = sock1.clone();
@@ -441,12 +454,12 @@ pub fn socket_name(addr: SocketAddr) {
         spawn(proc() {
             let mut sock3 = sock3;
             rx1.recv();
-            sock3.sendto([1], addr2).unwrap();
+            sock3.send_to([1], addr2).unwrap();
             tx2.send(());
         });
         tx1.send(());
         let mut buf = [0, 0];
-        assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
+        assert_eq!(sock1.recv_from(buf), Ok((1, addr2)));
         rx2.recv();
     })
 
@@ -460,9 +473,9 @@ pub fn socket_name(addr: SocketAddr) {
 
         spawn(proc() {
             let mut sock2 = sock2;
-            sock2.sendto([1], addr1).unwrap();
+            sock2.send_to([1], addr1).unwrap();
             rx.recv();
-            sock2.sendto([2], addr1).unwrap();
+            sock2.send_to([2], addr1).unwrap();
             rx.recv();
         });
 
@@ -472,12 +485,12 @@ pub fn socket_name(addr: SocketAddr) {
         spawn(proc() {
             let mut sock3 = sock3;
             let mut buf = [0, 0];
-            sock3.recvfrom(buf).unwrap();
+            sock3.recv_from(buf).unwrap();
             tx2.send(());
             done.send(());
         });
         let mut buf = [0, 0];
-        sock1.recvfrom(buf).unwrap();
+        sock1.recv_from(buf).unwrap();
         tx1.send(());
 
         rx.recv();
@@ -497,7 +510,7 @@ pub fn socket_name(addr: SocketAddr) {
             let mut buf = [0, 1];
 
             rx.recv();
-            match sock2.recvfrom(buf) {
+            match sock2.recv_from(buf) {
                 Ok(..) => {}
                 Err(e) => fail!("failed receive: {}", e),
             }
@@ -510,13 +523,13 @@ pub fn socket_name(addr: SocketAddr) {
         let tx2 = tx.clone();
         spawn(proc() {
             let mut sock3 = sock3;
-            match sock3.sendto([1], addr2) {
+            match sock3.send_to([1], addr2) {
                 Ok(..) => { let _ = tx2.send_opt(()); }
                 Err(..) => {}
             }
             done.send(());
         });
-        match sock1.sendto([2], addr2) {
+        match sock1.send_to([2], addr2) {
             Ok(..) => { let _ = tx.send_opt(()); }
             Err(..) => {}
         }
@@ -526,7 +539,7 @@ pub fn socket_name(addr: SocketAddr) {
         serv_rx.recv();
     })
 
-    iotest!(fn recvfrom_timeout() {
+    iotest!(fn recv_from_timeout() {
         let addr1 = next_test_ip4();
         let addr2 = next_test_ip4();
         let mut a = UdpSocket::bind(addr1).unwrap();
@@ -535,34 +548,34 @@ pub fn socket_name(addr: SocketAddr) {
         let (tx2, rx2) = channel();
         spawn(proc() {
             let mut a = UdpSocket::bind(addr2).unwrap();
-            assert_eq!(a.recvfrom([0]), Ok((1, addr1)));
-            assert_eq!(a.sendto([0], addr1), Ok(()));
+            assert_eq!(a.recv_from([0]), Ok((1, addr1)));
+            assert_eq!(a.send_to([0], addr1), Ok(()));
             rx.recv();
-            assert_eq!(a.sendto([0], addr1), Ok(()));
+            assert_eq!(a.send_to([0], addr1), Ok(()));
 
             tx2.send(());
         });
 
         // Make sure that reads time out, but writes can continue
         a.set_read_timeout(Some(20));
-        assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
-        assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
-        assert_eq!(a.sendto([0], addr2), Ok(()));
+        assert_eq!(a.recv_from([0]).err().unwrap().kind, TimedOut);
+        assert_eq!(a.recv_from([0]).err().unwrap().kind, TimedOut);
+        assert_eq!(a.send_to([0], addr2), Ok(()));
 
         // Cloned handles should be able to block
         let mut a2 = a.clone();
-        assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+        assert_eq!(a2.recv_from([0]), Ok((1, addr2)));
 
         // Clearing the timeout should allow for receiving
         a.set_timeout(None);
         tx.send(());
-        assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+        assert_eq!(a2.recv_from([0]), Ok((1, addr2)));
 
         // Make sure the child didn't die
         rx2.recv();
     })
 
-    iotest!(fn sendto_timeout() {
+    iotest!(fn send_to_timeout() {
         let addr1 = next_test_ip4();
         let addr2 = next_test_ip4();
         let mut a = UdpSocket::bind(addr1).unwrap();
@@ -570,7 +583,7 @@ pub fn socket_name(addr: SocketAddr) {
 
         a.set_write_timeout(Some(1000));
         for _ in range(0u, 100) {
-            match a.sendto([0, ..4*1024], addr2) {
+            match a.send_to([0, ..4*1024], addr2) {
                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
                 Err(IoError { kind: TimedOut, .. }) => break,
                 Err(e) => fail!("other error: {}", e),
index 48ccd1aa22ce3be3b18f6d517b8816aec688f4b2..06a1d069b6a72b25f9a75eae9c489a88b8545bd4 100644 (file)
 pub use alloc::owned;
 pub use alloc::rc;
 
-pub use core_collections::hash;
 pub use core_collections::slice;
 pub use core_collections::str;
 pub use core_collections::string;
@@ -237,6 +236,7 @@ fn start(argc: int, argv: *const *const u8) -> int {
 /* Common data structures */
 
 pub mod collections;
+pub mod hash;
 
 /* Tasks and communication */
 
index ec225a588fcc18bfb24616b9da80b6cf69eb6907..113b0410875af7ad0d068d0b394554320715de96 100644 (file)
@@ -242,14 +242,18 @@ unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
         fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
             // assume prefix is Some(DiskPrefix)
             let rest = path.slice_from(prefix_len(prefix));
-            !rest.is_empty() && rest[0].is_ascii() && is_sep(rest[0] as char)
+            !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char)
         }
         fn shares_volume(me: &Path, path: &str) -> bool {
             // path is assumed to have a prefix of Some(DiskPrefix)
             let repr = me.repr.as_slice();
             match me.prefix {
-                Some(DiskPrefix) => repr[0] == path[0].to_ascii().to_upper().to_byte(),
-                Some(VerbatimDiskPrefix) => repr[4] == path[0].to_ascii().to_upper().to_byte(),
+                Some(DiskPrefix) => {
+                    repr.as_bytes()[0] == path.as_bytes()[0].to_ascii().to_upper().to_byte()
+                }
+                Some(VerbatimDiskPrefix) => {
+                    repr.as_bytes()[4] == path.as_bytes()[0].to_ascii().to_upper().to_byte()
+                }
                 _ => false
             }
         }
@@ -279,7 +283,7 @@ fn append_path(me: &mut Path, path: &str) {
             // if me is "C:" we don't want to add a path separator
             match me.prefix {
                 Some(DiskPrefix) if me.repr.len() == plen => (),
-                _ if !(me.repr.len() > plen && me.repr.as_slice()[me.repr.len()-1] == SEP_BYTE) => {
+                _ if !(me.repr.len() > plen && me.repr.as_bytes()[me.repr.len()-1] == SEP_BYTE) => {
                     s.push_char(SEP);
                 }
                 _ => ()
@@ -302,7 +306,7 @@ fn append_path(me: &mut Path, path: &str) {
                     // absolute path, or cwd-relative and self is not same volume
                     replace_path(self, path, prefix);
                 }
-                None if !path.is_empty() && is_sep_(self.prefix, path[0]) => {
+                None if !path.is_empty() && is_sep_(self.prefix, path.as_bytes()[0]) => {
                     // volume-relative path
                     if self.prefix.is_some() {
                         // truncate self down to the prefix, then append
@@ -478,7 +482,7 @@ fn is_absolute(&self) -> bool {
         match self.prefix {
             Some(DiskPrefix) => {
                 let rest = self.repr.as_slice().slice_from(self.prefix_len());
-                rest.len() > 0 && rest[0] == SEP_BYTE
+                rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE
             }
             Some(_) => true,
             None => false
@@ -638,11 +642,11 @@ pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
         let s = match self.prefix {
             Some(_) => {
                 let plen = self.prefix_len();
-                if repr.len() > plen && repr[plen] == SEP_BYTE {
+                if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE {
                     repr.slice_from(plen+1)
                 } else { repr.slice_from(plen) }
             }
-            None if repr[0] == SEP_BYTE => repr.slice_from(1),
+            None if repr.as_bytes()[0] == SEP_BYTE => repr.slice_from(1),
             None => repr
         };
         let ret = s.split_terminator(SEP).map(Some);
@@ -665,14 +669,14 @@ fn equiv_prefix(&self, other: &Path) -> bool {
         match (self.prefix, other.prefix) {
             (Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
                 self.is_absolute() &&
-                    s_repr[0].to_ascii().eq_ignore_case(o_repr[4].to_ascii())
+                    s_repr.as_bytes()[0].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
             }
             (Some(VerbatimDiskPrefix), Some(DiskPrefix)) => {
                 other.is_absolute() &&
-                    s_repr[4].to_ascii().eq_ignore_case(o_repr[0].to_ascii())
+                    s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[0].to_ascii())
             }
             (Some(VerbatimDiskPrefix), Some(VerbatimDiskPrefix)) => {
-                s_repr[4].to_ascii().eq_ignore_case(o_repr[4].to_ascii())
+                s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
             }
             (Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => {
                 s_repr.slice(2, self.prefix_len()) == o_repr.slice(8, other.prefix_len())
@@ -718,12 +722,12 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
             let mut comps = comps;
             match (comps.is_some(),prefix) {
                 (false, Some(DiskPrefix)) => {
-                    if s[0] >= 'a' as u8 && s[0] <= 'z' as u8 {
+                    if s.as_bytes()[0] >= 'a' as u8 && s.as_bytes()[0] <= 'z' as u8 {
                         comps = Some(vec![]);
                     }
                 }
                 (false, Some(VerbatimDiskPrefix)) => {
-                    if s[4] >= 'a' as u8 && s[0] <= 'z' as u8 {
+                    if s.as_bytes()[4] >= 'a' as u8 && s.as_bytes()[0] <= 'z' as u8 {
                         comps = Some(vec![]);
                     }
                 }
@@ -778,12 +782,12 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
                         let mut s = String::with_capacity(n);
                         match prefix {
                             Some(DiskPrefix) => {
-                                s.push_char(prefix_[0].to_ascii().to_upper().to_char());
+                                s.push_char(prefix_.as_bytes()[0].to_ascii().to_upper().to_char());
                                 s.push_char(':');
                             }
                             Some(VerbatimDiskPrefix) => {
                                 s.push_str(prefix_.slice_to(4));
-                                s.push_char(prefix_[4].to_ascii().to_upper().to_char());
+                                s.push_char(prefix_.as_bytes()[4].to_ascii().to_upper().to_char());
                                 s.push_str(prefix_.slice_from(5));
                             }
                             Some(UNCPrefix(a,b)) => {
@@ -845,7 +849,7 @@ fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> {
 
     fn has_nonsemantic_trailing_slash(&self) -> bool {
         is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
-            self.repr.as_slice()[self.repr.len()-1] == SEP_BYTE
+            self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE
     }
 
     fn update_normalized<S: Str>(&mut self, s: S) {
@@ -861,7 +865,7 @@ fn update_normalized<S: Str>(&mut self, s: S) {
 /// but absolute within that volume.
 #[inline]
 pub fn is_vol_relative(path: &Path) -> bool {
-    path.prefix.is_none() && is_sep_byte(&path.repr.as_slice()[0])
+    path.prefix.is_none() && is_sep_byte(&path.repr.as_bytes()[0])
 }
 
 /// Returns whether the path is considered "cwd-relative", which means a path
@@ -991,8 +995,8 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
             } else {
                 // \\?\path
                 let idx = path.find('\\');
-                if idx == Some(2) && path[1] == ':' as u8 {
-                    let c = path[0];
+                if idx == Some(2) && path.as_bytes()[1] == ':' as u8 {
+                    let c = path.as_bytes()[0];
                     if c.is_ascii() && ::char::is_alphabetic(c as char) {
                         // \\?\C:\ path
                         return Some(VerbatimDiskPrefix);
@@ -1014,9 +1018,9 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
             }
             _ => ()
         }
-    } else if path.len() > 1 && path[1] == ':' as u8 {
+    } else if path.len() > 1 && path.as_bytes()[1] == ':' as u8 {
         // C:
-        let c = path[0];
+        let c = path.as_bytes()[0];
         if c.is_ascii() && ::char::is_alphabetic(c as char) {
             return Some(DiskPrefix);
         }
index 90569bfc132c7de3b2c819c37e92a85ee12a501d..dfaa9fb5fcb09507f31144396946f7708b588c40 100644 (file)
@@ -415,7 +415,7 @@ fn highlight_lines(err: &mut EmitterWriter,
         }
         let orig = fm.get_line(*lines.lines.get(0) as int);
         for pos in range(0u, left-skip) {
-            let cur_char = orig.as_slice()[pos] as char;
+            let cur_char = orig.as_bytes()[pos] as char;
             // Whenever a tab occurs on the previous line, we insert one on
             // the error-point-squiggly-line as well (instead of a space).
             // That way the squiggly line will usually appear in the correct
index ac570c888375c4bcf8e15e6f73ab18ab8d7858c3..0f188fdf18a5a80c06ee94126b1ac47e16198674 100644 (file)
@@ -1203,8 +1203,8 @@ fn read_to_eol(&mut self) -> String {
 
     fn read_one_line_comment(&mut self) -> String {
         let val = self.read_to_eol();
-        assert!((val.as_slice()[0] == '/' as u8 && val.as_slice()[1] == '/' as u8)
-             || (val.as_slice()[0] == '#' as u8 && val.as_slice()[1] == '!' as u8));
+        assert!((val.as_bytes()[0] == '/' as u8 && val.as_bytes()[1] == '/' as u8)
+             || (val.as_bytes()[0] == '#' as u8 && val.as_bytes()[1] == '!' as u8));
         return val;
     }
 
index 3ed7fccb933e667908d204c2199886dd690eec06..f52a032961dd96a568628259f8d785e43ff21fbd 100644 (file)
@@ -375,7 +375,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, String> {
     fn match_str(s: &str, pos: uint, needle: &str) -> bool {
         let mut i = pos;
         for ch in needle.bytes() {
-            if s[i] != ch {
+            if s.as_bytes()[i] != ch {
                 return false;
             }
             i += 1u;
index 19627e2c2ce5017ecf7e8a8a35e841554487c5e0..0e73256893e9cc1c06450b755c3fc6ccdccbdc2d 100644 (file)
@@ -324,8 +324,8 @@ pub fn to_simple_str(&self) -> String {
         let mut s: Vec<u8> = Vec::from_elem(32, 0u8);
         for i in range(0u, 16u) {
             let digit = format!("{:02x}", self.bytes[i] as uint);
-            *s.get_mut(i*2+0) = digit.as_slice()[0];
-            *s.get_mut(i*2+1) = digit.as_slice()[1];
+            *s.get_mut(i*2+0) = digit.as_bytes()[0];
+            *s.get_mut(i*2+1) = digit.as_bytes()[1];
         }
         str::from_utf8(s.as_slice()).unwrap().to_string()
     }
index 67be7d121a454049b709f6a7ad3f61e9935e34b0..195c146c12fe719f26927bef8016837b91852345 100644 (file)
@@ -183,7 +183,7 @@ fn main() {
 
        if line.len() == 0u { continue; }
 
-       match (line.as_slice()[0] as char, proc_mode) {
+       match (line.as_bytes()[0] as char, proc_mode) {
 
            // start processing if this is the one
            ('>', false) => {
index 0cb21807f92f9cc4513d9dbc7efa3d22d558dfdd..2d98668496cdb52e08c17a2a7d201ce41914106a 100644 (file)
@@ -1,12 +1,43 @@
-// 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.
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
 //
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+// contributed by the Rust Project Developers
+
+// Copyright (c) 2012-2014 The Rust Project Developers
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+//   notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+//   notice, this list of conditions and the following disclaimer in
+//   the documentation and/or other materials provided with the
+//   distribution.
+//
+// - Neither the name of "The Computer Language Benchmarks Game" nor
+//   the name of "The Computer Language Shootout Benchmarks" nor the
+//   names of its contributors may be used to endorse or promote
+//   products derived from this software without specific prior
+//   written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
 #![feature(macro_rules)]
 #![feature(simd)]
 #![allow(experimental)]
index 967229a34074bd7259cdb9370493b87fe02791ee..8b1f9eb19864fadf3a9caf31f5dcb686b4a09a4c 100644 (file)
@@ -17,10 +17,10 @@ pub fn main() {
     assert_eq!(v.as_slice()[3u32], 3); //~ ERROR: mismatched types
     assert_eq!(v.as_slice()[3i32], 3); //~ ERROR: mismatched types
     println!("{}", v.as_slice()[3u8]); //~ ERROR: mismatched types
-    assert_eq!(s.as_slice()[3u], 'd' as u8);
-    assert_eq!(s.as_slice()[3u8], 'd' as u8); //~ ERROR: mismatched types
-    assert_eq!(s.as_slice()[3i8], 'd' as u8); //~ ERROR: mismatched types
-    assert_eq!(s.as_slice()[3u32], 'd' as u8); //~ ERROR: mismatched types
-    assert_eq!(s.as_slice()[3i32], 'd' as u8); //~ ERROR: mismatched types
-    println!("{}", s.as_slice()[3u8]); //~ ERROR: mismatched types
+    assert_eq!(s.as_bytes()[3u], 'd' as u8);
+    assert_eq!(s.as_bytes()[3u8], 'd' as u8); //~ ERROR: mismatched types
+    assert_eq!(s.as_bytes()[3i8], 'd' as u8); //~ ERROR: mismatched types
+    assert_eq!(s.as_bytes()[3u32], 'd' as u8); //~ ERROR: mismatched types
+    assert_eq!(s.as_bytes()[3i32], 'd' as u8); //~ ERROR: mismatched types
+    println!("{}", s.as_bytes()[3u8]); //~ ERROR: mismatched types
 }
diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs
new file mode 100644 (file)
index 0000000..25e4c90
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate debug;
+
+pub fn main() {
+    let s: &str = "hello";
+    let c: u8 = s[4]; //~ ERROR cannot index a value of type `&str`
+}
index 26c5a6988cf13d3c7bed9c816bf9ca3ed40cc97c..c3ee76047d13428060432d2ded9cd7359bd79cb1 100644 (file)
@@ -14,5 +14,5 @@ fn main() {
     let s: String = "hello".to_string();
 
     // Bounds-check failure.
-    assert_eq!(s.as_slice()[5], 0x0 as u8);
+    assert_eq!(s.as_bytes()[5], 0x0 as u8);
 }
index 3d6b6ba626d1114d48b752dd14125fa47e30c93c..5364cdc627f50b1f95d9304ef8c0756c1c2b89cb 100644 (file)
@@ -17,8 +17,8 @@ pub fn main() {
     println!("{}", x);
     println!("{}", y);
 
-    assert_eq!(x[0], 'h' as u8);
-    assert_eq!(x[4], 'o' as u8);
+    assert_eq!(x.as_bytes()[0], 'h' as u8);
+    assert_eq!(x.as_bytes()[4], 'o' as u8);
 
     let z : &str = "thing";
     assert_eq!(v, x);
index 1652016b51b069151aaaa6195b2a4133c738ee60..b562558822cd1bf2064f346d670fa17a58526175 100644 (file)
@@ -15,6 +15,6 @@ pub fn main() {
     let _y : String = "there".to_string();
     let mut z = "thing".to_string();
     z = x;
-    assert_eq!(z.as_slice()[0], ('h' as u8));
-    assert_eq!(z.as_slice()[4], ('o' as u8));
+    assert_eq!(z.as_bytes()[0], ('h' as u8));
+    assert_eq!(z.as_bytes()[4], ('o' as u8));
 }
diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs
new file mode 100644 (file)
index 0000000..5b52bc3
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+trait Foo {}
+impl Foo for int {}
+fn foo(_: [&Foo, ..2]) {}
+fn foos(_: &[&Foo]) {}
+fn foog<T>(_: &[T], _: &[T]) {}
+
+fn bar(_: [Box<Foo>, ..2]) {}
+fn bars(_: &[Box<Foo>]) {}
+
+fn main() {
+    let x: [&Foo, ..2] = [&1i, &2i];
+    foo(x);
+    foo([&1i, &2i]);
+
+    let r = &1i;
+    let x: [&Foo, ..2] = [r, ..2];
+    foo(x);
+    foo([&1i, ..2]);
+
+    let x: &[&Foo] = &[&1i, &2i];
+    foos(x);
+    foos(&[&1i, &2i]);
+
+    let x: &[&Foo] = &[&1i, &2i];
+    let r = &1i;
+    foog(x, &[r]);
+
+    let x: [Box<Foo>, ..2] = [box 1i, box 2i];
+    bar(x);
+    bar([box 1i, box 2i]);
+
+    let x: &[Box<Foo>] = &[box 1i, box 2i];
+    bars(x);
+    bars(&[box 1i, box 2i]);
+
+    let x: &[Box<Foo>] = &[box 1i, box 2i];
+    foog(x, &[box 1i]);
+
+    struct T<'a> {
+        t: [&'a Foo, ..2]
+    }
+    let _n = T {
+        t: [&1i, &2i]
+    };
+    let r = &1i;
+    let _n = T {
+        t: [r, ..2]
+    };
+    let x: [&Foo, ..2] = [&1i, &2i];
+    let _n = T {
+        t: x
+    };
+
+    struct F<'b> {
+        t: &'b [&'b Foo]
+    }
+    let _n = F {
+        t: &[&1i, &2i]
+    };
+    let r = &1i;
+    let r: [&Foo, ..2] = [r, ..2];
+    let _n = F {
+        t: r
+    };
+    let x: [&Foo, ..2] = [&1i, &2i];
+    let _n = F {
+        t: x
+    };
+
+    struct M<'a> {
+        t: &'a [Box<Foo>]
+    }
+    let _n = M {
+        t: &[box 1i, box 2i]
+    };
+    let x: [Box<Foo>, ..2] = [box 1i, box 2i];
+    let _n = M {
+        t: x
+    };
+}
index 7141d0b9df5250e85decc2cbe02924024289ec37..ad0d2f11abd8611562a1c660f02d556142545134 100644 (file)
@@ -16,5 +16,5 @@ pub fn main() {
     let b: String = "world".to_string();
     let s: String = format!("{}{}", a, b);
     println!("{}", s.clone());
-    assert_eq!(s.as_slice()[9], 'd' as u8);
+    assert_eq!(s.as_bytes()[9], 'd' as u8);
 }
diff --git a/src/test/run-pass/str-idx.rs b/src/test/run-pass/str-idx.rs
deleted file mode 100644 (file)
index 8ac13e8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern crate debug;
-
-pub fn main() {
-    let s = "hello".to_string();
-    let c: u8 = s.as_slice()[4];
-    println!("{:?}", c);
-    assert_eq!(c, 0x6f as u8);
-}
index 9263cd1d485422e2dcfed162c1e5d5e4f96172b1..d45e7a20c3b2020271f71a5fa1ff7ac106cafcbb 100644 (file)
@@ -39,10 +39,10 @@ fn test_str() {
     let s0 = "test".to_string();
     tx.send(s0);
     let s1 = rx.recv();
-    assert_eq!(s1.as_slice()[0], 't' as u8);
-    assert_eq!(s1.as_slice()[1], 'e' as u8);
-    assert_eq!(s1.as_slice()[2], 's' as u8);
-    assert_eq!(s1.as_slice()[3], 't' as u8);
+    assert_eq!(s1.as_bytes()[0], 't' as u8);
+    assert_eq!(s1.as_bytes()[1], 'e' as u8);
+    assert_eq!(s1.as_bytes()[2], 's' as u8);
+    assert_eq!(s1.as_bytes()[3], 't' as u8);
 }
 
 #[deriving(Show)]
index 18a0e5d471c4a91fa3134034c6334ab324fee4d6..cfe9a772b2ee84de751ea38d3528d420f32b3bf1 100644 (file)
@@ -99,7 +99,7 @@ fn check_legs(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
 fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
     for pet in arc.iter() {
         pet.name(|name| {
-            assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
+            assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
         })
     }
 }
index a79fcfa94171fb4211ac1aa79f9a398c3a2f810a..557d2e5878e1dd1bf03f18786fec07e04b666ac5 100644 (file)
@@ -46,7 +46,7 @@ fn check_str_eq(a: String, b: String) {
         for ab in a.as_slice().bytes() {
             println!("{}", i);
             println!("{}", ab);
-            let bb: u8 = b.as_slice()[i as uint];
+            let bb: u8 = b.as_bytes()[i as uint];
             println!("{}", bb);
             assert_eq!(ab, bb);
             i += 1;