about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZiad Hatahet <hatahet@gmail.com>2013-10-23 10:09:06 -0700
committerZiad Hatahet <hatahet@gmail.com>2013-10-23 10:09:06 -0700
commit7d69837bd263f334aa9dea4235698c006f7b1ce8 (patch)
treeb43315adfc734b0ab480b40674721c99902f3eb2
parent60245b9290388671edac86d6db1619f60a9ccb68 (diff)
parenta4ec8af4c549bd806522826b756e18fbf0b5c47b (diff)
downloadrust-7d69837bd263f334aa9dea4235698c006f7b1ce8.tar.gz
rust-7d69837bd263f334aa9dea4235698c006f7b1ce8.zip
Merge remote-tracking branch 'upstream/master'
-rw-r--r--doc/rust.md17
-rw-r--r--doc/tutorial.md16
-rw-r--r--mk/tests.mk1
-rw-r--r--src/libextra/arc.rs10
-rw-r--r--src/libextra/base64.rs8
-rw-r--r--src/libextra/bitv.rs4
-rw-r--r--src/libextra/crypto/cryptoutil.rs2
-rw-r--r--src/libextra/ebml.rs2
-rw-r--r--src/libextra/fileinput.rs2
-rw-r--r--src/libextra/flate.rs2
-rw-r--r--src/libextra/getopts.rs6
-rw-r--r--src/libextra/glob.rs6
-rw-r--r--src/libextra/io_util.rs4
-rw-r--r--src/libextra/json.rs6
-rw-r--r--src/libextra/num/rational.rs4
-rw-r--r--src/libextra/semver.rs10
-rw-r--r--src/libextra/sort.rs12
-rw-r--r--src/libextra/stats.rs19
-rw-r--r--src/libextra/sync.rs4
-rw-r--r--src/libextra/task_pool.rs4
-rw-r--r--src/libextra/term.rs4
-rw-r--r--src/libextra/terminfo/parm.rs4
-rw-r--r--src/libextra/terminfo/terminfo.rs4
-rw-r--r--src/libextra/test.rs14
-rw-r--r--src/libextra/time.rs29
-rw-r--r--src/libextra/treemap.rs2
-rw-r--r--src/libextra/workcache.rs22
-rw-r--r--src/librustc/metadata/decoder.rs4
-rw-r--r--src/librustc/metadata/encoder.rs6
-rw-r--r--src/librustc/middle/astencode.rs2
-rw-r--r--src/librustc/middle/liveness.rs2
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/moves.rs2
-rw-r--r--src/librustc/middle/resolve.rs12
-rw-r--r--src/librustc/middle/trans/expr.rs2
-rw-r--r--src/librustc/middle/trans/inline.rs2
-rw-r--r--src/librustc/middle/trans/meth.rs2
-rw-r--r--src/librustc/middle/typeck/astconv.rs4
-rw-r--r--src/librustc/middle/typeck/check/method.rs10
-rw-r--r--src/librustc/middle/typeck/check/mod.rs2
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs2
-rw-r--r--src/librustdoc/clean.rs6
-rw-r--r--src/librustpkg/api.rs96
-rw-r--r--src/librustpkg/conditions.rs6
-rw-r--r--src/librustpkg/context.rs18
-rw-r--r--src/librustpkg/package_source.rs52
-rw-r--r--src/librustpkg/path_util.rs4
-rw-r--r--src/librustpkg/rustpkg.rs113
-rw-r--r--src/librustpkg/target.rs26
-rw-r--r--src/librustpkg/tests.rs121
-rw-r--r--src/librustpkg/testsuite/pass/src/c-dependencies/bar.rs13
-rw-r--r--src/librustpkg/testsuite/pass/src/c-dependencies/foo.rs12
-rw-r--r--src/librustpkg/testsuite/pass/src/c-dependencies/lib.rs14
-rw-r--r--src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs83
-rw-r--r--src/librustpkg/testsuite/pass/src/fancy-lib/lib.rs2
-rw-r--r--src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs31
-rw-r--r--src/librustpkg/util.rs26
-rw-r--r--src/libstd/fmt/mod.rs1
-rw-r--r--src/libstd/io.rs12
-rw-r--r--src/libstd/iter.rs4
-rw-r--r--src/libstd/rand/distributions.rs522
-rw-r--r--src/libstd/rand/isaac.rs83
-rw-r--r--src/libstd/rand/mod.rs347
-rw-r--r--src/libstd/rand/os.rs16
-rw-r--r--src/libstd/rand/range.rs235
-rw-r--r--src/libstd/reflect.rs2
-rw-r--r--src/libstd/repr.rs8
-rw-r--r--src/libstd/rt/borrowck.rs4
-rw-r--r--src/libstd/rt/comm.rs10
-rw-r--r--src/libstd/rt/context.rs24
-rw-r--r--src/libstd/rt/crate_map.rs6
-rw-r--r--src/libstd/rt/io/file.rs4
-rw-r--r--src/libstd/rt/io/flate.rs4
-rw-r--r--src/libstd/rt/io/mock.rs6
-rw-r--r--src/libstd/rt/io/mod.rs4
-rw-r--r--src/libstd/rt/kill.rs8
-rw-r--r--src/libstd/rt/local_heap.rs4
-rw-r--r--src/libstd/rt/rc.rs2
-rw-r--r--src/libstd/rt/rtio.rs2
-rw-r--r--src/libstd/rt/sched.rs14
-rw-r--r--src/libstd/rt/stack.rs4
-rw-r--r--src/libstd/rt/task.rs4
-rw-r--r--src/libstd/rt/thread.rs6
-rw-r--r--src/libstd/rt/tube.rs2
-rw-r--r--src/libstd/rt/uv/addrinfo.rs2
-rw-r--r--src/libstd/rt/uv/file.rs2
-rw-r--r--src/libstd/rt/uv/mod.rs2
-rw-r--r--src/libstd/rt/uv/uvio.rs46
-rw-r--r--src/libstd/rt/uv/uvll.rs64
-rw-r--r--src/libstd/run.rs2
-rw-r--r--src/libstd/str.rs1
-rw-r--r--src/libstd/task/mod.rs18
-rw-r--r--src/libstd/task/spawn.rs6
-rw-r--r--src/libstd/unstable/intrinsics.rs8
-rw-r--r--src/libstd/unstable/raw.rs2
-rw-r--r--src/libstd/unstable/sync.rs4
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/deriving/ty.rs4
-rw-r--r--src/libsyntax/parse/parser.rs40
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/rt/rust_builtin.cpp2
-rw-r--r--src/test/bench/core-std.rs6
-rw-r--r--src/test/compile-fail/issue-5216.rs20
-rw-r--r--src/test/compile-fail/issue-5500-1.rs22
-rw-r--r--src/test/compile-fail/issue-5500.rs13
-rw-r--r--src/test/run-pass/by-value-self-in-mut-slot.rs30
-rw-r--r--src/test/run-pass/issue-6334.rs56
-rw-r--r--src/test/run-pass/self-in-mut-slot-default-method.rs43
-rw-r--r--src/test/run-pass/uniq-self-in-mut-slot.rs30
110 files changed, 1957 insertions, 721 deletions
diff --git a/doc/rust.md b/doc/rust.md
index 2d4b0c15cb8..40a3bc12798 100644
--- a/doc/rust.md
+++ b/doc/rust.md
@@ -3168,7 +3168,7 @@ Raw pointers (`*`)
   : Raw pointers are pointers without safety or liveness guarantees.
     Raw pointers are written `*content`,
     for example `*int` means a raw pointer to an integer.
-    Copying or dropping a raw pointer is has no effect on the lifecycle of any other value.
+    Copying or dropping a raw pointer has no effect on the lifecycle of any other value.
     Dereferencing a raw pointer or converting it to any other pointer type is an [`unsafe` operation](#unsafe-functions).
     Raw pointers are generally discouraged in Rust code;
     they exist to support interoperability with foreign code,
@@ -3395,16 +3395,23 @@ a [temporary](#lvalues-rvalues-and-temporaries), or a local variable.
 A _local variable_ (or *stack-local* allocation) holds a value directly,
 allocated within the stack's memory. The value is a part of the stack frame.
 
-Local variables are immutable unless declared with `let mut`.  The
-`mut` keyword applies to all local variables declared within that
-declaration (so `let mut (x, y) = ...` declares two mutable variables, `x` and
-`y`).
+Local variables are immutable unless declared otherwise like: `let mut x = ...`.
 
 Function parameters are immutable unless declared with `mut`. The
 `mut` keyword applies only to the following parameter (so `|mut x, y|`
 and `fn f(mut x: ~int, y: ~int)` declare one mutable variable `x` and
 one immutable variable `y`).
 
+Methods that take either `self` or `~self` can optionally place them in a
+mutable slot by prefixing them with `mut` (similar to regular arguments):
+
+~~~
+trait Changer {
+    fn change(mut self) -> Self;
+    fn modify(mut ~self) -> ~Self;
+}
+~~~
+
 Local variables are not initialized when allocated; the entire frame worth of
 local variables are allocated at once, on frame-entry, in an uninitialized
 state. Subsequent statements within a function may or may not initialize the
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 42617a96daa..7451919c5be 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -151,22 +151,6 @@ declaration to appear at the top level of the file: all statements must
 live inside a function.  Rust programs can also be compiled as
 libraries, and included in other programs.
 
-## Using the rust tool
-
-While using `rustc` directly to generate your executables, and then
-running them manually is a perfectly valid way to test your code,
-for smaller projects, prototypes, or if you're a beginner, it might be
-more convenient to use the `rust` tool.
-
-The `rust` tool provides central access to the other rust tools,
-as well as handy shortcuts for directly running source files.
-For example, if you have a file `foo.rs` in your current directory,
-`rust run foo.rs` would attempt to compile it and, if successful,
-directly run the resulting binary.
-
-To get a list of all available commands, simply call `rust` without any
-argument.
-
 ## Editing Rust code
 
 There are vim highlighting and indentation scripts in the Rust source
diff --git a/mk/tests.mk b/mk/tests.mk
index c06c234e951..d6fc5ecb8e5 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -370,6 +370,7 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)):					\
 		$$(SREQ$(1)_T_$(2)_H_$(3)) \
 		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
 		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
+		$$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(2)) \
 		$$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2)) \
 		$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(2))
 	@$$(call E, compile_and_link: $$@)
diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs
index 66dad4721aa..1ce52d1d278 100644
--- a/src/libextra/arc.rs
+++ b/src/libextra/arc.rs
@@ -521,15 +521,15 @@ fn borrow_rwlock<T:Freeze + Send>(state: *mut RWArcInner<T>) -> *RWLock {
 
 /// The "write permission" token used for RWArc.write_downgrade().
 pub struct RWWriteMode<'self, T> {
-    data: &'self mut T,
-    token: sync::RWLockWriteMode<'self>,
-    poison: PoisonOnFail,
+    priv data: &'self mut T,
+    priv token: sync::RWLockWriteMode<'self>,
+    priv poison: PoisonOnFail,
 }
 
 /// The "read permission" token used for RWArc.write_downgrade().
 pub struct RWReadMode<'self, T> {
-    data: &'self T,
-    token: sync::RWLockReadMode<'self>,
+    priv data: &'self T,
+    priv token: sync::RWLockReadMode<'self>,
 }
 
 impl<'self, T:Freeze + Send> RWWriteMode<'self, T> {
diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs
index 3960be46686..032de0b5f4a 100644
--- a/src/libextra/base64.rs
+++ b/src/libextra/base64.rs
@@ -22,11 +22,11 @@ pub enum CharacterSet {
 /// Contains configuration parameters for `to_base64`.
 pub struct Config {
     /// Character set to use
-    char_set: CharacterSet,
+    priv char_set: CharacterSet,
     /// True to pad output with `=` characters
-    pad: bool,
+    priv pad: bool,
     /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
-    line_length: Option<uint>
+    priv line_length: Option<uint>
 }
 
 /// Configuration for RFC 4648 standard base64 encoding
@@ -318,7 +318,7 @@ mod test {
         use std::vec;
 
         do 1000.times {
-            let times = task_rng().gen_integer_range(1u, 100);
+            let times = task_rng().gen_range(1u, 100);
             let v = vec::from_fn(times, |_| random::<u8>());
             assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
         }
diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs
index bf0fde807d3..96123ad75b2 100644
--- a/src/libextra/bitv.rs
+++ b/src/libextra/bitv.rs
@@ -226,9 +226,9 @@ enum Op {Union, Intersect, Assign, Difference}
 #[deriving(Clone)]
 pub struct Bitv {
     /// Internal representation of the bit vector (small or large)
-    rep: BitvVariant,
+    priv rep: BitvVariant,
     /// The number of valid bits in the internal representation
-    nbits: uint
+    priv nbits: uint
 }
 
 fn die() -> ! {
diff --git a/src/libextra/crypto/cryptoutil.rs b/src/libextra/crypto/cryptoutil.rs
index 97b82383d84..bb3524a7d49 100644
--- a/src/libextra/crypto/cryptoutil.rs
+++ b/src/libextra/crypto/cryptoutil.rs
@@ -365,7 +365,7 @@ pub mod test {
         digest.reset();
 
         while count < total_size {
-            let next: uint = rng.gen_integer_range(0, 2 * blocksize + 1);
+            let next: uint = rng.gen_range(0, 2 * blocksize + 1);
             let remaining = total_size - count;
             let size = if next > remaining { remaining } else { next };
             digest.input(buffer.slice_to(size));
diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs
index 006ae3520c6..34515a2b955 100644
--- a/src/libextra/ebml.rs
+++ b/src/libextra/ebml.rs
@@ -50,7 +50,7 @@ impl Doc {
 }
 
 pub struct TaggedDoc {
-    tag: uint,
+    priv tag: uint,
     doc: Doc,
 }
 
diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs
index fda88c583ce..49072dab6d0 100644
--- a/src/libextra/fileinput.rs
+++ b/src/libextra/fileinput.rs
@@ -155,7 +155,7 @@ struct FileInput_ {
 // "self.fi" -> "self." and renaming FileInput_. Documentation above
 // will likely have to be updated to use `let mut in = ...`.
 pub struct FileInput  {
-    fi: @mut FileInput_
+    priv fi: @mut FileInput_
 }
 
 impl FileInput {
diff --git a/src/libextra/flate.rs b/src/libextra/flate.rs
index 9d6c2e8aa82..3f3b588e8bc 100644
--- a/src/libextra/flate.rs
+++ b/src/libextra/flate.rs
@@ -113,7 +113,7 @@ mod tests {
         let mut r = rand::rng();
         let mut words = ~[];
         do 20.times {
-            let range = r.gen_integer_range(1u, 10);
+            let range = r.gen_range(1u, 10);
             words.push(r.gen_vec::<u8>(range));
         }
         do 20.times {
diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs
index a0ce29cd1b6..38b4d83fe0b 100644
--- a/src/libextra/getopts.rs
+++ b/src/libextra/getopts.rs
@@ -119,7 +119,7 @@ pub struct Opt {
     /// How often it can occur
     occur: Occur,
     /// Which options it aliases
-    aliases: ~[Opt],
+    priv aliases: ~[Opt],
 }
 
 /// Describes wether an option is given at all or has a value.
@@ -134,9 +134,9 @@ enum Optval {
 #[deriving(Clone, Eq)]
 pub struct Matches {
     /// Options that matched
-    opts: ~[Opt],
+    priv opts: ~[Opt],
     /// Values of the Options that matched
-    vals: ~[~[Optval]],
+    priv vals: ~[~[Optval]],
     /// Free string fragments
     free: ~[~str]
 }
diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs
index cdcb730e8be..5297b48b0e1 100644
--- a/src/libextra/glob.rs
+++ b/src/libextra/glob.rs
@@ -480,13 +480,13 @@ pub struct MatchOptions {
      * currently only considers upper/lower case relationships between ASCII characters,
      * but in future this might be extended to work with Unicode.
      */
-    case_sensitive: bool,
+    priv case_sensitive: bool,
 
     /**
      * If this is true then path-component separator characters (e.g. `/` on Posix)
      * must be matched by a literal `/`, rather than by `*` or `?` or `[...]`
      */
-    require_literal_separator: bool,
+    priv require_literal_separator: bool,
 
     /**
      * If this is true then paths that contain components that start with a `.` will
@@ -494,7 +494,7 @@ pub struct MatchOptions {
      * will not match. This is useful because such files are conventionally considered
      * hidden on Unix systems and it might be desirable to skip them when listing files.
      */
-    require_literal_leading_dot: bool
+    priv require_literal_leading_dot: bool
 }
 
 impl MatchOptions {
diff --git a/src/libextra/io_util.rs b/src/libextra/io_util.rs
index 904ed13eabb..27a09be3a62 100644
--- a/src/libextra/io_util.rs
+++ b/src/libextra/io_util.rs
@@ -17,9 +17,9 @@ use std::cast;
 /// An implementation of the io::Reader interface which reads a buffer of bytes
 pub struct BufReader {
     /// The buffer of bytes to read
-    buf: ~[u8],
+    priv buf: ~[u8],
     /// The current position in the buffer of bytes
-    pos: @mut uint
+    priv pos: @mut uint
 }
 
 impl BufReader {
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index e151568ad7f..90260282e4b 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -49,11 +49,11 @@ pub type Object = TreeMap<~str, Json>;
 /// returned
 pub struct Error {
     /// The line number at which the error occurred
-    line: uint,
+    priv line: uint,
     /// The column number at which the error occurred
-    col: uint,
+    priv col: uint,
     /// A message describing the type of the error
-    msg: @~str,
+    priv msg: @~str,
 }
 
 fn escape_str(s: &str) -> ~str {
diff --git a/src/libextra/num/rational.rs b/src/libextra/num/rational.rs
index abb802c06f3..bdec950c87b 100644
--- a/src/libextra/num/rational.rs
+++ b/src/libextra/num/rational.rs
@@ -20,8 +20,8 @@ use super::bigint::BigInt;
 #[deriving(Clone)]
 #[allow(missing_doc)]
 pub struct Ratio<T> {
-    numer: T,
-    denom: T
+    priv numer: T,
+    priv denom: T
 }
 
 /// Alias for a `Ratio` of machine-sized integers.
diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs
index e5ef9ee12d5..02c35000ce3 100644
--- a/src/libextra/semver.rs
+++ b/src/libextra/semver.rs
@@ -71,17 +71,17 @@ impl ToStr for Identifier {
 #[deriving(Clone, Eq)]
 pub struct Version {
     /// The major version, to be incremented on incompatible changes.
-    major: uint,
+    priv major: uint,
     /// The minor version, to be incremented when functionality is added in a
     /// backwards-compatible manner.
-    minor: uint,
+    priv minor: uint,
     /// The patch version, to be incremented when backwards-compatible bug
     /// fixes are made.
-    patch: uint,
+    priv patch: uint,
     /// The pre-release version identifier, if one exists.
-    pre: ~[Identifier],
+    priv pre: ~[Identifier],
     /// The build metadata, ignored when determining version precedence.
-    build: ~[Identifier],
+    priv build: ~[Identifier],
 }
 
 impl ToStr for Version {
diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs
index d884f4f05c1..2a456f8de3e 100644
--- a/src/libextra/sort.rs
+++ b/src/libextra/sort.rs
@@ -1069,8 +1069,8 @@ mod big_tests {
             isSorted(arr);
 
             do 3.times {
-                let i1 = rng.gen_integer_range(0u, n);
-                let i2 = rng.gen_integer_range(0u, n);
+                let i1 = rng.gen_range(0u, n);
+                let i2 = rng.gen_range(0u, n);
                 arr.swap(i1, i2);
             }
             tim_sort(arr); // 3sort
@@ -1088,7 +1088,7 @@ mod big_tests {
             isSorted(arr);
 
             do (n/100).times {
-                let idx = rng.gen_integer_range(0u, n);
+                let idx = rng.gen_range(0u, n);
                 arr[idx] = rng.gen();
             }
             tim_sort(arr);
@@ -1141,8 +1141,8 @@ mod big_tests {
             isSorted(arr);
 
             do 3.times {
-                let i1 = rng.gen_integer_range(0u, n);
-                let i2 = rng.gen_integer_range(0u, n);
+                let i1 = rng.gen_range(0u, n);
+                let i2 = rng.gen_range(0u, n);
                 arr.swap(i1, i2);
             }
             tim_sort(arr); // 3sort
@@ -1160,7 +1160,7 @@ mod big_tests {
             isSorted(arr);
 
             do (n/100).times {
-                let idx = rng.gen_integer_range(0u, n);
+                let idx = rng.gen_range(0u, n);
                 arr[idx] = @rng.gen();
             }
             tim_sort(arr);
diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs
index cc6ce715ad3..40f99716ca7 100644
--- a/src/libextra/stats.rs
+++ b/src/libextra/stats.rs
@@ -105,18 +105,23 @@ pub trait Stats {
 #[deriving(Clone, Eq)]
 #[allow(missing_doc)]
 pub struct Summary {
-    sum: f64,
+    priv sum: f64,
+    // public
     min: f64,
+    // public
     max: f64,
-    mean: f64,
+    priv mean: f64,
+    // public
     median: f64,
-    var: f64,
-    std_dev: f64,
-    std_dev_pct: f64,
+    priv var: f64,
+    priv std_dev: f64,
+    priv std_dev_pct: f64,
+    // public
     median_abs_dev: f64,
+    // public
     median_abs_dev_pct: f64,
-    quartiles: (f64,f64,f64),
-    iqr: f64,
+    priv quartiles: (f64,f64,f64),
+    priv iqr: f64,
 }
 
 impl Summary {
diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs
index 5a2c1e0998c..131cf063d1d 100644
--- a/src/libextra/sync.rs
+++ b/src/libextra/sync.rs
@@ -376,8 +376,8 @@ impl Semaphore {
  * A task which fails while holding a mutex will unlock the mutex as it
  * unwinds.
  */
-pub struct Mutex { priv sem: Sem<~[WaitQueue]> }
 
+pub struct Mutex { priv sem: Sem<~[WaitQueue]> }
 impl Clone for Mutex {
     /// Create a new handle to the mutex.
     fn clone(&self) -> Mutex { Mutex { sem: Sem((*self.sem).clone()) } }
@@ -663,8 +663,8 @@ impl RWLock {
 }
 
 /// The "write permission" token used for rwlock.write_downgrade().
-pub struct RWLockWriteMode<'self> { priv lock: &'self RWLock, priv token: NonCopyable }
 
+pub struct RWLockWriteMode<'self> { priv lock: &'self RWLock, priv token: NonCopyable }
 /// The "read permission" token used for rwlock.write_downgrade().
 pub struct RWLockReadMode<'self> { priv lock: &'self RWLock,
                                    priv token: NonCopyable }
diff --git a/src/libextra/task_pool.rs b/src/libextra/task_pool.rs
index 804ccd2a9fd..f7db66dc4e0 100644
--- a/src/libextra/task_pool.rs
+++ b/src/libextra/task_pool.rs
@@ -28,8 +28,8 @@ enum Msg<T> {
 }
 
 pub struct TaskPool<T> {
-    channels: ~[Chan<Msg<T>>],
-    next_index: uint,
+    priv channels: ~[Chan<Msg<T>>],
+    priv next_index: uint,
 }
 
 #[unsafe_destructor]
diff --git a/src/libextra/term.rs b/src/libextra/term.rs
index cebe0ba9aa6..878224890e6 100644
--- a/src/libextra/term.rs
+++ b/src/libextra/term.rs
@@ -95,14 +95,14 @@ fn cap_for_attr(attr: attr::Attr) -> &'static str {
 
 #[cfg(not(target_os = "win32"))]
 pub struct Terminal {
-    num_colors: u16,
+    priv num_colors: u16,
     priv out: @io::Writer,
     priv ti: ~TermInfo
 }
 
 #[cfg(target_os = "win32")]
 pub struct Terminal {
-    num_colors: u16,
+    priv num_colors: u16,
     priv out: @io::Writer,
 }
 
diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs
index d1a0a86334a..c0a5d9d53aa 100644
--- a/src/libextra/terminfo/parm.rs
+++ b/src/libextra/terminfo/parm.rs
@@ -48,9 +48,9 @@ pub enum Param {
 /// Container for static and dynamic variable arrays
 pub struct Variables {
     /// Static variables A-Z
-    sta: [Param, ..26],
+    priv sta: [Param, ..26],
     /// Dynamic variables a-z
-    dyn: [Param, ..26]
+    priv dyn: [Param, ..26]
 }
 
 impl Variables {
diff --git a/src/libextra/terminfo/terminfo.rs b/src/libextra/terminfo/terminfo.rs
index 57e00885b2f..06bf6e47c32 100644
--- a/src/libextra/terminfo/terminfo.rs
+++ b/src/libextra/terminfo/terminfo.rs
@@ -15,9 +15,9 @@ use std::hashmap::HashMap;
 /// A parsed terminfo entry.
 pub struct TermInfo {
     /// Names for the terminal
-    names: ~[~str],
+    priv names: ~[~str],
     /// Map of capability name to boolean value
-    bools: HashMap<~str, bool>,
+    priv bools: HashMap<~str, bool>,
     /// Map of capability name to numeric value
     numbers: HashMap<~str, u16>,
     /// Map of capability name to raw (unexpanded) string
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index 1f8405dca94..f95c7aa22b7 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -102,9 +102,9 @@ impl TestFn {
 
 // Structure passed to BenchFns
 pub struct BenchHarness {
-    iterations: u64,
-    ns_start: u64,
-    ns_end: u64,
+    priv iterations: u64,
+    priv ns_start: u64,
+    priv ns_end: u64,
     bytes: u64
 }
 
@@ -124,8 +124,8 @@ pub struct TestDescAndFn {
 
 #[deriving(Clone, Encodable, Decodable, Eq)]
 pub struct Metric {
-    value: f64,
-    noise: f64
+    priv value: f64,
+    priv noise: f64
 }
 
 #[deriving(Eq)]
@@ -322,8 +322,8 @@ pub fn opt_shard(maybestr: Option<~str>) -> Option<(uint,uint)> {
 
 #[deriving(Clone, Eq)]
 pub struct BenchSamples {
-    ns_iter_summ: stats::Summary,
-    mb_s: uint
+    priv ns_iter_summ: stats::Summary,
+    priv mb_s: uint
 }
 
 #[deriving(Clone, Eq)]
diff --git a/src/libextra/time.rs b/src/libextra/time.rs
index ab701f1f982..71569be3a81 100644
--- a/src/libextra/time.rs
+++ b/src/libextra/time.rs
@@ -31,9 +31,10 @@ pub mod rustrt {
 }
 
 /// A record specifying a time value in seconds and nanoseconds.
-#[deriving(Clone, DeepClone, Eq, Encodable, Decodable)]
-pub struct Timespec { sec: i64, nsec: i32 }
 
+
+#[deriving(Clone, DeepClone, Eq, Encodable, Decodable)]
+pub struct Timespec { priv sec: i64, priv nsec: i32 }
 /*
  * Timespec assumes that pre-epoch Timespecs have negative sec and positive
  * nsec fields. Darwin's and Linux's struct timespec functions handle pre-
@@ -105,18 +106,18 @@ pub fn tzset() {
 
 #[deriving(Clone, DeepClone, Eq, Encodable, Decodable)]
 pub struct Tm {
-    tm_sec: i32, // seconds after the minute ~[0-60]
-    tm_min: i32, // minutes after the hour ~[0-59]
-    tm_hour: i32, // hours after midnight ~[0-23]
-    tm_mday: i32, // days of the month ~[1-31]
-    tm_mon: i32, // months since January ~[0-11]
-    tm_year: i32, // years since 1900
-    tm_wday: i32, // days since Sunday ~[0-6]
-    tm_yday: i32, // days since January 1 ~[0-365]
-    tm_isdst: i32, // Daylight Savings Time flag
-    tm_gmtoff: i32, // offset from UTC in seconds
-    tm_zone: ~str, // timezone abbreviation
-    tm_nsec: i32, // nanoseconds
+    priv tm_sec: i32, // seconds after the minute ~[0-60]
+    priv tm_min: i32, // minutes after the hour ~[0-59]
+    priv tm_hour: i32, // hours after midnight ~[0-23]
+    priv tm_mday: i32, // days of the month ~[1-31]
+    priv tm_mon: i32, // months since January ~[0-11]
+    priv tm_year: i32, // years since 1900
+    priv tm_wday: i32, // days since Sunday ~[0-6]
+    priv tm_yday: i32, // days since January 1 ~[0-365]
+    priv tm_isdst: i32, // Daylight Savings Time flag
+    priv tm_gmtoff: i32, // offset from UTC in seconds
+    priv tm_zone: ~str, // timezone abbreviation
+    priv tm_nsec: i32, // nanoseconds
 }
 
 pub fn empty_tm() -> Tm {
diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs
index ad196b32fb2..7ef9ba76b99 100644
--- a/src/libextra/treemap.rs
+++ b/src/libextra/treemap.rs
@@ -1028,7 +1028,7 @@ mod test_treemap {
             }
 
             do 30.times {
-                let r = rng.gen_integer_range(0, ctrl.len());
+                let r = rng.gen_range(0, ctrl.len());
                 let (key, _) = ctrl.remove(r);
                 assert!(map.remove(&key));
                 check_structure(&map);
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index 3ee10251323..4d79b2059db 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -128,8 +128,8 @@ impl WorkMap {
 }
 
 pub struct Database {
-    db_filename: Path,
-    db_cache: TreeMap<~str, ~str>,
+    priv db_filename: Path,
+    priv db_cache: TreeMap<~str, ~str>,
     db_dirty: bool
 }
 
@@ -209,7 +209,7 @@ impl Drop for Database {
 
 pub struct Logger {
     // FIXME #4432: Fill in
-    a: ()
+    priv a: ()
 }
 
 impl Logger {
@@ -228,26 +228,26 @@ pub type FreshnessMap = TreeMap<~str,extern fn(&str,&str)->bool>;
 #[deriving(Clone)]
 pub struct Context {
     db: RWArc<Database>,
-    logger: RWArc<Logger>,
-    cfg: Arc<json::Object>,
+    priv logger: RWArc<Logger>,
+    priv cfg: Arc<json::Object>,
     /// Map from kinds (source, exe, url, etc.) to a freshness function.
     /// The freshness function takes a name (e.g. file path) and value
     /// (e.g. hash of file contents) and determines whether it's up-to-date.
     /// For example, in the file case, this would read the file off disk,
     /// hash it, and return the result of comparing the given hash and the
     /// read hash for equality.
-    freshness: Arc<FreshnessMap>
+    priv freshness: Arc<FreshnessMap>
 }
 
 pub struct Prep<'self> {
-    ctxt: &'self Context,
-    fn_name: &'self str,
-    declared_inputs: WorkMap,
+    priv ctxt: &'self Context,
+    priv fn_name: &'self str,
+    priv declared_inputs: WorkMap,
 }
 
 pub struct Exec {
-    discovered_inputs: WorkMap,
-    discovered_outputs: WorkMap
+    priv discovered_inputs: WorkMap,
+    priv discovered_outputs: WorkMap
 }
 
 enum Work<'self, T> {
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index aa1c4c1eb7e..10232730329 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -975,9 +975,9 @@ fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
     let explicit_self_kind = string[0];
     match explicit_self_kind as char {
         's' => { return ast::sty_static; }
-        'v' => { return ast::sty_value; }
+        'v' => { return ast::sty_value(get_mutability(string[1])); }
         '@' => { return ast::sty_box(get_mutability(string[1])); }
-        '~' => { return ast::sty_uniq; }
+        '~' => { return ast::sty_uniq(get_mutability(string[1])); }
         '&' => {
             // FIXME(#4846) expl. region
             return ast::sty_region(None, get_mutability(string[1]));
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 9f40593a93a..bae0dcc2a52 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -662,8 +662,9 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic
         sty_static => {
             ebml_w.writer.write(&[ 's' as u8 ]);
         }
-        sty_value => {
+        sty_value(m) => {
             ebml_w.writer.write(&[ 'v' as u8 ]);
+            encode_mutability(ebml_w, m);
         }
         sty_region(_, m) => {
             // FIXME(#4846) encode custom lifetime
@@ -674,8 +675,9 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic
             ebml_w.writer.write(&[ '@' as u8 ]);
             encode_mutability(ebml_w, m);
         }
-        sty_uniq => {
+        sty_uniq(m) => {
             ebml_w.writer.write(&[ '~' as u8 ]);
+            encode_mutability(ebml_w, m);
         }
     }
 
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 294bbcb46f7..3d7f28b8b30 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -410,7 +410,7 @@ impl tr for ast::Def {
             ast::DefMethod(did0.tr(xcx), did1.map(|did1| did1.tr(xcx)))
           }
           ast::DefSelfTy(nid) => { ast::DefSelfTy(xcx.tr_id(nid)) }
-          ast::DefSelf(nid) => { ast::DefSelf(xcx.tr_id(nid)) }
+          ast::DefSelf(nid, m) => { ast::DefSelf(xcx.tr_id(nid), m) }
           ast::DefMod(did) => { ast::DefMod(did.tr(xcx)) }
           ast::DefForeignMod(did) => { ast::DefForeignMod(did.tr(xcx)) }
           ast::DefStatic(did, m) => { ast::DefStatic(did.tr(xcx), m) }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 6c53fc1602f..71934c9f2a7 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -392,7 +392,7 @@ fn visit_fn(v: &mut LivenessVisitor,
     match *fk {
         visit::fk_method(_, _, method) => {
             match method.explicit_self.node {
-                sty_value | sty_region(*) | sty_box(_) | sty_uniq => {
+                sty_value(_) | sty_region(*) | sty_box(_) | sty_uniq(_) => {
                     fn_maps.add_variable(Arg(method.self_id,
                                              special_idents::self_));
                 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 37e89e58fa5..eb03027ad71 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -488,12 +488,12 @@ impl mem_categorization_ctxt {
             }
           }
 
-          ast::DefSelf(self_id) => {
+          ast::DefSelf(self_id, mutbl) => {
             @cmt_ {
                 id:id,
                 span:span,
                 cat:cat_self(self_id),
-                mutbl: McImmutable,
+                mutbl: if mutbl { McDeclared } else { McImmutable },
                 ty:expr_ty
             }
           }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 1ed517c9512..5001614647a 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -227,7 +227,7 @@ pub fn moved_variable_node_id_from_def(def: Def) -> Option<NodeId> {
       DefBinding(nid, _) |
       DefArg(nid, _) |
       DefLocal(nid, _) |
-      DefSelf(nid) => Some(nid),
+      DefSelf(nid, _) => Some(nid),
 
       _ => None
     }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index b480aaac1ac..ee36b807ac7 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -150,7 +150,7 @@ enum Mutability {
 
 enum SelfBinding {
     NoSelfBinding,
-    HasSelfBinding(NodeId)
+    HasSelfBinding(NodeId, explicit_self)
 }
 
 impl Visitor<()> for Resolver {
@@ -3799,8 +3799,12 @@ impl Resolver {
                 NoSelfBinding => {
                     // Nothing to do.
                 }
-                HasSelfBinding(self_node_id) => {
-                    let def_like = DlDef(DefSelf(self_node_id));
+                HasSelfBinding(self_node_id, explicit_self) => {
+                    let mutable = match explicit_self.node {
+                        sty_uniq(m) | sty_value(m) if m == MutMutable => true,
+                        _ => false
+                    };
+                    let def_like = DlDef(DefSelf(self_node_id, mutable));
                     *function_value_rib.self_binding = Some(def_like);
                 }
             }
@@ -3937,7 +3941,7 @@ impl Resolver {
         // we only have self ty if it is a non static method
         let self_binding = match method.explicit_self.node {
           sty_static => { NoSelfBinding }
-          _ => { HasSelfBinding(method.self_id) }
+          _ => { HasSelfBinding(method.self_id, method.explicit_self) }
         };
 
         self.resolve_function(rib_kind,
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 238b15fe597..56f1e047841 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -1099,7 +1099,7 @@ pub fn trans_local_var(bcx: @mut Block, def: ast::Def) -> Datum {
         ast::DefLocal(nid, _) | ast::DefBinding(nid, _) => {
             take_local(bcx, bcx.fcx.lllocals, nid)
         }
-        ast::DefSelf(nid) => {
+        ast::DefSelf(nid, _) => {
             let self_info: ValSelfData = match bcx.fcx.llself {
                 Some(ref self_info) => *self_info,
                 None => {
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index a5be9a3ca5e..d9f7cdeeb2e 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -144,7 +144,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId)
                       debug!("calling inline trans_fn with self_ty {}",
                              ty_to_str(ccx.tcx, self_ty));
                       match mth.explicit_self.node {
-                          ast::sty_value => impl_self(self_ty, ty::ByRef),
+                          ast::sty_value(_) => impl_self(self_ty, ty::ByRef),
                           _ => impl_self(self_ty, ty::ByCopy),
                       }
                   }
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index a8c18c72167..61384c72efa 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -120,7 +120,7 @@ pub fn trans_method(ccx: @mut CrateContext,
         debug!("calling trans_fn with self_ty {}",
                self_ty.repr(ccx.tcx));
         match method.explicit_self.node {
-          ast::sty_value => impl_self(self_ty, ty::ByRef),
+          ast::sty_value(_) => impl_self(self_ty, ty::ByRef),
           _ => impl_self(self_ty, ty::ByCopy),
         }
       }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index ccda6bbaf9d..dd0c6c12a69 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -672,7 +672,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
     {
         match self_info.explicit_self.node {
             ast::sty_static => None,
-            ast::sty_value => {
+            ast::sty_value(_) => {
                 Some(self_info.untransformed_self_ty)
             }
             ast::sty_region(ref lifetime, mutability) => {
@@ -689,7 +689,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
                                 ty::mt {ty: self_info.untransformed_self_ty,
                                         mutbl: mutability}))
             }
-            ast::sty_uniq => {
+            ast::sty_uniq(_) => {
                 Some(ty::mk_uniq(this.tcx(),
                                  ty::mt {ty: self_info.untransformed_self_ty,
                                          mutbl: ast::MutImmutable}))
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index f6efd3aa5ad..af1d5ce3cc6 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -1082,7 +1082,7 @@ impl<'self> LookupContext<'self> {
             ast::sty_static => {
                 self.bug(~"static method for object type receiver");
             }
-            ast::sty_value => {
+            ast::sty_value(_) => {
                 ty::mk_err() // error reported in `enforce_object_limitations()`
             }
             ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {
@@ -1141,7 +1141,7 @@ impl<'self> LookupContext<'self> {
                      through an object");
             }
 
-            ast::sty_value => { // reason (a) above
+            ast::sty_value(_) => { // reason (a) above
                 self.tcx().sess.span_err(
                     self.expr.span,
                     "cannot call a method with a by-value receiver \
@@ -1198,7 +1198,7 @@ impl<'self> LookupContext<'self> {
                 false
             }
 
-            sty_value => {
+            sty_value(_) => {
                 rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
             }
 
@@ -1236,7 +1236,7 @@ impl<'self> LookupContext<'self> {
                 }
             }
 
-            sty_uniq => {
+            sty_uniq(_) => {
                 debug!("(is relevant?) explicit self is a unique pointer");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(mt) => {
@@ -1369,7 +1369,7 @@ impl<'self> LookupContext<'self> {
 
 pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMode {
     match explicit_self {
-        sty_value => ty::ByRef,
+        sty_value(_) => ty::ByRef,
         _ => ty::ByCopy,
     }
 }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index eddf8aa5185..4514564ff1f 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3254,7 +3254,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
                                       defn: ast::Def)
                                    -> ty_param_bounds_and_ty {
     match defn {
-      ast::DefArg(nid, _) | ast::DefLocal(nid, _) | ast::DefSelf(nid) |
+      ast::DefArg(nid, _) | ast::DefLocal(nid, _) | ast::DefSelf(nid, _) |
       ast::DefBinding(nid, _) => {
           let typ = fcx.local_ty(sp, nid);
           return no_params(typ);
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 06a13059462..09fc7b5c15c 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -58,7 +58,7 @@ fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::Def) -> ty::Region {
     let tcx = fcx.tcx();
     match def {
         DefLocal(node_id, _) | DefArg(node_id, _) |
-        DefSelf(node_id) | DefBinding(node_id, _) => {
+        DefSelf(node_id, _) | DefBinding(node_id, _) => {
             tcx.region_maps.encl_region(node_id)
         }
         DefUpvar(_, subdef, closure_id, body_id) => {
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index 6ee7f8c1727..dd1ad8263da 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -388,8 +388,8 @@ impl Clean<SelfTy> for ast::explicit_self {
     fn clean(&self) -> SelfTy {
         match self.node {
             ast::sty_static => SelfStatic,
-            ast::sty_value => SelfValue,
-            ast::sty_uniq => SelfOwned,
+            ast::sty_value(_) => SelfValue,
+            ast::sty_uniq(_) => SelfOwned,
             ast::sty_region(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
             ast::sty_box(mt) => SelfManaged(mt.clean()),
         }
@@ -1171,7 +1171,7 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
 
     let (def_id, kind) = match *d {
         ast::DefFn(i, _) => (i, TypeFunction),
-        ast::DefSelf(i) | ast::DefSelfTy(i) => return Self(i),
+        ast::DefSelf(i, _) | ast::DefSelfTy(i) => return Self(i),
         ast::DefTy(i) => (i, TypeEnum),
         ast::DefTrait(i) => {
             debug!("saw DefTrait in def_to_id");
diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs
index 1f5802927a6..c67b6f52c7e 100644
--- a/src/librustpkg/api.rs
+++ b/src/librustpkg/api.rs
@@ -12,22 +12,35 @@ use context::*;
 use crate::*;
 use package_id::*;
 use package_source::*;
+use path_util::{platform_library_name, target_build_dir};
 use target::*;
 use version::Version;
+use workspace::pkg_parent_workspaces;
 use workcache_support::*;
+pub use path_util::default_workspace;
 
 pub use source_control::{safe_git_clone, git_clone_url};
 
-use std::os;
+use std::{os, run};
 use extra::arc::{Arc,RWArc};
 use extra::workcache;
 use extra::workcache::{Database, Logger, FreshnessMap};
 use extra::treemap::TreeMap;
 
+// A little sad -- duplicated from rustc::back::*
+#[cfg(target_arch = "arm")]
+fn cc_args() -> ~[~str] { ~[~"-marm"] }
+#[cfg(target_arch = "mips")]
+fn cc_args() -> ~[~str] { ~[] }
+#[cfg(target_arch = "x86")]
+fn cc_args() -> ~[~str] { ~[~"-m32"] }
+#[cfg(target_arch = "x86_64")]
+fn cc_args() -> ~[~str] { ~[~"-m64"] }
+
 /// Convenience functions intended for calling from pkg.rs
 /// p is where to put the cache file for dependencies
-pub fn default_context(p: Path) -> BuildContext {
-    new_default_context(new_workcache_context(&p), p)
+pub fn default_context(sysroot: Path, p: Path) -> BuildContext {
+    new_default_context(new_workcache_context(&p), sysroot)
 }
 
 pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
@@ -68,7 +81,7 @@ pub fn new_workcache_context(p: &Path) -> workcache::Context {
 
 pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
                  lib: Path) {
-    let cx = default_context(sysroot);
+    let cx = default_context(sysroot, root.clone());
     let pkg_src = PkgSrc {
         source_workspace: root.clone(),
         build_in_destination: false,
@@ -81,12 +94,12 @@ pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
         tests: ~[],
         benchs: ~[]
     };
-    pkg_src.build(&cx, ~[]);
+    pkg_src.build(&cx, ~[], []);
 }
 
 pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
                  main: Path) {
-    let cx = default_context(sysroot);
+    let cx = default_context(sysroot, root.clone());
     let pkg_src = PkgSrc {
         source_workspace: root.clone(),
         build_in_destination: false,
@@ -100,13 +113,76 @@ pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
         benchs: ~[]
     };
 
-    pkg_src.build(&cx, ~[]);
+    pkg_src.build(&cx, ~[], []);
 }
 
-pub fn install_pkg(sysroot: Path, workspace: Path, name: ~str, version: Version) {
-    let cx = default_context(sysroot);
+pub fn install_pkg(cx: &BuildContext,
+                   workspace: Path,
+                   name: ~str,
+                   version: Version,
+                   // For now, these inputs are assumed to be inputs to each of the crates
+                   more_inputs: ~[(~str, Path)]) { // pairs of Kind and Path
     let pkgid = PkgId{ version: version, ..PkgId::new(name)};
-    cx.install(PkgSrc::new(workspace.clone(), workspace, false, pkgid), &Everything);
+    cx.install(PkgSrc::new(workspace.clone(), workspace, false, pkgid),
+               &WhatToBuild{ build_type: Inferred,
+                             inputs_to_discover: more_inputs,
+                             sources: Everything });
+}
+
+/// Builds an arbitrary library whose short name is `output`,
+/// by invoking `tool` with arguments `args` plus "-o %s", where %s
+/// is the platform-specific library name for `output`.
+/// Returns that platform-specific name.
+pub fn build_library_in_workspace(exec: &mut workcache::Exec,
+                                  context: &mut Context,
+                                  package_name: &str,
+                                  tool: &str,
+                                  flags: &[~str],
+                                  paths: &[~str],
+                                  output: &str) -> ~str {
+    use command_failed = conditions::command_failed::cond;
+
+    let workspace = my_workspace(context, package_name);
+    let workspace_build_dir = target_build_dir(&workspace);
+    let out_name = workspace_build_dir.join_many([package_name.to_str(),
+                                                  platform_library_name(output)]);
+    // make paths absolute
+    let pkgid = PkgId::new(package_name);
+    let absolute_paths = paths.map(|s| {
+            let whatever = workspace.join_many([~"src",
+                                pkgid.to_str(),
+                                s.to_owned()]);
+            whatever.as_str().unwrap().to_owned()
+        });
+
+    let cc_args = cc_args();
+
+    let all_args = flags + absolute_paths + cc_args +
+         ~[~"-o", out_name.as_str().unwrap().to_owned()];
+    let exit_code = run::process_status(tool, all_args);
+    if exit_code != 0 {
+        command_failed.raise((tool.to_owned(), all_args, exit_code))
+    }
+    else {
+        let out_name_str = out_name.as_str().unwrap().to_owned();
+        exec.discover_output("binary",
+                             out_name_str,
+                             digest_only_date(&out_name));
+        context.add_library_path(out_name.dir_path());
+        out_name_str
+    }
+}
+
+pub fn my_workspace(context: &Context, package_name: &str) -> Path {
+    use bad_pkg_id     = conditions::bad_pkg_id::cond;
+
+    // (this assumes no particular version is requested)
+    let pkgid = PkgId::new(package_name);
+    let workspaces = pkg_parent_workspaces(context, &pkgid);
+    if workspaces.is_empty() {
+        bad_pkg_id.raise((Path::new(package_name), package_name.to_owned()));
+    }
+    workspaces[0]
 }
 
 fn mk_crate(p: Path) -> Crate {
diff --git a/src/librustpkg/conditions.rs b/src/librustpkg/conditions.rs
index 01bd4e6736e..91edc275826 100644
--- a/src/librustpkg/conditions.rs
+++ b/src/librustpkg/conditions.rs
@@ -53,3 +53,9 @@ condition! {
 condition! {
     pub git_checkout_failed: (~str, Path) -> ();
 }
+
+condition! {
+    // str is output of applying the command (first component)
+    // to the args (second component)
+    pub command_failed: (~str, ~[~str], int) -> ~str;
+}
diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs
index 3f1f2a1f59d..72197219fc5 100644
--- a/src/librustpkg/context.rs
+++ b/src/librustpkg/context.rs
@@ -54,6 +54,15 @@ impl BuildContext {
     pub fn compile_upto(&self) -> StopBefore {
         self.context.compile_upto()
     }
+
+    pub fn add_library_path(&mut self, p: Path) {
+        debug!("Adding library path: {}", p.display());
+        self.context.add_library_path(p);
+    }
+
+    pub fn additional_library_paths(&self) -> ~[Path] {
+        self.context.rustc_flags.additional_library_paths.clone()
+    }
 }
 
 /*
@@ -85,6 +94,9 @@ pub struct RustcFlags {
     target: Option<~str>,
     // Target CPU (defaults to rustc's default target CPU)
     target_cpu: Option<~str>,
+    // Additional library directories, which get passed with the -L flag
+    // This can't be set with a rustpkg flag, only from package scripts
+    additional_library_paths: ~[Path],
     // Any -Z features
     experimental_features: Option<~[~str]>
 }
@@ -99,6 +111,7 @@ impl Clone for RustcFlags {
             save_temps: self.save_temps,
             target: self.target.clone(),
             target_cpu: self.target_cpu.clone(),
+            additional_library_paths: self.additional_library_paths.clone(),
             experimental_features: self.experimental_features.clone()
         }
     }
@@ -148,6 +161,10 @@ impl Context {
     pub fn compile_upto(&self) -> StopBefore {
         self.rustc_flags.compile_upto
     }
+
+    pub fn add_library_path(&mut self, p: Path) {
+        self.rustc_flags.additional_library_paths.push(p);
+    }
 }
 
 /// We assume that if ../../rustc exists, then we're running
@@ -210,6 +227,7 @@ impl RustcFlags {
             save_temps: false,
             target: None,
             target_cpu: None,
+            additional_library_paths: ~[],
             experimental_features: None
         }
     }
diff --git a/src/librustpkg/package_source.rs b/src/librustpkg/package_source.rs
index 68d2d9662e3..17ba79862e0 100644
--- a/src/librustpkg/package_source.rs
+++ b/src/librustpkg/package_source.rs
@@ -23,7 +23,7 @@ use path_util::{find_dir_using_rust_path_hack, make_dir_rwx_recursive, default_w
 use path_util::{target_build_dir, versionize, dir_has_crate_file};
 use util::{compile_crate, DepMap};
 use workcache_support;
-use workcache_support::crate_tag;
+use workcache_support::{digest_only_date, digest_file_with_date, crate_tag};
 use extra::workcache;
 use extra::treemap::TreeMap;
 
@@ -390,7 +390,8 @@ impl PkgSrc {
                     deps: &mut DepMap,
                     crates: &[Crate],
                     cfgs: &[~str],
-                    what: OutputType) {
+                    what: OutputType,
+                    inputs_to_discover: &[(~str, Path)]) {
         for crate in crates.iter() {
             let path = self.start_dir.join(&crate.file);
             debug!("build_crates: compiling {}", path.display());
@@ -408,7 +409,19 @@ impl PkgSrc {
                 let sub_dir = self.build_workspace().clone();
                 let sub_flags = crate.flags.clone();
                 let sub_deps = deps.clone();
+                let inputs = inputs_to_discover.map(|&(ref k, ref p)|
+                                                    (k.clone(), p.as_str().unwrap().to_owned()));
                 do prep.exec |exec| {
+                    for &(ref kind, ref p) in inputs.iter() {
+                        let pth = Path::new(p.clone());
+                        exec.discover_input(*kind, *p, if *kind == ~"file" {
+                                digest_file_with_date(&pth)
+                            } else if *kind == ~"binary" {
+                                digest_only_date(&Path::new(p.clone()))
+                            } else {
+                                fail!("Bad kind in build_crates")
+                            });
+                    }
                     let result = compile_crate(&subcx,
                                                exec,
                                                &id,
@@ -452,22 +465,43 @@ impl PkgSrc {
                  build_context: &BuildContext,
                  // DepMap is a map from str (crate name) to (kind, name) --
                  // it tracks discovered dependencies per-crate
-                 cfgs: ~[~str]) -> DepMap {
+                 cfgs: ~[~str],
+                 inputs_to_discover: &[(~str, Path)]) -> DepMap {
         let mut deps = TreeMap::new();
-
         let libs = self.libs.clone();
         let mains = self.mains.clone();
         let tests = self.tests.clone();
         let benchs = self.benchs.clone();
         debug!("Building libs in {}, destination = {}",
-               self.source_workspace.display(), self.build_workspace().display());
-        self.build_crates(build_context, &mut deps, libs, cfgs, Lib);
+               self.destination_workspace.display(),
+               self.destination_workspace.display());
+        self.build_crates(build_context,
+                          &mut deps,
+                          libs,
+                          cfgs,
+                          Lib,
+                          inputs_to_discover);
         debug!("Building mains");
-        self.build_crates(build_context, &mut deps, mains, cfgs, Main);
+        self.build_crates(build_context,
+                          &mut deps,
+                          mains,
+                          cfgs,
+                          Main,
+                          inputs_to_discover);
         debug!("Building tests");
-        self.build_crates(build_context, &mut deps, tests, cfgs, Test);
+        self.build_crates(build_context,
+                          &mut deps,
+                          tests,
+                          cfgs,
+                          Test,
+                          inputs_to_discover);
         debug!("Building benches");
-        self.build_crates(build_context, &mut deps, benchs, cfgs, Bench);
+        self.build_crates(build_context,
+                          &mut deps,
+                          benchs,
+                          cfgs,
+                          Bench,
+                          inputs_to_discover);
         deps
     }
 
diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs
index c47c89d777b..a48ef23115c 100644
--- a/src/librustpkg/path_util.rs
+++ b/src/librustpkg/path_util.rs
@@ -461,7 +461,6 @@ pub fn versionize(p: &Path, v: &Version) -> Path {
     p.with_filename(q)
 }
 
-
 #[cfg(target_os = "win32")]
 pub fn chmod_read_only(p: &Path) -> bool {
     #[fixed_stack_segment];
@@ -483,3 +482,6 @@ pub fn chmod_read_only(p: &Path) -> bool {
     }
 }
 
+pub fn platform_library_name(s: &str) -> ~str {
+    format!("{}{}{}", os::consts::DLL_PREFIX, s, os::consts::DLL_SUFFIX)
+}
diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs
index 6c55f7af0c0..37a5a2ea711 100644
--- a/src/librustpkg/rustpkg.rs
+++ b/src/librustpkg/rustpkg.rs
@@ -33,7 +33,6 @@ use rustc::metadata::filesearch;
 use rustc::metadata::filesearch::rust_path;
 use extra::{getopts};
 use syntax::{ast, diagnostic};
-use util::*;
 use messages::{error, warn, note};
 use path_util::{build_pkg_id_in_workspace, built_test_in_workspace};
 use path_util::{U_RWX, in_rust_path};
@@ -47,15 +46,16 @@ use context::{Context, BuildContext,
                        LLVMAssemble, LLVMCompileBitcode};
 use package_id::PkgId;
 use package_source::PkgSrc;
-use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench, Tests};
+use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
+use target::{Tests, MaybeCustom, Inferred, JustOne};
 use workcache_support::digest_only_date;
 use exit_codes::{COPY_FAILED_CODE, BAD_FLAG_CODE};
 
 pub mod api;
 mod conditions;
-mod context;
+pub mod context;
 mod crate;
-mod exit_codes;
+pub mod exit_codes;
 mod installed_packages;
 mod messages;
 mod package_id;
@@ -67,7 +67,7 @@ mod target;
 #[cfg(test)]
 mod tests;
 mod util;
-mod version;
+pub mod version;
 pub mod workcache_support;
 mod workspace;
 
@@ -96,7 +96,7 @@ impl<'self> PkgScript<'self> {
     /// Given the path name for a package script
     /// and a package ID, parse the package script into
     /// a PkgScript that we can then execute
-    fn parse<'a>(sysroot: @Path,
+    fn parse<'a>(sysroot: Path,
                  script: Path,
                  workspace: &Path,
                  id: &'a PkgId) -> PkgScript<'a> {
@@ -107,7 +107,7 @@ impl<'self> PkgScript<'self> {
         debug!("pkgscript parse: {}", sysroot.display());
         let options = @session::options {
             binary: binary,
-            maybe_sysroot: Some(sysroot),
+            maybe_sysroot: Some(@sysroot),
             crate_type: session::bin_crate,
             .. (*session::basic_options()).clone()
         };
@@ -132,12 +132,7 @@ impl<'self> PkgScript<'self> {
         }
     }
 
-    /// Run the contents of this package script, where <what>
-    /// is the command to pass to it (e.g., "build", "clean", "install")
-    /// Returns a pair of an exit code and list of configs (obtained by
-    /// calling the package script's configs() function if it exists
-    fn run_custom(&mut self, exec: &mut workcache::Exec,
-                  sysroot: &Path) -> (~[~str], ExitCode) {
+    fn build_custom(&mut self, exec: &mut workcache::Exec) -> ~str {
         let sess = self.sess;
 
         debug!("Working directory = {}", self.build_dir.display());
@@ -152,17 +147,28 @@ impl<'self> PkgScript<'self> {
                                        &self.build_dir,
                                        sess,
                                        crate);
-        debug!("Running program: {} {} {}", exe.display(),
-               sysroot.display(), "install");
         // Discover the output
         // FIXME (#9639): This needs to handle non-utf8 paths
-        exec.discover_output("binary", exe.as_str().unwrap(), digest_only_date(&exe));
+        // Discover the output
+        exec.discover_output("binary", exe.as_str().unwrap().to_owned(), digest_only_date(&exe));
+        exe.as_str().unwrap().to_owned()
+    }
+
+
+    /// Run the contents of this package script, where <what>
+    /// is the command to pass to it (e.g., "build", "clean", "install")
+    /// Returns a pair of an exit code and list of configs (obtained by
+    /// calling the package script's configs() function if it exists
+    fn run_custom(exe: &Path, sysroot: &Path) -> (~[~str], int) {
+        debug!("Running program: {} {} {}", exe.as_str().unwrap().to_owned(),
+               sysroot.display(), "install");
         // FIXME #7401 should support commands besides `install`
         // FIXME (#9639): This needs to handle non-utf8 paths
         let status = run::process_status(exe.as_str().unwrap(),
                                          [sysroot.as_str().unwrap().to_owned(), ~"install"]);
         if status != 0 {
-            return (~[], status);
+            debug!("run_custom: first pkg command failed with {:?}", status);
+            (~[], status)
         }
         else {
             debug!("Running program (configs): {} {} {}",
@@ -170,6 +176,7 @@ impl<'self> PkgScript<'self> {
             // FIXME (#9639): This needs to handle non-utf8 paths
             let output = run::process_output(exe.as_str().unwrap(),
                                              [sysroot.as_str().unwrap().to_owned(), ~"configs"]);
+            debug!("run_custom: second pkg command did {:?}", output.status);
             // Run the configs() function to get the configs
             let cfgs = str::from_utf8_slice(output.output).word_iter()
                 .map(|w| w.to_owned()).collect();
@@ -263,7 +270,7 @@ impl CtxMethods for BuildContext {
         let cwd = os::getcwd();
         match cmd {
             "build" => {
-                self.build_args(args, &Everything);
+                self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything));
             }
             "clean" => {
                 if args.len() < 1 {
@@ -301,12 +308,14 @@ impl CtxMethods for BuildContext {
                             let inferred_pkgid =
                                 PkgId::new(cwd.filename_str().unwrap());
                             self.install(PkgSrc::new(cwd, default_workspace(),
-                                                     true, inferred_pkgid), &Everything);
+                                                     true, inferred_pkgid),
+                                         &WhatToBuild::new(MaybeCustom, Everything));
                         }
                         None  => { usage::install(); return; }
                         Some((ws, pkgid))                => {
                             let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, pkgid);
-                            self.install(pkg_src, &Everything);
+                            self.install(pkg_src, &WhatToBuild::new(MaybeCustom,
+                                                                    Everything));
                       }
                   }
                 }
@@ -320,7 +329,7 @@ impl CtxMethods for BuildContext {
                     if workspaces.is_empty() {
                         let d = default_workspace();
                         let src = PkgSrc::new(d.clone(), d, false, pkgid.clone());
-                        self.install(src, &Everything);
+                        self.install(src, &WhatToBuild::new(MaybeCustom, Everything));
                     }
                     else {
                         for workspace in workspaces.iter() {
@@ -331,7 +340,7 @@ impl CtxMethods for BuildContext {
                                                   dest,
                                                   self.context.use_rust_path_hack,
                                                   pkgid.clone());
-                            self.install(src, &Everything);
+                            self.install(src, &WhatToBuild::new(MaybeCustom, Everything));
                         };
                     }
                 }
@@ -354,7 +363,8 @@ impl CtxMethods for BuildContext {
             }
             "test" => {
                 // Build the test executable
-                let maybe_id_and_workspace = self.build_args(args, &Tests);
+                let maybe_id_and_workspace = self.build_args(args,
+                                                             &WhatToBuild::new(MaybeCustom, Tests));
                 match maybe_id_and_workspace {
                     Some((pkg_id, workspace)) => {
                         // Assuming it's built, run the tests
@@ -420,6 +430,7 @@ impl CtxMethods for BuildContext {
                 pkgid = {} pkgsrc start_dir = {}", workspace.display(),
                in_rust_path(&workspace), is_git_dir(&workspace.join(&pkgid.path)),
                pkgid.to_str(), pkg_src.start_dir.display());
+        debug!("build: what to build = {:?}", what_to_build);
 
         // If workspace isn't in the RUST_PATH, and it's a git repo,
         // then clone it into the first entry in RUST_PATH, and repeat
@@ -448,27 +459,27 @@ impl CtxMethods for BuildContext {
         debug!("Package source directory = {}", pkg_src.to_str());
         let opt = pkg_src.package_script_option();
         debug!("Calling pkg_script_option on {:?}", opt);
-        let cfgs = match pkg_src.package_script_option() {
-            Some(package_script_path) => {
+        let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) {
+            (Some(package_script_path), MaybeCustom)  => {
                 let sysroot = self.sysroot_to_use();
-                // FIXME (#9639): This needs to handle non-utf8 paths
-                let pkg_script_path_str = package_script_path.as_str().unwrap();
-                let (cfgs, hook_result) =
-                    do self.workcache_context.with_prep(pkg_script_path_str) |prep| {
-                    let sub_sysroot = sysroot.clone();
-                    let package_script_path_clone = package_script_path.clone();
-                    let sub_ws = workspace.clone();
-                    let sub_id = pkgid.clone();
-                    declare_package_script_dependency(prep, &*pkg_src);
+                // Build the package script if needed
+                let script_build = format!("build_package_script({})",
+                                           package_script_path.display());
+                let pkg_exe = do self.workcache_context.with_prep(script_build) |prep| {
+                    let subsysroot = sysroot.clone();
+                    let psp = package_script_path.clone();
+                    let ws = workspace.clone();
+                    let pid = pkgid.clone();
                     do prep.exec |exec| {
-                        let mut pscript = PkgScript::parse(@sub_sysroot.clone(),
-                                                          package_script_path_clone.clone(),
-                                                          &sub_ws,
-                                                          &sub_id);
-
-                        pscript.run_custom(exec, &sub_sysroot)
+                        let mut pscript = PkgScript::parse(subsysroot.clone(),
+                                                           psp.clone(),
+                                                           &ws,
+                                                           &pid);
+                        pscript.build_custom(exec)
                     }
                 };
+                // We always *run* the package script
+                let (cfgs, hook_result) = PkgScript::run_custom(&Path::new(pkg_exe), &sysroot);
                 debug!("Command return code = {:?}", hook_result);
                 if hook_result != 0 {
                     fail!("Error running custom build command")
@@ -477,7 +488,11 @@ impl CtxMethods for BuildContext {
                 // otherwise, the package script succeeded
                 cfgs
             }
-            None => {
+            (Some(_), Inferred) => {
+                debug!("There is a package script, but we're ignoring it");
+                ~[]
+            }
+            (None, _) => {
                 debug!("No package script, continuing");
                 ~[]
             }
@@ -486,13 +501,13 @@ impl CtxMethods for BuildContext {
         // If there was a package script, it should have finished
         // the build already. Otherwise...
         if !custom {
-            match what_to_build {
+            match what_to_build.sources {
                 // Find crates inside the workspace
-                &Everything => pkg_src.find_crates(),
+                Everything => pkg_src.find_crates(),
                 // Find only tests
-                &Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }),
+                Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }),
                 // Don't infer any crates -- just build the one that was requested
-                &JustOne(ref p) => {
+                JustOne(ref p) => {
                     // We expect that p is relative to the package source's start directory,
                     // so check that assumption
                     debug!("JustOne: p = {}", p.display());
@@ -512,7 +527,7 @@ impl CtxMethods for BuildContext {
                 }
             }
             // Build it!
-            pkg_src.build(self, cfgs);
+            pkg_src.build(self, cfgs, []);
         }
     }
 
@@ -551,6 +566,8 @@ impl CtxMethods for BuildContext {
         // just means inferring all the crates in it, then building each one.
         self.build(&mut pkg_src, what);
 
+        debug!("Done building package source {}", pkg_src.to_str());
+
         let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(),
                       pkg_src.tests.clone(), pkg_src.benchs.clone()];
         debug!("In declare inputs for {}", id.to_str());
@@ -823,6 +840,7 @@ pub fn main_args(args: &[~str]) -> int {
         save_temps: save_temps,
         target: target,
         target_cpu: target_cpu,
+        additional_library_paths: ~[], // No way to set this from the rustpkg command line
         experimental_features: experimental_features
     };
 
@@ -895,7 +913,8 @@ pub fn main_args(args: &[~str]) -> int {
                 use_rust_path_hack: use_rust_path_hack,
                 sysroot: sroot.clone(), // Currently, only tests override this
             },
-            workcache_context: api::default_context(default_workspace()).workcache_context
+            workcache_context: api::default_context(sroot.clone(),
+                                                    default_workspace()).workcache_context
         }.run(sub_cmd, rm_args.clone())
     };
     // FIXME #9262: This is using the same error code for all errors,
diff --git a/src/librustpkg/target.rs b/src/librustpkg/target.rs
index b21641a5e53..9863fd0a89e 100644
--- a/src/librustpkg/target.rs
+++ b/src/librustpkg/target.rs
@@ -23,7 +23,31 @@ pub enum Target {
 }
 
 #[deriving(Eq, Clone)]
-pub enum WhatToBuild {
+pub struct WhatToBuild {
+    build_type: BuildType, // Whether or not to ignore the pkg.rs file
+    sources: SourceType, // Which crates to build
+    inputs_to_discover: ~[(~str, Path)] // Inputs to these crates to be discovered
+        // (For now all of these inputs will be taken as discovered inputs
+        // for all of the crates)
+        // (Paired with their kinds)
+}
+
+impl WhatToBuild {
+    pub fn new(build_type: BuildType, sources: SourceType) -> WhatToBuild {
+        WhatToBuild { build_type: build_type,
+                      sources: sources,
+                      inputs_to_discover: ~[] }
+    }
+}
+
+#[deriving(Eq, Clone)]
+pub enum BuildType {
+    Inferred, // Ignore the pkg.rs file even if one exists
+    MaybeCustom // Use the pkg.rs file if it exists
+}
+
+#[deriving(Eq, Clone)]
+pub enum SourceType {
     /// Build just one lib.rs file in `path`, which is relative to the active workspace's src/ dir
     JustOne(Path),
     /// Build any test.rs files that can be recursively found in the active workspace
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index 58c6b4ff81f..16e13f70092 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -28,7 +28,7 @@ use path_util::{target_executable_in_workspace, target_test_in_workspace,
                library_in_workspace, installed_library_in_workspace,
                built_bench_in_workspace, built_test_in_workspace,
                built_library_in_workspace, built_executable_in_workspace, target_build_dir,
-               chmod_read_only};
+               chmod_read_only, platform_library_name};
 use rustc::back::link::get_cc_prog;
 use rustc::metadata::filesearch::rust_path;
 use rustc::driver::driver::{build_session, build_session_options, host_triple, optgroups};
@@ -299,12 +299,6 @@ fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~s
                     cmd, args, str::from_utf8(output.output),
                    str::from_utf8(output.error),
                    output.status);
-/*
-By the way, rustpkg *won't* return a nonzero exit code if it fails --
-see #4547
-So tests that use this need to check the existence of a file
-to make sure the command succeeded
-*/
     if output.status != 0 {
         debug!("Command {} {:?} failed with exit code {:?}; its output was --- {} ---",
               cmd, args, output.status,
@@ -600,7 +594,7 @@ fn test_install_valid() {
                           temp_workspace.clone(),
                           false,
                           temp_pkg_id.clone());
-    ctxt.install(src, &Everything);
+    ctxt.install(src, &WhatToBuild::new(MaybeCustom, Everything));
     // Check that all files exist
     let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace);
     debug!("exec = {}", exec.display());
@@ -639,7 +633,7 @@ fn test_install_invalid() {
                                   temp_workspace.clone(),
                                   false,
                                   pkgid.clone());
-        ctxt.install(pkg_src, &Everything);
+        ctxt.install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything));
     };
     // Not the best test -- doesn't test that we failed in the right way.
     // Best we can do for now.
@@ -897,14 +891,14 @@ fn rustpkg_local_pkg() {
 }
 
 #[test]
-#[ignore (reason = "test makes bogus assumptions about build directory layout: issue #8690")]
 fn package_script_with_default_build() {
     let dir = create_local_package(&PkgId::new("fancy-lib"));
     let dir = dir.path();
     debug!("dir = {}", dir.display());
     let mut source = test_sysroot().dir_path();
     source.pop(); source.pop();
-    source.push_many(["src", "librustpkg", "testsuite", "pass", "src", "fancy-lib", "pkg.rs"]);
+    let source = Path::new(file!()).dir_path().join_many(
+        [~"testsuite", ~"pass", ~"src", ~"fancy-lib", ~"pkg.rs"]);
     debug!("package_script_with_default_build: {}", source.display());
     if !os::copy_file(&source,
                       &dir.join_many(["src", "fancy-lib-0.1", "pkg.rs"])) {
@@ -912,7 +906,10 @@ fn package_script_with_default_build() {
     }
     command_line_test([~"install", ~"fancy-lib"], dir);
     assert_lib_exists(dir, &Path::new("fancy-lib"), NoVersion);
-    assert!(os::path_exists(&target_build_dir(dir).join_many(["fancy-lib", "generated.rs"])));
+    assert!(os::path_exists(&target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"])));
+    let generated_path = target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]);
+    debug!("generated path = {}", generated_path.display());
+    assert!(os::path_exists(&generated_path));
 }
 
 #[test]
@@ -2251,6 +2248,106 @@ fn find_sources_in_cwd() {
     assert_executable_exists(&source_dir.join(".rust"), "foo");
 }
 
+#[test]
+fn test_c_dependency_ok() {
+    // Pkg has a custom build script that adds a single C file as a dependency, and
+    // registers a hook to build it if it's not fresh
+    // After running `build`, test that the C library built
+
+    let dir = create_local_package(&PkgId::new("cdep"));
+    let dir = dir.path();
+    writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
+              "#[link_args = \"-lfoo\"]\nextern { fn f(); } \
+              \n#[fixed_stack_segment]\nfn main() { unsafe { f(); } }");
+    writeFile(&dir.join_many(["src", "cdep-0.1", "foo.c"]), "void f() {}");
+
+    debug!("dir = {}", dir.display());
+    let source = Path::new(file!()).dir_path().join_many(
+        [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
+    if !os::copy_file(&source,
+                      &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"])) {
+        fail!("Couldn't copy file");
+    }
+    command_line_test([~"build", ~"cdep"], dir);
+    assert_executable_exists(dir, "cdep");
+    let out_dir = target_build_dir(dir).join("cdep");
+    let c_library_path = out_dir.join(platform_library_name("foo"));
+    debug!("c library path: {}", c_library_path.display());
+    assert!(os::path_exists(&c_library_path));
+}
+
+#[test]
+fn test_c_dependency_no_rebuilding() {
+    let dir = create_local_package(&PkgId::new("cdep"));
+    let dir = dir.path();
+    writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
+              "#[link_args = \"-lfoo\"]\nextern { fn f(); } \
+              \n#[fixed_stack_segment]\nfn main() { unsafe { f(); } }");
+    writeFile(&dir.join_many(["src", "cdep-0.1", "foo.c"]), "void f() {}");
+
+    debug!("dir = {}", dir.display());
+    let source = Path::new(file!()).dir_path().join_many(
+        [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
+    if !os::copy_file(&source,
+                      &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"])) {
+        fail!("Couldn't copy file");
+    }
+    command_line_test([~"build", ~"cdep"], dir);
+    assert_executable_exists(dir, "cdep");
+    let out_dir = target_build_dir(dir).join("cdep");
+    let c_library_path = out_dir.join(platform_library_name("foo"));
+    debug!("c library path: {}", c_library_path.display());
+    assert!(os::path_exists(&c_library_path));
+
+    // Now, make it read-only so rebuilding will fail
+    assert!(chmod_read_only(&c_library_path));
+
+    match command_line_test_partial([~"build", ~"cdep"], dir) {
+        Success(*) => (), // ok
+        Fail(status) if status == 65 => fail!("test_c_dependency_no_rebuilding failed: \
+                                              it tried to rebuild foo.c"),
+        Fail(_) => fail!("test_c_dependency_no_rebuilding failed for some other reason")
+    }
+}
+
+#[test]
+fn test_c_dependency_yes_rebuilding() {
+    let dir = create_local_package(&PkgId::new("cdep"));
+    let dir = dir.path();
+    writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
+              "#[link_args = \"-lfoo\"]\nextern { fn f(); } \
+              \n#[fixed_stack_segment]\nfn main() { unsafe { f(); } }");
+    let c_file_name = dir.join_many(["src", "cdep-0.1", "foo.c"]);
+    writeFile(&c_file_name, "void f() {}");
+
+    let source = Path::new(file!()).dir_path().join_many(
+        [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
+    let target = dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]);
+    debug!("Copying {} -> {}", source.display(), target.display());
+    if !os::copy_file(&source, &target) {
+        fail!("Couldn't copy file");
+    }
+    command_line_test([~"build", ~"cdep"], dir);
+    assert_executable_exists(dir, "cdep");
+    let out_dir = target_build_dir(dir).join("cdep");
+    let c_library_path = out_dir.join(platform_library_name("foo"));
+    debug!("c library path: {}", c_library_path.display());
+    assert!(os::path_exists(&c_library_path));
+
+    // Now, make the Rust library read-only so rebuilding will fail
+    match built_library_in_workspace(&PkgId::new("cdep"), dir) {
+        Some(ref pth) => assert!(chmod_read_only(pth)),
+        None => assert_built_library_exists(dir, "cdep")
+    }
+
+    match command_line_test_partial([~"build", ~"cdep"], dir) {
+        Success(*) => fail!("test_c_dependency_yes_rebuilding failed: \
+                            it didn't rebuild and should have"),
+        Fail(status) if status == 65 => (),
+        Fail(_) => fail!("test_c_dependency_yes_rebuilding failed for some other reason")
+    }
+}
+
 /// Returns true if p exists and is executable
 fn is_executable(p: &Path) -> bool {
     use std::libc::consts::os::posix88::{S_IXUSR};
diff --git a/src/librustpkg/testsuite/pass/src/c-dependencies/bar.rs b/src/librustpkg/testsuite/pass/src/c-dependencies/bar.rs
new file mode 100644
index 00000000000..ffbc6e2a7f9
--- /dev/null
+++ b/src/librustpkg/testsuite/pass/src/c-dependencies/bar.rs
@@ -0,0 +1,13 @@
+// Copyright 2013 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.
+
+pub fn assert_true() {
+    assert!(true);
+}
diff --git a/src/librustpkg/testsuite/pass/src/c-dependencies/foo.rs b/src/librustpkg/testsuite/pass/src/c-dependencies/foo.rs
new file mode 100644
index 00000000000..542a6af402d
--- /dev/null
+++ b/src/librustpkg/testsuite/pass/src/c-dependencies/foo.rs
@@ -0,0 +1,12 @@
+// Copyright 2013 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.
+
+pub fn do_nothing() {
+}
\ No newline at end of file
diff --git a/src/librustpkg/testsuite/pass/src/c-dependencies/lib.rs b/src/librustpkg/testsuite/pass/src/c-dependencies/lib.rs
new file mode 100644
index 00000000000..bd1cb240a34
--- /dev/null
+++ b/src/librustpkg/testsuite/pass/src/c-dependencies/lib.rs
@@ -0,0 +1,14 @@
+// Copyright 2013 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 mod std;
+
+pub mod foo;
+pub mod bar;
diff --git a/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs b/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs
new file mode 100644
index 00000000000..b667dc0a576
--- /dev/null
+++ b/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs
@@ -0,0 +1,83 @@
+// Copyright 2013 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 mod rustpkg;
+extern mod rustc;
+
+use std::{io, os, task};
+use rustpkg::api;
+use rustpkg::version::NoVersion;
+use rustpkg::workcache_support::digest_file_with_date;
+use rustpkg::exit_codes::COPY_FAILED_CODE;
+
+pub fn main() {
+    let args = os::args();
+
+// by convention, first arg is sysroot
+    if args.len() < 2 {
+        fail!("Package script requires a directory where rustc libraries live as the first \
+               argument");
+    }
+
+    let path_for_db = api::default_workspace();
+    debug!("path_for_db = {}", path_for_db.display());
+
+    let sysroot_arg = args[1].clone();
+    let sysroot = Path::new(sysroot_arg);
+    if !os::path_exists(&sysroot) {
+        fail!("Package script requires a sysroot that exists; {} doesn't", sysroot.display());
+    }
+
+    if args[2] != ~"install" {
+        io::println(format!("Warning: I don't know how to {}", args[2]));
+        return;
+    }
+
+    let mut context = api::default_context(sysroot, path_for_db);
+    let my_workspace = api::my_workspace(&context.context, "cdep");
+    let foo_c_name = my_workspace.join_many(["src", "cdep-0.1", "foo.c"]);
+
+    let out_lib_path = do context.workcache_context.with_prep("foo.c") |prep| {
+        let sub_cx = context.context.clone();
+        debug!("foo_c_name = {}", foo_c_name.display());
+        prep.declare_input("file",
+                           foo_c_name.as_str().unwrap().to_owned(),
+                           digest_file_with_date(&foo_c_name));
+        let out_path = do prep.exec |exec| {
+            let out_path = api::build_library_in_workspace(exec,
+                                                           &mut sub_cx.clone(),
+                                                           "cdep",
+                                                           "gcc",
+                                                           [~"-c"],
+                                                           [~"foo.c"],
+                                                           "foo");
+            let out_p = Path::new(out_path);
+            out_p.as_str().unwrap().to_owned()
+        };
+        out_path
+    };
+    let out_lib_path = Path::new(out_lib_path);
+    debug!("out_lib_path = {}", out_lib_path.display());
+    context.add_library_path(out_lib_path.dir_path());
+
+    let context_clone = context.clone();
+    let task_res = do task::try {
+        let mut cc = context_clone.clone();
+        api::install_pkg(&mut cc,
+                         os::getcwd(),
+                         ~"cdep",
+                         NoVersion,
+                         ~[(~"binary", out_lib_path.clone()), (~"file", foo_c_name.clone())]);
+    };
+
+    if task_res.is_err() {
+        os::set_exit_status(COPY_FAILED_CODE);
+    }
+}
diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/lib.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/lib.rs
index dc068eed143..17386cd03c2 100644
--- a/src/librustpkg/testsuite/pass/src/fancy-lib/lib.rs
+++ b/src/librustpkg/testsuite/pass/src/fancy-lib/lib.rs
@@ -21,4 +21,4 @@ extern mod std;
 
 pub mod foo;
 pub mod bar;
-#[path = "../../build/fancy_lib/generated.rs"] pub mod generated;
+#[path = "../../build/fancy-lib/generated.rs"] pub mod generated;
diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
index db11ffa0cc6..0b838b3e0f9 100644
--- a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
+++ b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
@@ -15,42 +15,37 @@ use std::{io, os};
 use rustpkg::api;
 use rustpkg::version::NoVersion;
 
-use rustc::metadata::filesearch;
-
 pub fn main() {
-    use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
     let args = os::args();
 
 // by convention, first arg is sysroot
     if args.len() < 2 {
+        debug!("Failing, arg len");
         fail!("Package script requires a directory where rustc libraries live as the first \
                argument");
     }
 
     let sysroot_arg = args[1].clone();
-    let sysroot = Path(sysroot_arg);
+    let sysroot = Path::new(sysroot_arg);
     if !os::path_exists(&sysroot) {
-        fail!("Package script requires a sysroot that exists; %s doesn't", sysroot.to_str());
+        debug!("Failing, sysroot");
+        fail!("Package script requires a sysroot that exists;{} doesn't", sysroot.display());
     }
 
     if args[2] != ~"install" {
+        debug!("Failing, weird command");
         println!("Warning: I don't know how to {}", args[2]);
         return;
     }
 
-    let out_path = Path("build/fancy-lib");
-    if !os::path_exists(&out_path) {
-        assert!(os::make_dir(&out_path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-    }
-
-    let file = io::file_writer(&out_path.push("generated.rs"),
-                               [io::Create]).unwrap();
-    file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }");
-
+    debug!("Checking self_exe_path");
+    let out_path = os::self_exe_path().expect("Couldn't get self_exe path");
 
-    debug!("api_____install_____lib, my sysroot:");
-    debug!(sysroot.to_str());
+    debug!("Writing file");
+    let file = io::file_writer(&out_path.join("generated.rs"), [io::Create]).unwrap();
+    file.write_str("pub fn wheeeee() { let xs = [1, 2, 3]; \
+                   for _ in xs.iter() { assert!(true); } }");
 
-    api::install_lib(@sysroot, os::getcwd(), ~"fancy-lib", Path("lib.rs"),
-                     NoVersion);
+    let context = api::default_context(sysroot, api::default_workspace());
+    api::install_pkg(&context, os::getcwd(), ~"fancy-lib", NoVersion, ~[]);
 }
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 9144c08cb73..3824f6d38de 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -27,11 +27,13 @@ use context::{in_target, StopBefore, Link, Assemble, BuildContext};
 use package_id::PkgId;
 use package_source::PkgSrc;
 use workspace::pkg_parent_workspaces;
-use path_util::{U_RWX, system_library, target_build_dir};
+use path_util::{system_library, target_build_dir};
 use path_util::{default_workspace, built_library_in_workspace};
 pub use target::{OutputType, Main, Lib, Bench, Test, JustOne, lib_name_of, lib_crate_filename};
 pub use target::{Target, Build, Install};
 use extra::treemap::TreeMap;
+use path_util::U_RWX;
+pub use target::{lib_name_of, lib_crate_filename, WhatToBuild, MaybeCustom, Inferred};
 use workcache_support::{digest_file_with_date, digest_only_date};
 
 // It would be nice to have the list of commands in just one place -- for example,
@@ -233,12 +235,14 @@ pub fn compile_input(context: &BuildContext,
         Nothing => link::output_type_exe
     };
 
+    debug!("Output type = {:?}", output_type);
+
     let options = @session::options {
         crate_type: crate_type,
         optimize: if opt { session::Aggressive } else { session::No },
         test: what == Test || what == Bench,
         maybe_sysroot: Some(sysroot_to_use),
-        addl_lib_search_paths: @mut (~[]),
+        addl_lib_search_paths: @mut context.additional_library_paths(),
         output_type: output_type,
         .. (*driver::build_session_options(binary,
                                            &matches,
@@ -246,6 +250,8 @@ pub fn compile_input(context: &BuildContext,
                                             @diagnostic::Emitter)).clone()
     };
 
+    debug!("Created options...");
+
     let addl_lib_search_paths = @mut options.addl_lib_search_paths;
     // Make sure all the library directories actually exist, since the linker will complain
     // otherwise
@@ -258,16 +264,22 @@ pub fn compile_input(context: &BuildContext,
         }
     }
 
+    debug!("About to build session...");
+
     let sess = driver::build_session(options,
                                      @diagnostic::DefaultEmitter as
                                         @diagnostic::Emitter);
 
+    debug!("About to build config...");
+
     // Infer dependencies that rustpkg needs to build, by scanning for
     // `extern mod` directives.
     let cfg = driver::build_configuration(sess);
     let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
     crate = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate);
 
+    debug!("About to call find_and_install_dependencies...");
+
     find_and_install_dependencies(context, pkg_id, in_file, sess, exec, &crate, deps,
                                   |p| {
                                       debug!("a dependency: {}", p.display());
@@ -377,7 +389,6 @@ pub fn compile_crate_from_input(input: &Path,
 
     debug!("Built {}, date = {:?}", outputs.out_filename.display(),
            datestamp(&outputs.out_filename));
-
     Some(outputs.out_filename)
 }
 
@@ -431,7 +442,9 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
                 };
                 debug!("Finding and installing... {}", lib_name);
                 // Check standard Rust library path first
-                match system_library(&self.context.sysroot(), lib_name) {
+                let whatever = system_library(&self.context.sysroot(), lib_name);
+                debug!("system library returned {:?}", whatever);
+                match whatever {
                     Some(ref installed_path) => {
                         debug!("It exists: {}", installed_path.display());
                         // Say that [path for c] has a discovered dependency on
@@ -478,7 +491,10 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
                                                   self.context.context.use_rust_path_hack,
                                                   pkg_id.clone());
                         let (outputs_disc, inputs_disc) =
-                            self.context.install(pkg_src, &JustOne(Path::new(lib_crate_filename)));
+                            self.context.install(
+                                pkg_src,
+                                &WhatToBuild::new(Inferred,
+                                                  JustOne(Path::new(lib_crate_filename))));
                         debug!("Installed {}, returned {:?} dependencies and \
                                {:?} transitive dependencies",
                                lib_name, outputs_disc.len(), inputs_disc.len());
diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs
index e7fa81fc87a..9d5c9c1a5cd 100644
--- a/src/libstd/fmt/mod.rs
+++ b/src/libstd/fmt/mod.rs
@@ -490,7 +490,6 @@ pub struct Formatter<'self> {
 
     /// Output buffer.
     buf: &'self mut io::Writer,
-
     priv curarg: vec::VecIterator<'self, Argument<'self>>,
     priv args: &'self [Argument<'self>],
 }
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index 94a6b7cfea8..4e55c5fe60e 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -1009,7 +1009,7 @@ impl<R:Reader,C> Reader for Wrapper<R, C> {
 }
 
 pub struct FILERes {
-    f: *libc::FILE,
+    priv f: *libc::FILE,
 }
 
 impl FILERes {
@@ -1282,7 +1282,7 @@ impl Writer for fd_t {
 }
 
 pub struct FdRes {
-    fd: fd_t,
+    priv fd: fd_t,
 }
 
 impl FdRes {
@@ -1792,7 +1792,7 @@ pub mod fsync {
 
     // Artifacts that need to fsync on destruction
     pub struct Res<t> {
-        arg: Arg<t>,
+        priv arg: Arg<t>,
     }
 
     impl <t> Res<t> {
@@ -1815,9 +1815,9 @@ pub mod fsync {
     }
 
     pub struct Arg<t> {
-        val: t,
-        opt_level: Option<Level>,
-        fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
+        priv val: t,
+        priv opt_level: Option<Level>,
+        priv fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
     }
 
     // fsync file after executing blk
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
index 01af3d93157..771be3b2a13 100644
--- a/src/libstd/iter.rs
+++ b/src/libstd/iter.rs
@@ -1790,9 +1790,9 @@ impl<'self, A, St> Iterator<A> for Unfold<'self, A, St> {
 #[deriving(Clone)]
 pub struct Counter<A> {
     /// The current state the counter is at (next value to be yielded)
-    state: A,
+    priv state: A,
     /// The amount that this iterator is stepping by
-    step: A
+    priv step: A
 }
 
 /// Creates a new counter with the specified start/step
diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs
index 0902100dca6..e7bcf8ce5d3 100644
--- a/src/libstd/rand/distributions.rs
+++ b/src/libstd/rand/distributions.rs
@@ -8,38 +8,226 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Sampling from random distributions
+/*!
+Sampling from random distributions.
 
-// Some implementations use the Ziggurat method
-// https://en.wikipedia.org/wiki/Ziggurat_algorithm
-//
-// The version used here is ZIGNOR [Doornik 2005, "An Improved
-// Ziggurat Method to Generate Normal Random Samples"] which is slower
-// (about double, it generates an extra random number) than the
-// canonical version [Marsaglia & Tsang 2000, "The Ziggurat Method for
-// Generating Random Variables"], but more robust. If one wanted, one
-// could implement VIZIGNOR the ZIGNOR paper for more speed.
+This is a generalization of `Rand` to allow parameters to control the
+exact properties of the generated values, e.g. the mean and standard
+deviation of a normal distribution. The `Sample` trait is the most
+general, and allows for generating values that change some state
+internally. The `IndependentSample` trait is for generating values
+that do not need to record state.
+
+*/
 
+use iter::range;
+use option::{Some, None};
 use num;
 use rand::{Rng,Rand};
+use clone::Clone;
+
+pub use self::range::Range;
+
+pub mod range;
+
+/// Types that can be used to create a random instance of `Support`.
+pub trait Sample<Support> {
+    /// Generate a random value of `Support`, using `rng` as the
+    /// source of randomness.
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> Support;
+}
+
+/// `Sample`s that do not require keeping track of state.
+///
+/// Since no state is recored, each sample is (statistically)
+/// independent of all others, assuming the `Rng` used has this
+/// property.
+// XXX maybe having this separate is overkill (the only reason is to
+// take &self rather than &mut self)? or maybe this should be the
+// trait called `Sample` and the other should be `DependentSample`.
+pub trait IndependentSample<Support>: Sample<Support> {
+    /// Generate a random value.
+    fn ind_sample<R: Rng>(&self, &mut R) -> Support;
+}
+
+/// A wrapper for generating types that implement `Rand` via the
+/// `Sample` & `IndependentSample` traits.
+pub struct RandSample<Sup>;
+
+impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
+}
+
+impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
+    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
+        rng.gen()
+    }
+}
+
+/// A value with a particular weight for use with `WeightedChoice`.
+pub struct Weighted<T> {
+    /// The numerical weight of this item
+    weight: uint,
+    /// The actual item which is being weighted
+    item: T,
+}
+
+/// A distribution that selects from a finite collection of weighted items.
+///
+/// Each item has an associated weight that influences how likely it
+/// is to be chosen: higher weight is more likely.
+///
+/// The `Clone` restriction is a limitation of the `Sample` and
+/// `IndepedentSample` traits. Note that `&T` is (cheaply) `Clone` for
+/// all `T`, as is `uint`, so one can store references or indices into
+/// another vector.
+///
+/// # Example
+///
+/// ```rust
+/// use std::rand;
+/// use std::rand::distributions::{Weighted, WeightedChoice, IndepedentSample};
+///
+/// fn main() {
+///     let wc = WeightedChoice::new(~[Weighted { weight: 2, item: 'a' },
+///                                    Weighted { weight: 4, item: 'b' },
+///                                    Weighted { weight: 1, item: 'c' }]);
+///     let rng = rand::task_rng();
+///     for _ in range(0, 16) {
+///          // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
+///          println!("{}", wc.ind_sample(rng));
+///     }
+/// }
+/// ```
+pub struct WeightedChoice<T> {
+    priv items: ~[Weighted<T>],
+    priv weight_range: Range<uint>
+}
+
+impl<T: Clone> WeightedChoice<T> {
+    /// Create a new `WeightedChoice`.
+    ///
+    /// Fails if:
+    /// - `v` is empty
+    /// - the total weight is 0
+    /// - the total weight is larger than a `uint` can contain.
+    pub fn new(mut items: ~[Weighted<T>]) -> WeightedChoice<T> {
+        // strictly speaking, this is subsumed by the total weight == 0 case
+        assert!(!items.is_empty(), "WeightedChoice::new called with no items");
+
+        let mut running_total = 0u;
+
+        // we convert the list from individual weights to cumulative
+        // weights so we can binary search. This *could* drop elements
+        // with weight == 0 as an optimisation.
+        for item in items.mut_iter() {
+            running_total = running_total.checked_add(&item.weight)
+                .expect("WeightedChoice::new called with a total weight larger \
+                        than a uint can contain");
+
+            item.weight = running_total;
+        }
+        assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0");
+
+        WeightedChoice {
+            items: items,
+            // we're likely to be generating numbers in this range
+            // relatively often, so might as well cache it
+            weight_range: Range::new(0, running_total)
+        }
+    }
+}
+
+impl<T: Clone> Sample<T> for WeightedChoice<T> {
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
+}
+
+impl<T: Clone> IndependentSample<T> for WeightedChoice<T> {
+    fn ind_sample<R: Rng>(&self, rng: &mut R) -> T {
+        // we want to find the first element that has cumulative
+        // weight > sample_weight, which we do by binary since the
+        // cumulative weights of self.items are sorted.
+
+        // choose a weight in [0, total_weight)
+        let sample_weight = self.weight_range.ind_sample(rng);
+
+        // short circuit when it's the first item
+        if sample_weight < self.items[0].weight {
+            return self.items[0].item.clone();
+        }
+
+        let mut idx = 0;
+        let mut modifier = self.items.len();
+
+        // now we know that every possibility has an element to the
+        // left, so we can just search for the last element that has
+        // cumulative weight <= sample_weight, then the next one will
+        // be "it". (Note that this greatest element will never be the
+        // last element of the vector, since sample_weight is chosen
+        // in [0, total_weight) and the cumulative weight of the last
+        // one is exactly the total weight.)
+        while modifier > 1 {
+            let i = idx + modifier / 2;
+            if self.items[i].weight <= sample_weight {
+                // we're small, so look to the right, but allow this
+                // exact element still.
+                idx = i;
+                // we need the `/ 2` to round up otherwise we'll drop
+                // the trailing elements when `modifier` is odd.
+                modifier += 1;
+            } else {
+                // otherwise we're too big, so go left. (i.e. do
+                // nothing)
+            }
+            modifier /= 2;
+        }
+        return self.items[idx + 1].item.clone();
+    }
+}
 
 mod ziggurat_tables;
 
-// inlining should mean there is no performance penalty for this
-#[inline]
+/// Sample a random number using the Ziggurat method (specifically the
+/// ZIGNOR variant from Doornik 2005). Most of the arguments are
+/// directly from the paper:
+///
+/// * `rng`: source of randomness
+/// * `symmetric`: whether this is a symmetric distribution, or one-sided with P(x < 0) = 0.
+/// * `X`: the $x_i$ abscissae.
+/// * `F`: precomputed values of the PDF at the $x_i$, (i.e. $f(x_i)$)
+/// * `F_DIFF`: precomputed values of $f(x_i) - f(x_{i+1})$
+/// * `pdf`: the probability density function
+/// * `zero_case`: manual sampling from the tail when we chose the
+///    bottom box (i.e. i == 0)
+
+// the perf improvement (25-50%) is definitely worth the extra code
+// size from force-inlining.
+#[inline(always)]
 fn ziggurat<R:Rng>(rng: &mut R,
-                   center_u: bool,
+                   symmetric: bool,
                    X: ziggurat_tables::ZigTable,
                    F: ziggurat_tables::ZigTable,
                    F_DIFF: ziggurat_tables::ZigTable,
-                   pdf: &'static fn(f64) -> f64, // probability density function
+                   pdf: &'static fn(f64) -> f64,
                    zero_case: &'static fn(&mut R, f64) -> f64) -> f64 {
+    static SCALE: f64 = (1u64 << 53) as f64;
     loop {
-        let u = if center_u {2.0 * rng.gen() - 1.0} else {rng.gen()};
-        let i: uint = rng.gen::<uint>() & 0xff;
+        // reimplement the f64 generation as an optimisation suggested
+        // by the Doornik paper: we have a lot of precision-space
+        // (i.e. there are 11 bits of the 64 of a u64 to use after
+        // creating a f64), so we might as well reuse some to save
+        // generating a whole extra random number. (Seems to be 15%
+        // faster.)
+        let bits: u64 = rng.gen();
+        let i = (bits & 0xff) as uint;
+        let f = (bits >> 11) as f64 / SCALE;
+
+        // u is either U(-1, 1) or U(0, 1) depending on if this is a
+        // symmetric distribution or not.
+        let u = if symmetric {2.0 * f - 1.0} else {f};
         let x = u * X[i];
 
-        let test_x = if center_u {num::abs(x)} else {x};
+        let test_x = if symmetric {num::abs(x)} else {x};
 
         // algebraically equivalent to |u| < X[i+1]/X[i] (or u < X[i+1]/X[i])
         if test_x < X[i + 1] {
@@ -49,30 +237,25 @@ fn ziggurat<R:Rng>(rng: &mut R,
             return zero_case(rng, u);
         }
         // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
-        if F[i+1] + F_DIFF[i+1] * rng.gen() < pdf(x) {
+        if F[i + 1] + F_DIFF[i + 1] * rng.gen() < pdf(x) {
             return x;
         }
     }
 }
 
-/// A wrapper around an `f64` to generate N(0, 1) random numbers (a.k.a.  a
-/// standard normal, or Gaussian). Multiplying the generated values by the
-/// desired standard deviation `sigma` then adding the desired mean `mu` will
-/// give N(mu, sigma^2) distributed random numbers.
+/// A wrapper around an `f64` to generate N(0, 1) random numbers
+/// (a.k.a.  a standard normal, or Gaussian).
 ///
-/// Note that this has to be unwrapped before use as an `f64` (using either
-/// `*` or `cast::transmute` is safe).
+/// See `Normal` for the general normal distribution. That this has to
+/// be unwrapped before use as an `f64` (using either `*` or
+/// `cast::transmute` is safe).
 ///
-/// # Example
+/// Implemented via the ZIGNOR variant[1] of the Ziggurat method.
 ///
-/// ```
-/// use std::rand::distributions::StandardNormal;
-///
-/// fn main() {
-///     let normal = 2.0 + (*rand::random::<StandardNormal>()) * 3.0;
-///     println!("{} is from a N(2, 9) distribution", normal)
-/// }
-/// ```
+/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
+/// Generate Normal Random
+/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
+/// College, Oxford
 pub struct StandardNormal(f64);
 
 impl Rand for StandardNormal {
@@ -110,23 +293,62 @@ impl Rand for StandardNormal {
     }
 }
 
-/// A wrapper around an `f64` to generate Exp(1) random numbers. Dividing by
-/// the desired rate `lambda` will give Exp(lambda) distributed random
-/// numbers.
+/// The normal distribution `N(mean, std_dev**2)`.
 ///
-/// Note that this has to be unwrapped before use as an `f64` (using either
-/// `*` or `cast::transmute` is safe).
+/// This uses the ZIGNOR variant of the Ziggurat method, see
+/// `StandardNormal` for more details.
 ///
 /// # Example
 ///
 /// ```
-/// use std::rand::distributions::Exp1;
+/// use std::rand;
+/// use std::rand::distributions::{Normal, IndependentSample};
 ///
 /// fn main() {
-///     let exp2 = (*rand::random::<Exp1>()) * 0.5;
-///     println!("{} is from a Exp(2) distribution", exp2);
+///     let normal = Normal::new(2.0, 3.0);
+///     let v = normal.ind_sample(rand::task_rng());
+///     println!("{} is from a N(2, 9) distribution", v)
 /// }
 /// ```
+pub struct Normal {
+    priv mean: f64,
+    priv std_dev: f64
+}
+
+impl Normal {
+    /// Construct a new `Normal` distribution with the given mean and
+    /// standard deviation. Fails if `std_dev < 0`.
+    pub fn new(mean: f64, std_dev: f64) -> Normal {
+        assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0");
+        Normal {
+            mean: mean,
+            std_dev: std_dev
+        }
+    }
+}
+impl Sample<f64> for Normal {
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+}
+impl IndependentSample<f64> for Normal {
+    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
+        self.mean + self.std_dev * (*rng.gen::<StandardNormal>())
+    }
+}
+
+/// A wrapper around an `f64` to generate Exp(1) random numbers.
+///
+/// See `Exp` for the general exponential distribution.Note that this
+ // has to be unwrapped before use as an `f64` (using either
+/// `*` or `cast::transmute` is safe).
+///
+/// Implemented via the ZIGNOR variant[1] of the Ziggurat method. The
+/// exact description in the paper was adjusted to use tables for the
+/// exponential distribution rather than normal.
+///
+/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
+/// Generate Normal Random
+/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
+/// College, Oxford
 pub struct Exp1(f64);
 
 // This could be done via `-rng.gen::<f64>().ln()` but that is slower.
@@ -148,3 +370,221 @@ impl Rand for Exp1 {
                       pdf, zero_case))
     }
 }
+
+/// The exponential distribution `Exp(lambda)`.
+///
+/// This distribution has density function: `f(x) = lambda *
+/// exp(-lambda * x)` for `x > 0`.
+///
+/// # Example
+///
+/// ```
+/// use std::rand;
+/// use std::rand::distributions::{Exp, IndependentSample};
+///
+/// fn main() {
+///     let exp = Exp::new(2.0);
+///     let v = exp.ind_sample(rand::task_rng());
+///     println!("{} is from a Exp(2) distribution", v);
+/// }
+/// ```
+pub struct Exp {
+    /// `lambda` stored as `1/lambda`, since this is what we scale by.
+    priv lambda_inverse: f64
+}
+
+impl Exp {
+    /// Construct a new `Exp` with the given shape parameter
+    /// `lambda`. Fails if `lambda <= 0`.
+    pub fn new(lambda: f64) -> Exp {
+        assert!(lambda > 0.0, "Exp::new called with `lambda` <= 0");
+        Exp { lambda_inverse: 1.0 / lambda }
+    }
+}
+
+impl Sample<f64> for Exp {
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+}
+impl IndependentSample<f64> for Exp {
+    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
+        (*rng.gen::<Exp1>()) * self.lambda_inverse
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use rand::*;
+    use super::*;
+    use iter::range;
+    use option::{Some, None};
+
+    struct ConstRand(uint);
+    impl Rand for ConstRand {
+        fn rand<R: Rng>(_: &mut R) -> ConstRand {
+            ConstRand(0)
+        }
+    }
+
+    // 0, 1, 2, 3, ...
+    struct CountingRng { i: u32 }
+    impl Rng for CountingRng {
+        fn next_u32(&mut self) -> u32 {
+            self.i += 1;
+            self.i - 1
+        }
+        fn next_u64(&mut self) -> u64 {
+            self.next_u32() as u64
+        }
+    }
+
+    #[test]
+    fn test_rand_sample() {
+        let mut rand_sample = RandSample::<ConstRand>;
+
+        assert_eq!(*rand_sample.sample(task_rng()), 0);
+        assert_eq!(*rand_sample.ind_sample(task_rng()), 0);
+    }
+
+    #[test]
+    fn test_normal() {
+        let mut norm = Normal::new(10.0, 10.0);
+        let rng = task_rng();
+        for _ in range(0, 1000) {
+            norm.sample(rng);
+            norm.ind_sample(rng);
+        }
+    }
+    #[test]
+    #[should_fail]
+    fn test_normal_invalid_sd() {
+        Normal::new(10.0, -1.0);
+    }
+
+    #[test]
+    fn test_exp() {
+        let mut exp = Exp::new(10.0);
+        let rng = task_rng();
+        for _ in range(0, 1000) {
+            assert!(exp.sample(rng) >= 0.0);
+            assert!(exp.ind_sample(rng) >= 0.0);
+        }
+    }
+    #[test]
+    #[should_fail]
+    fn test_exp_invalid_lambda_zero() {
+        Exp::new(0.0);
+    }
+    #[test]
+    #[should_fail]
+    fn test_exp_invalid_lambda_neg() {
+        Exp::new(-10.0);
+    }
+
+    #[test]
+    fn test_weighted_choice() {
+        // this makes assumptions about the internal implementation of
+        // WeightedChoice, specifically: it doesn't reorder the items,
+        // it doesn't do weird things to the RNG (so 0 maps to 0, 1 to
+        // 1, internally; modulo a modulo operation).
+
+        macro_rules! t (
+            ($items:expr, $expected:expr) => {{
+                let wc = WeightedChoice::new($items);
+                let expected = $expected;
+
+                let mut rng = CountingRng { i: 0 };
+
+                for &val in expected.iter() {
+                    assert_eq!(wc.ind_sample(&mut rng), val)
+                }
+            }}
+        );
+
+        t!(~[Weighted { weight: 1, item: 10}], ~[10]);
+
+        // skip some
+        t!(~[Weighted { weight: 0, item: 20},
+             Weighted { weight: 2, item: 21},
+             Weighted { weight: 0, item: 22},
+             Weighted { weight: 1, item: 23}],
+           ~[21,21, 23]);
+
+        // different weights
+        t!(~[Weighted { weight: 4, item: 30},
+             Weighted { weight: 3, item: 31}],
+           ~[30,30,30,30, 31,31,31]);
+
+        // check that we're binary searching
+        // correctly with some vectors of odd
+        // length.
+        t!(~[Weighted { weight: 1, item: 40},
+             Weighted { weight: 1, item: 41},
+             Weighted { weight: 1, item: 42},
+             Weighted { weight: 1, item: 43},
+             Weighted { weight: 1, item: 44}],
+           ~[40, 41, 42, 43, 44]);
+        t!(~[Weighted { weight: 1, item: 50},
+             Weighted { weight: 1, item: 51},
+             Weighted { weight: 1, item: 52},
+             Weighted { weight: 1, item: 53},
+             Weighted { weight: 1, item: 54},
+             Weighted { weight: 1, item: 55},
+             Weighted { weight: 1, item: 56}],
+           ~[50, 51, 52, 53, 54, 55, 56]);
+    }
+
+    #[test] #[should_fail]
+    fn test_weighted_choice_no_items() {
+        WeightedChoice::<int>::new(~[]);
+    }
+    #[test] #[should_fail]
+    fn test_weighted_choice_zero_weight() {
+        WeightedChoice::new(~[Weighted { weight: 0, item: 0},
+                              Weighted { weight: 0, item: 1}]);
+    }
+    #[test] #[should_fail]
+    fn test_weighted_choice_weight_overflows() {
+        let x = (-1) as uint / 2; // x + x + 2 is the overflow
+        WeightedChoice::new(~[Weighted { weight: x, item: 0 },
+                              Weighted { weight: 1, item: 1 },
+                              Weighted { weight: x, item: 2 },
+                              Weighted { weight: 1, item: 3 }]);
+    }
+}
+
+#[cfg(test)]
+mod bench {
+    use extra::test::BenchHarness;
+    use rand::*;
+    use super::*;
+    use iter::range;
+    use option::{Some, None};
+    use mem::size_of;
+
+    static N: u64 = 100;
+
+    #[bench]
+    fn rand_normal(bh: &mut BenchHarness) {
+        let mut rng = XorShiftRng::new();
+        let mut normal = Normal::new(-2.71828, 3.14159);
+
+        do bh.iter {
+            for _ in range(0, N) {
+                normal.sample(&mut rng);
+            }
+        }
+        bh.bytes = size_of::<f64>() as u64 * N;
+    }
+    #[bench]
+    fn rand_exp(bh: &mut BenchHarness) {
+        let mut rng = XorShiftRng::new();
+        let mut exp = Exp::new(2.71828 * 3.14159);
+
+        do bh.iter {
+            for _ in range(0, N) {
+                exp.sample(&mut rng);
+            }
+        }
+        bh.bytes = size_of::<f64>() as u64 * N;
+    }
+}
diff --git a/src/libstd/rand/isaac.rs b/src/libstd/rand/isaac.rs
index 0068b60cfa5..42254b211a1 100644
--- a/src/libstd/rand/isaac.rs
+++ b/src/libstd/rand/isaac.rs
@@ -10,18 +10,24 @@
 
 //! The ISAAC random number generator.
 
-use cast;
 use rand::{Rng, SeedableRng, OSRng};
 use iter::{Iterator, range, range_step, Repeat};
 use option::{None, Some};
+use vec::raw;
+use mem;
 
 static RAND_SIZE_LEN: u32 = 8;
 static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
 
-/// A random number generator that uses the [ISAAC
-/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
+/// A random number generator that uses the ISAAC algorithm[1].
 ///
-/// The ISAAC algorithm is suitable for cryptographic purposes.
+/// The ISAAC algorithm is generally accepted as suitable for
+/// cryptographic purposes, but this implementation has not be
+/// verified as such. Prefer a generator like `OSRng` that defers to
+/// the operating system for cases that need high security.
+///
+/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
+/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
 pub struct IsaacRng {
     priv cnt: u32,
     priv rsl: [u32, .. RAND_SIZE],
@@ -42,9 +48,12 @@ impl IsaacRng {
     pub fn new() -> IsaacRng {
         let mut rng = EMPTY;
 
-        {
-            let bytes = unsafe {cast::transmute::<&mut [u32], &mut [u8]>(rng.rsl)};
-            OSRng::new().fill_bytes(bytes);
+        unsafe {
+            let ptr = raw::to_mut_ptr(rng.rsl);
+
+            do raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl)) |slice| {
+                OSRng::new().fill_bytes(slice);
+            }
         }
 
         rng.init(true);
@@ -212,11 +221,16 @@ impl<'self> SeedableRng<&'self [u32]> for IsaacRng {
 static RAND_SIZE_64_LEN: uint = 8;
 static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
 
-/// A random number generator that uses the 64-bit variant of the
-/// [ISAAC
-/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
+/// A random number generator that uses ISAAC-64[1], the 64-bit
+/// variant of the ISAAC algorithm.
+///
+/// The ISAAC algorithm is generally accepted as suitable for
+/// cryptographic purposes, but this implementation has not be
+/// verified as such. Prefer a generator like `OSRng` that defers to
+/// the operating system for cases that need high security.
 ///
-/// The ISAAC algorithm is suitable for cryptographic purposes.
+/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
+/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
 pub struct Isaac64Rng {
     priv cnt: uint,
     priv rsl: [u64, .. RAND_SIZE_64],
@@ -238,10 +252,15 @@ impl Isaac64Rng {
     /// seed.
     pub fn new() -> Isaac64Rng {
         let mut rng = EMPTY_64;
-        {
-            let bytes = unsafe {cast::transmute::<&mut [u64], &mut [u8]>(rng.rsl)};
-            OSRng::new().fill_bytes(bytes);
+
+        unsafe {
+            let ptr = raw::to_mut_ptr(rng.rsl);
+
+            do raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl)) |slice| {
+                OSRng::new().fill_bytes(slice);
+            }
         }
+
         rng.init(true);
         rng
     }
@@ -434,14 +453,14 @@ mod test {
 
     #[test]
     fn test_rng_32_seeded() {
-        let seed = &[2, 32, 4, 32, 51];
+        let seed = &[1, 23, 456, 7890, 12345];
         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
         assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
     }
     #[test]
     fn test_rng_64_seeded() {
-        let seed = &[2, 32, 4, 32, 51];
+        let seed = &[1, 23, 456, 7890, 12345];
         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
         assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
@@ -472,46 +491,46 @@ mod test {
 
     #[test]
     fn test_rng_32_true_values() {
-        let seed = &[2, 32, 4, 32, 51];
+        let seed = &[1, 23, 456, 7890, 12345];
         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
         // Regression test that isaac is actually using the above vector
         let v = vec::from_fn(10, |_| ra.next_u32());
         assert_eq!(v,
-                   ~[447462228, 2081944040, 3163797308, 2379916134, 2377489184,
-                     1132373754, 536342443, 2995223415, 1265094839, 345325140]);
+                   ~[2558573138, 873787463, 263499565, 2103644246, 3595684709,
+                     4203127393, 264982119, 2765226902, 2737944514, 3900253796]);
 
-        let seed = &[500, -4000, 123456, 9876543, 1, 1, 1, 1, 1];
+        let seed = &[12345, 67890, 54321, 9876];
         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
         // skip forward to the 10000th number
         for _ in range(0, 10000) { rb.next_u32(); }
 
         let v = vec::from_fn(10, |_| rb.next_u32());
         assert_eq!(v,
-                   ~[612373032, 292987903, 1819311337, 3141271980, 422447569,
-                     310096395, 1083172510, 867909094, 2478664230, 2073577855]);
+                   ~[3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
+                     1576568959, 3507990155, 179069555, 141456972, 2478885421]);
     }
     #[test]
     fn test_rng_64_true_values() {
-        let seed = &[2, 32, 4, 32, 51];
+        let seed = &[1, 23, 456, 7890, 12345];
         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
         // Regression test that isaac is actually using the above vector
         let v = vec::from_fn(10, |_| ra.next_u64());
         assert_eq!(v,
-                   ~[15015576812873463115, 12461067598045625862, 14818626436142668771,
-                     5562406406765984441, 11813289907965514161, 13443797187798420053,
-                     6935026941854944442, 7750800609318664042, 14428747036317928637,
-                     14028894460301215947]);
+                   ~[547121783600835980, 14377643087320773276, 17351601304698403469,
+                     1238879483818134882, 11952566807690396487, 13970131091560099343,
+                     4469761996653280935, 15552757044682284409, 6860251611068737823,
+                     13722198873481261842]);
 
-        let seed = &[500, -4000, 123456, 9876543, 1, 1, 1, 1, 1];
+        let seed = &[12345, 67890, 54321, 9876];
         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
         // skip forward to the 10000th number
         for _ in range(0, 10000) { rb.next_u64(); }
 
         let v = vec::from_fn(10, |_| rb.next_u64());
         assert_eq!(v,
-                   ~[13557216323596688637, 17060829581390442094, 4927582063811333743,
-                     2699639759356482270, 4819341314392384881, 6047100822963614452,
-                     11086255989965979163, 11901890363215659856, 5370800226050011580,
-                     16496463556025356451]);
+                   ~[18143823860592706164, 8491801882678285927, 2699425367717515619,
+                     17196852593171130876, 2606123525235546165, 15790932315217671084,
+                     596345674630742204, 9947027391921273664, 11788097613744130851,
+                     10391409374914919106]);
     }
 }
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index f5c60417bac..a6efdfc66db 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -28,6 +28,23 @@ from an operating-system source of randomness, e.g. `/dev/urandom` on
 Unix systems, and will automatically reseed itself from this source
 after generating 32 KiB of random data.
 
+# Cryptographic security
+
+An application that requires random numbers for cryptographic purposes
+should prefer `OSRng`, which reads randomness from one of the source
+that the operating system provides (e.g. `/dev/urandom` on
+Unixes). The other random number generators provided by this module
+are either known to be insecure (`XorShiftRng`), or are not verified
+to be secure (`IsaacRng`, `Isaac64Rng` and `StdRng`).
+
+*Note*: on Linux, `/dev/random` is more secure than `/dev/urandom`,
+but it is a blocking RNG, and will wait until it has determined that
+it has collected enough entropy to fulfill a request for random
+data. It can be used with the `Rng` trait provided by this module by
+opening the file and passing it to `reader::ReaderRng`. Since it
+blocks, `/dev/random` should only be used to retrieve small amounts of
+randomness.
+
 # Examples
 
 ```rust
@@ -52,20 +69,21 @@ fn main () {
  ```
 */
 
-use mem::size_of;
-use unstable::raw::Slice;
 use cast;
+use cmp::Ord;
 use container::Container;
 use iter::{Iterator, range};
 use local_data;
 use prelude::*;
 use str;
-use u64;
 use vec;
 
 pub use self::isaac::{IsaacRng, Isaac64Rng};
 pub use self::os::OSRng;
 
+use self::distributions::{Range, IndependentSample};
+use self::distributions::range::SampleRange;
+
 pub mod distributions;
 pub mod isaac;
 pub mod os;
@@ -80,14 +98,6 @@ pub trait Rand {
     fn rand<R: Rng>(rng: &mut R) -> Self;
 }
 
-/// A value with a particular weight compared to other values
-pub struct Weighted<T> {
-    /// The numerical weight of this item
-    weight: uint,
-    /// The actual item which is being weighted
-    item: T,
-}
-
 /// A random number generator
 pub trait Rng {
     /// Return the next random u32. This rarely needs to be called
@@ -136,46 +146,26 @@ pub trait Rng {
     /// }
     /// ```
     fn fill_bytes(&mut self, dest: &mut [u8]) {
-        let mut slice: Slice<u64> = unsafe { cast::transmute_copy(&dest) };
-        slice.len /= size_of::<u64>();
-        let as_u64: &mut [u64] = unsafe { cast::transmute(slice) };
-        for dest in as_u64.mut_iter() {
-            *dest = self.next_u64();
-        }
-
-        // the above will have filled up the vector as much as
-        // possible in multiples of 8 bytes.
-        let mut remaining = dest.len() % 8;
-
-        // space for a u32
-        if remaining >= 4 {
-            let mut slice: Slice<u32> = unsafe { cast::transmute_copy(&dest) };
-            slice.len /= size_of::<u32>();
-            let as_u32: &mut [u32] = unsafe { cast::transmute(slice) };
-            as_u32[as_u32.len() - 1] = self.next_u32();
-            remaining -= 4;
-        }
-        // exactly filled
-        if remaining == 0 { return }
-
-        // now we know we've either got 1, 2 or 3 spots to go,
-        // i.e. exactly one u32 is enough.
-        let rand = self.next_u32();
-        let remaining_index = dest.len() - remaining;
-        match dest.mut_slice_from(remaining_index) {
-            [ref mut a] => {
-                *a = rand as u8;
-            }
-            [ref mut a, ref mut b] => {
-                *a = rand as u8;
-                *b = (rand >> 8) as u8;
-            }
-            [ref mut a, ref mut b, ref mut c] => {
-                *a = rand as u8;
-                *b = (rand >> 8) as u8;
-                *c = (rand >> 16) as u8;
+        // this could, in theory, be done by transmuting dest to a
+        // [u64], but this is (1) likely to be undefined behaviour for
+        // LLVM, (2) has to be very careful about alignment concerns,
+        // (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 num = 0;
+        for byte in dest.mut_iter() {
+            if count == 0 {
+                // we could micro-optimise here by generating a u32 if
+                // we only need a few more bytes to fill the vector
+                // (i.e. at most 4).
+                num = self.next_u64();
+                count = 8;
             }
-            _ => fail!("Rng.fill_bytes: the impossible occurred: remaining != 1, 2 or 3")
+
+            *byte = (num & 0xff) as u8;
+            num >>= 8;
+            count -= 1;
         }
     }
 
@@ -218,14 +208,14 @@ pub trait Rng {
         vec::from_fn(len, |_| self.gen())
     }
 
-    /// Generate a random primitive integer in the range [`low`,
-    /// `high`). Fails if `low >= high`.
+    /// Generate a random value in the range [`low`, `high`). Fails if
+    /// `low >= high`.
     ///
-    /// This gives a uniform distribution (assuming this RNG is itself
-    /// uniform), even for edge cases like `gen_integer_range(0u8,
-    /// 170)`, which a naive modulo operation would return numbers
-    /// less than 85 with double the probability to those greater than
-    /// 85.
+    /// This is a convenience wrapper around
+    /// `distributions::Range`. If this function will be called
+    /// repeatedly with the same arguments, one should use `Range`, as
+    /// that will amortize the computations that allow for perfect
+    /// uniformity, as they only happen on initialization.
     ///
     /// # Example
     ///
@@ -235,22 +225,15 @@ pub trait Rng {
     ///
     /// fn main() {
     ///    let mut rng = rand::task_rng();
-    ///    let n: uint = rng.gen_integer_range(0u, 10);
+    ///    let n: uint = rng.gen_range(0u, 10);
     ///    println!("{}", n);
-    ///    let m: int = rng.gen_integer_range(-40, 400);
+    ///    let m: float = rng.gen_range(-40.0, 1.3e5);
     ///    println!("{}", m);
     /// }
     /// ```
-    fn gen_integer_range<T: Rand + Int>(&mut self, low: T, high: T) -> T {
-        assert!(low < high, "RNG.gen_integer_range called with low >= high");
-        let range = (high - low).to_u64().unwrap();
-        let accept_zone = u64::max_value - u64::max_value % range;
-        loop {
-            let rand = self.gen::<u64>();
-            if rand < accept_zone {
-                return low + NumCast::from(rand % range).unwrap();
-            }
-        }
+    fn gen_range<T: Ord + SampleRange>(&mut self, low: T, high: T) -> T {
+        assert!(low < high, "Rng.gen_range called with low >= high");
+        Range::new(low, high).ind_sample(self)
     }
 
     /// Return a bool with a 1 in n chance of true
@@ -267,7 +250,7 @@ pub trait Rng {
     /// }
     /// ```
     fn gen_weighted_bool(&mut self, n: uint) -> bool {
-        n == 0 || self.gen_integer_range(0, n) == 0
+        n == 0 || self.gen_range(0, n) == 0
     }
 
     /// Return a random string of the specified length composed of
@@ -317,93 +300,8 @@ pub trait Rng {
         if values.is_empty() {
             None
         } else {
-            Some(&values[self.gen_integer_range(0u, values.len())])
-        }
-    }
-
-    /// Choose an item respecting the relative weights, failing if the sum of
-    /// the weights is 0
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// use std::rand;
-    /// use std::rand::Rng;
-    ///
-    /// fn main() {
-    ///     let mut rng = rand::rng();
-    ///     let x = [rand::Weighted {weight: 4, item: 'a'},
-    ///              rand::Weighted {weight: 2, item: 'b'},
-    ///              rand::Weighted {weight: 2, item: 'c'}];
-    ///     println!("{}", rng.choose_weighted(x));
-    /// }
-    /// ```
-    fn choose_weighted<T:Clone>(&mut self, v: &[Weighted<T>]) -> T {
-        self.choose_weighted_option(v).expect("Rng.choose_weighted: total weight is 0")
-    }
-
-    /// Choose Some(item) respecting the relative weights, returning none if
-    /// the sum of the weights is 0
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// use std::rand;
-    /// use std::rand::Rng;
-    ///
-    /// fn main() {
-    ///     let mut rng = rand::rng();
-    ///     let x = [rand::Weighted {weight: 4, item: 'a'},
-    ///              rand::Weighted {weight: 2, item: 'b'},
-    ///              rand::Weighted {weight: 2, item: 'c'}];
-    ///     println!("{:?}", rng.choose_weighted_option(x));
-    /// }
-    /// ```
-    fn choose_weighted_option<T:Clone>(&mut self, v: &[Weighted<T>])
-                                       -> Option<T> {
-        let mut total = 0u;
-        for item in v.iter() {
-            total += item.weight;
-        }
-        if total == 0u {
-            return None;
-        }
-        let chosen = self.gen_integer_range(0u, total);
-        let mut so_far = 0u;
-        for item in v.iter() {
-            so_far += item.weight;
-            if so_far > chosen {
-                return Some(item.item.clone());
-            }
+            Some(&values[self.gen_range(0u, values.len())])
         }
-        unreachable!();
-    }
-
-    /// Return a vec containing copies of the items, in order, where
-    /// the weight of the item determines how many copies there are
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// use std::rand;
-    /// use std::rand::Rng;
-    ///
-    /// fn main() {
-    ///     let mut rng = rand::rng();
-    ///     let x = [rand::Weighted {weight: 4, item: 'a'},
-    ///              rand::Weighted {weight: 2, item: 'b'},
-    ///              rand::Weighted {weight: 2, item: 'c'}];
-    ///     println!("{}", rng.weighted_vec(x));
-    /// }
-    /// ```
-    fn weighted_vec<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T] {
-        let mut r = ~[];
-        for item in v.iter() {
-            for _ in range(0u, item.weight) {
-                r.push(item.item.clone());
-            }
-        }
-        r
     }
 
     /// Shuffle a vec
@@ -447,7 +345,7 @@ pub trait Rng {
             // invariant: elements with index >= i have been locked in place.
             i -= 1u;
             // lock element i in place.
-            values.swap(i, self.gen_integer_range(0u, i + 1u));
+            values.swap(i, self.gen_range(0u, i + 1u));
         }
     }
 
@@ -473,7 +371,7 @@ pub trait Rng {
                 continue
             }
 
-            let k = self.gen_integer_range(0, i + 1);
+            let k = self.gen_range(0, i + 1);
             if k < reservoir.len() {
                 reservoir[k] = elem
             }
@@ -520,8 +418,8 @@ pub trait SeedableRng<Seed>: Rng {
 
 /// Create a random number generator with a default algorithm and seed.
 ///
-/// It returns the cryptographically-safest `Rng` algorithm currently
-/// available in Rust. If you require a specifically seeded `Rng` for
+/// It returns the strongest `Rng` algorithm currently implemented in
+/// pure Rust. If you require a specifically seeded `Rng` for
 /// consistency over time you should pick one algorithm and create the
 /// `Rng` yourself.
 ///
@@ -596,12 +494,16 @@ pub fn weak_rng() -> XorShiftRng {
     XorShiftRng::new()
 }
 
-/// An [Xorshift random number
-/// generator](http://en.wikipedia.org/wiki/Xorshift).
+/// An Xorshift[1] random number
+/// generator.
 ///
 /// The Xorshift algorithm is not suitable for cryptographic purposes
 /// but is very fast. If you do not know for sure that it fits your
-/// requirements, use a more secure one such as `IsaacRng`.
+/// requirements, use a more secure one such as `IsaacRng` or `OSRng`.
+///
+/// [1]: Marsaglia, George (July 2003). ["Xorshift
+/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
+/// Statistical Software*. Vol. 8 (Issue 14).
 pub struct XorShiftRng {
     priv x: u32,
     priv y: u32,
@@ -749,47 +651,68 @@ pub fn random<T: Rand>() -> T {
 mod test {
     use iter::{Iterator, range};
     use option::{Option, Some};
+    use vec;
     use super::*;
 
+    struct ConstRng { i: u64 }
+    impl Rng for ConstRng {
+        fn next_u32(&mut self) -> u32 { self.i as u32 }
+        fn next_u64(&mut self) -> u64 { self.i }
+
+        // no fill_bytes on purpose
+    }
+
     #[test]
     fn test_fill_bytes_default() {
-        let mut r = weak_rng();
-
-        let mut v = [0u8, .. 100];
-        r.fill_bytes(v);
+        let mut r = ConstRng { i: 0x11_22_33_44_55_66_77_88 };
+
+        // check every remainder mod 8, both in small and big vectors.
+        let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
+                       80, 81, 82, 83, 84, 85, 86, 87];
+        for &n in lengths.iter() {
+            let mut v = vec::from_elem(n, 0u8);
+            r.fill_bytes(v);
+
+            // use this to get nicer error messages.
+            for (i, &byte) in v.iter().enumerate() {
+                if byte == 0 {
+                    fail!("byte {} of {} is zero", i, n)
+                }
+            }
+        }
     }
 
     #[test]
-    fn test_gen_integer_range() {
+    fn test_gen_range() {
         let mut r = rng();
         for _ in range(0, 1000) {
-            let a = r.gen_integer_range(-3i, 42);
+            let a = r.gen_range(-3i, 42);
             assert!(a >= -3 && a < 42);
-            assert_eq!(r.gen_integer_range(0, 1), 0);
-            assert_eq!(r.gen_integer_range(-12, -11), -12);
+            assert_eq!(r.gen_range(0, 1), 0);
+            assert_eq!(r.gen_range(-12, -11), -12);
         }
 
         for _ in range(0, 1000) {
-            let a = r.gen_integer_range(10, 42);
+            let a = r.gen_range(10, 42);
             assert!(a >= 10 && a < 42);
-            assert_eq!(r.gen_integer_range(0, 1), 0);
-            assert_eq!(r.gen_integer_range(3_000_000u, 3_000_001), 3_000_000);
+            assert_eq!(r.gen_range(0, 1), 0);
+            assert_eq!(r.gen_range(3_000_000u, 3_000_001), 3_000_000);
         }
 
     }
 
     #[test]
     #[should_fail]
-    fn test_gen_integer_range_fail_int() {
+    fn test_gen_range_fail_int() {
         let mut r = rng();
-        r.gen_integer_range(5i, -2);
+        r.gen_range(5i, -2);
     }
 
     #[test]
     #[should_fail]
-    fn test_gen_integer_range_fail_uint() {
+    fn test_gen_range_fail_uint() {
         let mut r = rng();
-        r.gen_integer_range(5u, 2u);
+        r.gen_range(5u, 2u);
     }
 
     #[test]
@@ -844,44 +767,6 @@ mod test {
     }
 
     #[test]
-    fn test_choose_weighted() {
-        let mut r = rng();
-        assert!(r.choose_weighted([
-            Weighted { weight: 1u, item: 42 },
-        ]) == 42);
-        assert!(r.choose_weighted([
-            Weighted { weight: 0u, item: 42 },
-            Weighted { weight: 1u, item: 43 },
-        ]) == 43);
-    }
-
-    #[test]
-    fn test_choose_weighted_option() {
-        let mut r = rng();
-        assert!(r.choose_weighted_option([
-            Weighted { weight: 1u, item: 42 },
-        ]) == Some(42));
-        assert!(r.choose_weighted_option([
-            Weighted { weight: 0u, item: 42 },
-            Weighted { weight: 1u, item: 43 },
-        ]) == Some(43));
-        let v: Option<int> = r.choose_weighted_option([]);
-        assert!(v.is_none());
-    }
-
-    #[test]
-    fn test_weighted_vec() {
-        let mut r = rng();
-        let empty: ~[int] = ~[];
-        assert_eq!(r.weighted_vec([]), empty);
-        assert!(r.weighted_vec([
-            Weighted { weight: 0u, item: 3u },
-            Weighted { weight: 1u, item: 2u },
-            Weighted { weight: 2u, item: 1u },
-        ]) == ~[2u, 1u, 1u]);
-    }
-
-    #[test]
     fn test_shuffle() {
         let mut r = rng();
         let empty: ~[int] = ~[];
@@ -894,7 +779,7 @@ mod test {
         let mut r = task_rng();
         r.gen::<int>();
         assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]);
-        assert_eq!(r.gen_integer_range(0u, 1u), 0u);
+        assert_eq!(r.gen_range(0u, 1u), 0u);
     }
 
     #[test]
@@ -953,41 +838,53 @@ mod bench {
     use extra::test::BenchHarness;
     use rand::*;
     use mem::size_of;
+    use iter::range;
+    use option::{Some, None};
+
+    static N: u64 = 100;
 
     #[bench]
     fn rand_xorshift(bh: &mut BenchHarness) {
         let mut rng = XorShiftRng::new();
         do bh.iter {
-            rng.gen::<uint>();
+            for _ in range(0, N) {
+                rng.gen::<uint>();
+            }
         }
-        bh.bytes = size_of::<uint>() as u64;
+        bh.bytes = size_of::<uint>() as u64 * N;
     }
 
     #[bench]
     fn rand_isaac(bh: &mut BenchHarness) {
         let mut rng = IsaacRng::new();
         do bh.iter {
-            rng.gen::<uint>();
+            for _ in range(0, N) {
+                rng.gen::<uint>();
+            }
         }
-        bh.bytes = size_of::<uint>() as u64;
+        bh.bytes = size_of::<uint>() as u64 * N;
     }
 
     #[bench]
     fn rand_isaac64(bh: &mut BenchHarness) {
         let mut rng = Isaac64Rng::new();
         do bh.iter {
-            rng.gen::<uint>();
+            for _ in range(0, N) {
+                rng.gen::<uint>();
+            }
         }
-        bh.bytes = size_of::<uint>() as u64;
+        bh.bytes = size_of::<uint>() as u64 * N;
     }
 
     #[bench]
     fn rand_std(bh: &mut BenchHarness) {
         let mut rng = StdRng::new();
         do bh.iter {
-            rng.gen::<uint>();
+            for _ in range(0, N) {
+                rng.gen::<uint>();
+            }
         }
-        bh.bytes = size_of::<uint>() as u64;
+        bh.bytes = size_of::<uint>() as u64 * N;
     }
 
     #[bench]
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 4c8cf06c55e..5ed8d6b10d1 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -30,8 +30,12 @@ type HCRYPTPROV = c_long;
 // assume they work when we call them.
 
 /// A random number generator that retrieves randomness straight from
-/// the operating system. On Unix-like systems this reads from
-/// `/dev/urandom`, on Windows this uses `CryptGenRandom`.
+/// the operating system. Platform sources:
+///
+/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+///   `/dev/urandom`.
+/// - Windows: calls `CryptGenRandom`, using the default cryptographic
+///   service provider with the `PROV_RSA_FULL` type.
 ///
 /// This does not block.
 #[cfg(unix)]
@@ -39,8 +43,12 @@ pub struct OSRng {
     priv inner: ReaderRng<file::FileStream>
 }
 /// A random number generator that retrieves randomness straight from
-/// the operating system. On Unix-like systems this reads from
-/// `/dev/urandom`, on Windows this uses `CryptGenRandom`.
+/// the operating system. Platform sources:
+///
+/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+///   `/dev/urandom`.
+/// - Windows: calls `CryptGenRandom`, using the default cryptographic
+///   service provider with the `PROV_RSA_FULL` type.
 ///
 /// This does not block.
 #[cfg(windows)]
diff --git a/src/libstd/rand/range.rs b/src/libstd/rand/range.rs
new file mode 100644
index 00000000000..1b805a0b8f7
--- /dev/null
+++ b/src/libstd/rand/range.rs
@@ -0,0 +1,235 @@
+// Copyright 2013 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.
+
+//! Generating numbers between two others.
+
+// this is surprisingly complicated to be both generic & correct
+
+use cmp::Ord;
+use num::Bounded;
+use rand::Rng;
+use rand::distributions::{Sample, IndependentSample};
+
+/// Sample values uniformly between two bounds.
+///
+/// This gives a uniform distribution (assuming the RNG used to sample
+/// it is itself uniform & the `SampleRange` implementation for the
+/// given type is correct), even for edge cases like `low = 0u8`,
+/// `high = 170u8`, for which a naive modulo operation would return
+/// numbers less than 85 with double the probability to those greater
+/// than 85.
+///
+/// Types should attempt to sample in `[low, high)`, i.e., not
+/// including `high`, but this may be very difficult. All the
+/// primitive integer types satisfy this property, and the float types
+/// normally satisfy it, but rounding may mean `high` can occur.
+///
+/// # Example
+///
+/// ```rust
+/// use std::rand;
+/// use std::rand::distributions::{IndependentSample, Range};
+///
+/// fn main() {
+///     let between = Range::new(10u, 10000u);
+///     let rng = rand::task_rng();
+///     let mut sum = 0;
+///     for _ in range(0, 1000) {
+///         sum += between.ind_sample(rng);
+///     }
+///     println!("{}", sum);
+/// }
+/// ```
+pub struct Range<X> {
+    priv low: X,
+    priv range: X,
+    priv accept_zone: X
+}
+
+impl<X: SampleRange + Ord> Range<X> {
+    /// Create a new `Range` instance that samples uniformly from
+    /// `[low, high)`. Fails if `low >= high`.
+    pub fn new(low: X, high: X) -> Range<X> {
+        assert!(low < high, "Range::new called with `low >= high`");
+        SampleRange::construct_range(low, high)
+    }
+}
+
+impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
+    #[inline]
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
+}
+impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
+    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
+        SampleRange::sample_range(self, rng)
+    }
+}
+
+/// The helper trait for types that have a sensible way to sample
+/// uniformly between two values. This should not be used directly,
+/// and is only to facilitate `Range`.
+pub trait SampleRange {
+    /// Construct the `Range` object that `sample_range`
+    /// requires. This should not ever be called directly, only via
+    /// `Range::new`, which will check that `low < high`, so this
+    /// function doesn't have to repeat the check.
+    fn construct_range(low: Self, high: Self) -> Range<Self>;
+
+    /// Sample a value from the given `Range` with the given `Rng` as
+    /// a source of randomness.
+    fn sample_range<R: Rng>(r: &Range<Self>, rng: &mut R) -> Self;
+}
+
+macro_rules! integer_impl {
+    ($ty:ty, $unsigned:ty) => {
+        impl SampleRange for $ty {
+            // we play free and fast with unsigned vs signed here
+            // (when $ty is signed), but that's fine, since the
+            // contract of this macro is for $ty and $unsigned to be
+            // "bit-equal", so casting between them is a no-op & a
+            // bijection.
+
+            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
+                let range = high as $unsigned - low as $unsigned;
+                let unsigned_max: $unsigned = Bounded::max_value();
+
+                // this is the largest number that fits into $unsigned
+                // that `range` divides evenly, so, if we've sampled
+                // `n` uniformly from this region, then `n % range` is
+                // uniform in [0, range)
+                let zone = unsigned_max - unsigned_max % range;
+
+                Range {
+                    low: low,
+                    range: range as $ty,
+                    accept_zone: zone as $ty
+                }
+            }
+            #[inline]
+            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
+                loop {
+                    // rejection sample
+                    let v = rng.gen::<$unsigned>();
+                    // until we find something that fits into the
+                    // region which r.range evenly divides (this will
+                    // be uniformly distributed)
+                    if v < r.accept_zone as $unsigned {
+                        // and return it, with some adjustments
+                        return r.low + (v % r.range as $unsigned) as $ty;
+                    }
+                }
+            }
+        }
+    }
+}
+
+integer_impl! { i8, u8 }
+integer_impl! { i16, u16 }
+integer_impl! { i32, u32 }
+integer_impl! { i64, u64 }
+integer_impl! { int, uint }
+integer_impl! { u8, u8 }
+integer_impl! { u16, u16 }
+integer_impl! { u32, u32 }
+integer_impl! { u64, u64 }
+integer_impl! { uint, uint }
+
+macro_rules! float_impl {
+    ($ty:ty) => {
+        impl SampleRange for $ty {
+            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
+                Range {
+                    low: low,
+                    range: high - low,
+                    accept_zone: 0.0 // unused
+                }
+            }
+            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
+                r.low + r.range * rng.gen()
+            }
+        }
+    }
+}
+
+float_impl! { f32 }
+float_impl! { f64 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use rand::*;
+    use num::Bounded;
+    use iter::range;
+    use option::{Some, None};
+    use vec::ImmutableVector;
+
+    #[should_fail]
+    #[test]
+    fn test_range_bad_limits_equal() {
+        Range::new(10, 10);
+    }
+    #[should_fail]
+    #[test]
+    fn test_range_bad_limits_flipped() {
+        Range::new(10, 5);
+    }
+
+    #[test]
+    fn test_integers() {
+        let rng = task_rng();
+        macro_rules! t (
+            ($($ty:ty),*) => {{
+                $(
+                   let v: &[($ty, $ty)] = [(0, 10),
+                                           (10, 127),
+                                           (Bounded::min_value(), Bounded::max_value())];
+                   for &(low, high) in v.iter() {
+                        let mut sampler: Range<$ty> = Range::new(low, high);
+                        for _ in range(0, 1000) {
+                            let v = sampler.sample(rng);
+                            assert!(low <= v && v < high);
+                            let v = sampler.ind_sample(rng);
+                            assert!(low <= v && v < high);
+                        }
+                    }
+                 )*
+            }}
+        );
+        t!(i8, i16, i32, i64, int,
+           u8, u16, u32, u64, uint)
+    }
+
+    #[test]
+    fn test_floats() {
+        let rng = task_rng();
+        macro_rules! t (
+            ($($ty:ty),*) => {{
+                $(
+                   let v: &[($ty, $ty)] = [(0.0, 100.0),
+                                           (-1e35, -1e25),
+                                           (1e-35, 1e-25),
+                                           (-1e35, 1e35)];
+                   for &(low, high) in v.iter() {
+                        let mut sampler: Range<$ty> = Range::new(low, high);
+                        for _ in range(0, 1000) {
+                            let v = sampler.sample(rng);
+                            assert!(low <= v && v < high);
+                            let v = sampler.ind_sample(rng);
+                            assert!(low <= v && v < high);
+                        }
+                    }
+                 )*
+            }}
+        );
+
+        t!(f32, f64)
+    }
+
+}
diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs
index 1cd76727716..d63b14f982d 100644
--- a/src/libstd/reflect.rs
+++ b/src/libstd/reflect.rs
@@ -41,7 +41,7 @@ pub fn align(size: uint, align: uint) -> uint {
 
 /// Adaptor to wrap around visitors implementing MovePtr.
 pub struct MovePtrAdaptor<V> {
-    inner: V
+    priv inner: V
 }
 pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> {
     MovePtrAdaptor { inner: v }
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
index 4feb1ca1910..d03621eb60d 100644
--- a/src/libstd/repr.rs
+++ b/src/libstd/repr.rs
@@ -98,10 +98,10 @@ enum VariantState {
 }
 
 pub struct ReprVisitor<'self> {
-    ptr: *c_void,
-    ptr_stk: ~[*c_void],
-    var_stk: ~[VariantState],
-    writer: &'self mut io::Writer
+    priv ptr: *c_void,
+    priv ptr_stk: ~[*c_void],
+    priv var_stk: ~[VariantState],
+    priv writer: &'self mut io::Writer
 }
 
 pub fn ReprVisitor<'a>(ptr: *c_void,
diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs
index 3c2000c522c..4426a3eafe1 100644
--- a/src/libstd/rt/borrowck.rs
+++ b/src/libstd/rt/borrowck.rs
@@ -29,9 +29,9 @@ static ALL_BITS: uint = FROZEN_BIT | MUT_BIT;
 
 #[deriving(Eq)]
 pub struct BorrowRecord {
-    box: *mut raw::Box<()>,
+    priv box: *mut raw::Box<()>,
     file: *c_char,
-    line: size_t
+    priv line: size_t
 }
 
 fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> {
diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs
index 4eae8bdc9a8..6319fdead17 100644
--- a/src/libstd/rt/comm.rs
+++ b/src/libstd/rt/comm.rs
@@ -48,14 +48,14 @@ struct Packet<T> {
 
 // A one-shot channel.
 pub struct ChanOne<T> {
-    void_packet: *mut Void,
-    suppress_finalize: bool
+    priv void_packet: *mut Void,
+    priv suppress_finalize: bool
 }
 
 /// A one-shot port.
 pub struct PortOne<T> {
-    void_packet: *mut Void,
-    suppress_finalize: bool
+    priv void_packet: *mut Void,
+    priv suppress_finalize: bool
 }
 
 pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
@@ -1117,7 +1117,7 @@ mod test {
             let total = stress_factor() + 10;
             let mut rng = rand::rng();
             do total.times {
-                let msgs = rng.gen_integer_range(0u, 10);
+                let msgs = rng.gen_range(0u, 10);
                 let pipe_clone = pipe.clone();
                 let end_chan_clone = end_chan.clone();
                 do spawntask_random {
diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs
index 7f7545ca230..b86dbfd6fb0 100644
--- a/src/libstd/rt/context.rs
+++ b/src/libstd/rt/context.rs
@@ -25,11 +25,11 @@ pub static RED_ZONE: uint = 20 * 1024;
 // then misalign the regs again.
 pub struct Context {
     /// The context entry point, saved here for later destruction
-    start: Option<~~fn()>,
+    priv start: Option<~~fn()>,
     /// Hold the registers while the task or scheduler is suspended
-    regs: ~Registers,
+    priv regs: ~Registers,
     /// Lower bound and upper bound for the stack
-    stack_bounds: Option<(uint, uint)>,
+    priv stack_bounds: Option<(uint, uint)>,
 }
 
 impl Context {
@@ -391,36 +391,32 @@ pub unsafe fn record_sp_limit(limit: uint) {
 /// As with the setter, this function does not have a __morestack header and can
 /// therefore be called in a "we're out of stack" situation.
 #[inline(always)]
-// NOTE: after the next snapshot, can remove the initialization before inline
-//       assembly due to an improvement in how it's handled, then this specific
-//       allow directive should get removed.
-#[allow(dead_assignment)]
 pub unsafe fn get_sp_limit() -> uint {
     return target_get_sp_limit();
 
     // x86-64
     #[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movq $$0x60+90*8, %rsi
               movq %gs:(%rsi), $0" : "=r"(limit) :: "rsi" : "volatile");
         return limit;
     }
     #[cfg(target_arch = "x86_64", target_os = "linux")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
     #[cfg(target_arch = "x86_64", target_os = "win32")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movq %gs:0x28, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
     #[cfg(target_arch = "x86_64", target_os = "freebsd")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
@@ -428,7 +424,7 @@ pub unsafe fn get_sp_limit() -> uint {
     // x86
     #[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movl $$0x48+90*4, %eax
               movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile");
         return limit;
@@ -436,13 +432,13 @@ pub unsafe fn get_sp_limit() -> uint {
     #[cfg(target_arch = "x86", target_os = "linux")]
     #[cfg(target_arch = "x86", target_os = "freebsd")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
     #[cfg(target_arch = "x86", target_os = "win32")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
-        let mut limit: uint = 0;
+        let limit;
         asm!("movl %fs:0x14, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs
index d33e1af90f8..dd71426938d 100644
--- a/src/libstd/rt/crate_map.rs
+++ b/src/libstd/rt/crate_map.rs
@@ -26,9 +26,9 @@ pub struct ModEntry<'self> {
 }
 
 pub struct CrateMap<'self> {
-    version: i32,
-    entries: &'self [ModEntry<'self>],
-    children: &'self [&'self CrateMap<'self>]
+     priv version: i32,
+     priv entries: &'self [ModEntry<'self>],
+     priv children: &'self [&'self CrateMap<'self>]
 }
 
 #[cfg(not(windows))]
diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs
index e25b03be361..a43bcd8142e 100644
--- a/src/libstd/rt/io/file.rs
+++ b/src/libstd/rt/io/file.rs
@@ -362,8 +362,8 @@ impl Seek for FileWriter {
 /// For this reason, it is best to use the access-constrained wrappers that are
 /// exposed via `FileInfo.open_reader()` and `FileInfo.open_writer()`.
 pub struct FileStream {
-    fd: ~RtioFileStream,
-    last_nread: int,
+    priv fd: ~RtioFileStream,
+    priv last_nread: int,
 }
 
 /// a `std::rt::io::Reader` trait impl for file I/O.
diff --git a/src/libstd/rt/io/flate.rs b/src/libstd/rt/io/flate.rs
index 7c72ce6ba89..8a5aa171eb8 100644
--- a/src/libstd/rt/io/flate.rs
+++ b/src/libstd/rt/io/flate.rs
@@ -17,7 +17,7 @@ use super::*;
 
 /// A Writer decorator that compresses using the 'deflate' scheme
 pub struct DeflateWriter<W> {
-    inner_writer: W
+    priv inner_writer: W
 }
 
 impl<W: Writer> DeflateWriter<W> {
@@ -56,7 +56,7 @@ impl<W: Writer> Decorator<W> for DeflateWriter<W> {
 
 /// A Reader decorator that decompresses using the 'deflate' scheme
 pub struct InflateReader<R> {
-    inner_reader: R
+    priv inner_reader: R
 }
 
 impl<R: Reader> InflateReader<R> {
diff --git a/src/libstd/rt/io/mock.rs b/src/libstd/rt/io/mock.rs
index c46e1372c64..44709c7b7b6 100644
--- a/src/libstd/rt/io/mock.rs
+++ b/src/libstd/rt/io/mock.rs
@@ -13,7 +13,7 @@ use rt::io::{Reader, Writer};
 
 pub struct MockReader {
     read: ~fn(buf: &mut [u8]) -> Option<uint>,
-    eof: ~fn() -> bool
+    priv eof: ~fn() -> bool
 }
 
 impl MockReader {
@@ -31,8 +31,8 @@ impl Reader for MockReader {
 }
 
 pub struct MockWriter {
-    write: ~fn(buf: &[u8]),
-    flush: ~fn()
+    priv write: ~fn(buf: &[u8]),
+    priv flush: ~fn()
 }
 
 impl MockWriter {
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
index 97d44da765a..a80c1aab398 100644
--- a/src/libstd/rt/io/mod.rs
+++ b/src/libstd/rt/io/mod.rs
@@ -12,8 +12,8 @@
 
 This module defines the Rust interface for synchronous I/O.
 It models byte-oriented input and output with the Reader and Writer traits.
-Types that implement both `Reader` and `Writer` and called 'streams',
-and automatically implement trait `Stream`.
+Types that implement both `Reader` and `Writer` are called 'streams',
+and automatically implement the `Stream` trait.
 Implementations are provided for common I/O streams like
 file, TCP, UDP, Unix domain sockets.
 Readers and Writers may be composed to add capabilities like string
diff --git a/src/libstd/rt/kill.rs b/src/libstd/rt/kill.rs
index 8029e3f6431..19f17ca966d 100644
--- a/src/libstd/rt/kill.rs
+++ b/src/libstd/rt/kill.rs
@@ -219,17 +219,17 @@ pub struct Death {
     // might kill it. This is optional so we can take it by-value at exit time.
     kill_handle:     Option<KillHandle>,
     // Handle to a watching parent, if we have one, for exit code propagation.
-    watching_parent: Option<KillHandle>,
+    priv watching_parent: Option<KillHandle>,
     // Action to be done with the exit code. If set, also makes the task wait
     // until all its watched children exit before collecting the status.
     on_exit:         Option<~fn(bool)>,
     // nesting level counter for task::unkillable calls (0 == killable).
-    unkillable:      int,
+    priv unkillable:      int,
     // nesting level counter for unstable::atomically calls (0 == can deschedule).
-    wont_sleep:      int,
+    priv wont_sleep:      int,
     // A "spare" handle to the kill flag inside the kill handle. Used during
     // blocking/waking as an optimization to avoid two xadds on the refcount.
-    spare_kill_flag: Option<KillFlagHandle>,
+    priv spare_kill_flag: Option<KillFlagHandle>,
 }
 
 impl Drop for KillFlag {
diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs
index 262da9f3b8e..14df292343e 100644
--- a/src/libstd/rt/local_heap.rs
+++ b/src/libstd/rt/local_heap.rs
@@ -32,8 +32,8 @@ pub type OpaqueBox = c_void;
 pub type TypeDesc = c_void;
 
 pub struct LocalHeap {
-    memory_region: *MemoryRegion,
-    boxed_region: *BoxedRegion
+    priv memory_region: *MemoryRegion,
+    priv boxed_region: *BoxedRegion
 }
 
 impl LocalHeap {
diff --git a/src/libstd/rt/rc.rs b/src/libstd/rt/rc.rs
index 2ba00c3a2fb..2699dab6d38 100644
--- a/src/libstd/rt/rc.rs
+++ b/src/libstd/rt/rc.rs
@@ -24,7 +24,7 @@ use libc::c_void;
 use cast;
 
 pub struct RC<T> {
-    p: *c_void // ~(uint, T)
+    priv p: *c_void // ~(uint, T)
 }
 
 impl<T> RC<T> {
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index ca521c792dc..501def8b060 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -66,7 +66,7 @@ pub struct FileOpenConfig {
     /// Flags for file access mode (as per open(2))
     flags: int,
     /// File creation mode, ignored unless O_CREAT is passed as part of flags
-    mode: int
+    priv mode: int
 }
 
 pub trait IoFactory {
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 336d2518e43..ee163bab3c0 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -66,26 +66,26 @@ pub struct Scheduler {
     event_loop: ~EventLoopObject,
     /// The scheduler runs on a special task. When it is not running
     /// it is stored here instead of the work queue.
-    sched_task: Option<~Task>,
+    priv sched_task: Option<~Task>,
     /// An action performed after a context switch on behalf of the
     /// code running before the context switch
-    cleanup_job: Option<CleanupJob>,
+    priv cleanup_job: Option<CleanupJob>,
     /// Should this scheduler run any task, or only pinned tasks?
     run_anything: bool,
     /// If the scheduler shouldn't run some tasks, a friend to send
     /// them to.
-    friend_handle: Option<SchedHandle>,
+    priv friend_handle: Option<SchedHandle>,
     /// A fast XorShift rng for scheduler use
     rng: XorShiftRng,
     /// A toggleable idle callback
-    idle_callback: Option<~PausibleIdleCallback>,
+    priv idle_callback: Option<~PausibleIdleCallback>,
     /// A countdown that starts at a random value and is decremented
     /// every time a yield check is performed. When it hits 0 a task
     /// will yield.
-    yield_check_count: uint,
+    priv yield_check_count: uint,
     /// A flag to tell the scheduler loop it needs to do some stealing
     /// in order to introduce randomness as part of a yield
-    steal_for_yield: bool
+    priv steal_for_yield: bool
 }
 
 /// An indication of how hard to work on a given operation, the difference
@@ -431,7 +431,7 @@ impl Scheduler {
     fn try_steals(&mut self) -> Option<~Task> {
         let work_queues = &mut self.work_queues;
         let len = work_queues.len();
-        let start_index = self.rng.gen_integer_range(0, len);
+        let start_index = self.rng.gen_range(0, len);
         for index in range(0, len).map(|i| (i + start_index) % len) {
             match work_queues[index].steal() {
                 Some(task) => {
diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs
index fddee5882b9..55bd4b0732a 100644
--- a/src/libstd/rt/stack.rs
+++ b/src/libstd/rt/stack.rs
@@ -15,8 +15,8 @@ use ops::Drop;
 use libc::{c_uint, uintptr_t};
 
 pub struct StackSegment {
-    buf: ~[u8],
-    valgrind_id: c_uint
+    priv buf: ~[u8],
+    priv valgrind_id: c_uint
 }
 
 impl StackSegment {
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index a6f9e11e40e..c4f352501a0 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -44,7 +44,7 @@ use send_str::SendStr;
 
 pub struct Task {
     heap: LocalHeap,
-    gc: GarbageCollector,
+    priv gc: GarbageCollector,
     storage: LocalStorage,
     logger: StdErrLogger,
     unwinder: Unwinder,
@@ -69,7 +69,7 @@ pub struct Coroutine {
     /// The segment of stack on which the task is currently running or
     /// if the task is blocked, on which the task will resume
     /// execution.
-    current_stack_segment: StackSegment,
+    priv current_stack_segment: StackSegment,
     /// Always valid if the task is alive and not running.
     saved_context: Context
 }
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
index e774b81da35..949d73ecc4f 100644
--- a/src/libstd/rt/thread.rs
+++ b/src/libstd/rt/thread.rs
@@ -18,9 +18,9 @@ use uint;
 type raw_thread = libc::c_void;
 
 pub struct Thread {
-    main: ~fn(),
-    raw_thread: *raw_thread,
-    joined: bool,
+    priv main: ~fn(),
+    priv raw_thread: *raw_thread,
+    priv joined: bool
 }
 
 impl Thread {
diff --git a/src/libstd/rt/tube.rs b/src/libstd/rt/tube.rs
index b8e535e4c7d..16fd3fa38ea 100644
--- a/src/libstd/rt/tube.rs
+++ b/src/libstd/rt/tube.rs
@@ -28,7 +28,7 @@ struct TubeState<T> {
 }
 
 pub struct Tube<T> {
-    p: RC<TubeState<T>>
+    priv p: RC<TubeState<T>>
 }
 
 impl<T> Tube<T> {
diff --git a/src/libstd/rt/uv/addrinfo.rs b/src/libstd/rt/uv/addrinfo.rs
index 83a7e64b139..f2abcd3aca7 100644
--- a/src/libstd/rt/uv/addrinfo.rs
+++ b/src/libstd/rt/uv/addrinfo.rs
@@ -25,7 +25,7 @@ type GetAddrInfoCallback = ~fn(GetAddrInfoRequest, &UvAddrInfo, Option<UvError>)
 pub struct GetAddrInfoRequest(*uvll::uv_getaddrinfo_t);
 
 pub struct RequestData {
-    getaddrinfo_cb: Option<GetAddrInfoCallback>,
+    priv getaddrinfo_cb: Option<GetAddrInfoCallback>,
 }
 
 impl GetAddrInfoRequest {
diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs
index 3a6d858df79..5d64ca4d755 100644
--- a/src/libstd/rt/uv/file.rs
+++ b/src/libstd/rt/uv/file.rs
@@ -25,7 +25,7 @@ pub struct FsRequest(*uvll::uv_fs_t);
 impl Request for FsRequest {}
 
 pub struct RequestData {
-    complete_cb: Option<FsCallback>
+    priv complete_cb: Option<FsCallback>
 }
 
 impl FsRequest {
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs
index 67926b35a62..3a6a3acbc53 100644
--- a/src/libstd/rt/uv/mod.rs
+++ b/src/libstd/rt/uv/mod.rs
@@ -80,7 +80,7 @@ pub mod pipe;
 /// with dtors may not be destructured, but tuple structs can,
 /// but the results are not correct.
 pub struct Loop {
-    handle: *uvll::uv_loop_t
+    priv handle: *uvll::uv_loop_t
 }
 
 /// The trait implemented by uv 'watchers' (handles). Watchers are
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index c7e51b3485d..8dd0f8a6b10 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -180,7 +180,7 @@ fn socket_name<T, U: Watcher + NativeHandle<*T>>(sk: SocketNameKind,
 
 // Obviously an Event Loop is always home.
 pub struct UvEventLoop {
-    uvio: UvIoFactory
+    priv uvio: UvIoFactory
 }
 
 impl UvEventLoop {
@@ -240,9 +240,9 @@ impl EventLoop for UvEventLoop {
 }
 
 pub struct UvPausibleIdleCallback {
-    watcher: IdleWatcher,
-    idle_flag: bool,
-    closed: bool
+    priv watcher: IdleWatcher,
+    priv idle_flag: bool,
+    priv closed: bool
 }
 
 impl UvPausibleIdleCallback {
@@ -294,10 +294,10 @@ fn test_callback_run_once() {
 // The entire point of async is to call into a loop from other threads so it does not need to home.
 pub struct UvRemoteCallback {
     // The uv async handle for triggering the callback
-    async: AsyncWatcher,
+    priv async: AsyncWatcher,
     // A flag to tell the callback to exit, set from the dtor. This is
     // almost never contested - only in rare races with the dtor.
-    exit_flag: Exclusive<bool>
+    priv exit_flag: Exclusive<bool>
 }
 
 impl UvRemoteCallback {
@@ -804,8 +804,8 @@ impl IoFactory for UvIoFactory {
 }
 
 pub struct UvTcpListener {
-    watcher : TcpWatcher,
-    home: SchedHandle,
+    priv watcher : TcpWatcher,
+    priv home: SchedHandle,
 }
 
 impl HomingIO for UvTcpListener {
@@ -866,8 +866,8 @@ impl RtioTcpListener for UvTcpListener {
 }
 
 pub struct UvTcpAcceptor {
-    listener: UvTcpListener,
-    incoming: Tube<Result<~RtioTcpStreamObject, IoError>>,
+    priv listener: UvTcpListener,
+    priv incoming: Tube<Result<~RtioTcpStreamObject, IoError>>,
 }
 
 impl HomingIO for UvTcpAcceptor {
@@ -991,7 +991,7 @@ fn write_stream(mut watcher: StreamWatcher,
 
 pub struct UvUnboundPipe {
     pipe: Pipe,
-    home: SchedHandle,
+    priv home: SchedHandle,
 }
 
 impl HomingIO for UvUnboundPipe {
@@ -1043,8 +1043,8 @@ impl RtioPipe for UvPipeStream {
 }
 
 pub struct UvTcpStream {
-    watcher: TcpWatcher,
-    home: SchedHandle,
+    priv watcher: TcpWatcher,
+    priv home: SchedHandle,
 }
 
 impl HomingIO for UvTcpStream {
@@ -1143,8 +1143,8 @@ impl RtioTcpStream for UvTcpStream {
 }
 
 pub struct UvUdpSocket {
-    watcher: UdpWatcher,
-    home: SchedHandle,
+    priv watcher: UdpWatcher,
+    priv home: SchedHandle,
 }
 
 impl HomingIO for UvUdpSocket {
@@ -1353,8 +1353,8 @@ impl RtioUdpSocket for UvUdpSocket {
 }
 
 pub struct UvTimer {
-    watcher: timer::TimerWatcher,
-    home: SchedHandle,
+    priv watcher: timer::TimerWatcher,
+    priv home: SchedHandle,
 }
 
 impl HomingIO for UvTimer {
@@ -1400,10 +1400,10 @@ impl RtioTimer for UvTimer {
 }
 
 pub struct UvFileStream {
-    loop_: Loop,
-    fd: c_int,
-    close_on_drop: bool,
-    home: SchedHandle
+    priv loop_: Loop,
+    priv fd: c_int,
+    priv close_on_drop: bool,
+    priv home: SchedHandle
 }
 
 impl HomingIO for UvFileStream {
@@ -1533,11 +1533,11 @@ impl RtioFileStream for UvFileStream {
 }
 
 pub struct UvProcess {
-    process: process::Process,
+    priv process: process::Process,
 
     // Sadly, this structure must be created before we return it, so in that
     // brief interim the `home` is None.
-    home: Option<SchedHandle>,
+    priv home: Option<SchedHandle>,
 
     // All None until the process exits (exit_error may stay None)
     priv exit_status: Option<int>,
diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs
index a80d5cbc1fb..96c5dd068d0 100644
--- a/src/libstd/rt/uv/uvll.rs
+++ b/src/libstd/rt/uv/uvll.rs
@@ -134,26 +134,26 @@ pub type uv_pipe_t = c_void;
 
 pub struct uv_timespec_t {
     tv_sec: libc::c_long,
-    tv_nsec: libc::c_long
+    priv tv_nsec: libc::c_long
 }
 
 pub struct uv_stat_t {
-    st_dev: libc::uint64_t,
+    priv st_dev: libc::uint64_t,
     st_mode: libc::uint64_t,
-    st_nlink: libc::uint64_t,
-    st_uid: libc::uint64_t,
-    st_gid: libc::uint64_t,
-    st_rdev: libc::uint64_t,
-    st_ino: libc::uint64_t,
+    priv st_nlink: libc::uint64_t,
+    priv st_uid: libc::uint64_t,
+    priv st_gid: libc::uint64_t,
+    priv st_rdev: libc::uint64_t,
+    priv st_ino: libc::uint64_t,
     st_size: libc::uint64_t,
-    st_blksize: libc::uint64_t,
-    st_blocks: libc::uint64_t,
-    st_flags: libc::uint64_t,
-    st_gen: libc::uint64_t,
+    priv st_blksize: libc::uint64_t,
+    priv st_blocks: libc::uint64_t,
+    priv st_flags: libc::uint64_t,
+    priv st_gen: libc::uint64_t,
     st_atim: uv_timespec_t,
     st_mtim: uv_timespec_t,
     st_ctim: uv_timespec_t,
-    st_birthtim: uv_timespec_t
+    priv st_birthtim: uv_timespec_t
 }
 
 impl uv_stat_t {
@@ -231,37 +231,37 @@ pub type socklen_t = c_int;
 #[cfg(target_os = "android")]
 #[cfg(target_os = "linux")]
 pub struct addrinfo {
-    ai_flags: c_int,
-    ai_family: c_int,
-    ai_socktype: c_int,
-    ai_protocol: c_int,
-    ai_addrlen: socklen_t,
+    priv ai_flags: c_int,
+    priv ai_family: c_int,
+    priv ai_socktype: c_int,
+    priv ai_protocol: c_int,
+    priv ai_addrlen: socklen_t,
     ai_addr: *sockaddr,
-    ai_canonname: *char,
+    priv ai_canonname: *char,
     ai_next: *addrinfo
 }
 
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
 pub struct addrinfo {
-    ai_flags: c_int,
-    ai_family: c_int,
-    ai_socktype: c_int,
-    ai_protocol: c_int,
-    ai_addrlen: socklen_t,
-    ai_canonname: *char,
+    priv ai_flags: c_int,
+    priv ai_family: c_int,
+    priv ai_socktype: c_int,
+    priv ai_protocol: c_int,
+    priv ai_addrlen: socklen_t,
+    priv ai_canonname: *char,
     ai_addr: *sockaddr,
     ai_next: *addrinfo
 }
 
 #[cfg(windows)]
 pub struct addrinfo {
-    ai_flags: c_int,
-    ai_family: c_int,
-    ai_socktype: c_int,
-    ai_protocol: c_int,
-    ai_addrlen: size_t,
-    ai_canonname: *char,
+    priv ai_flags: c_int,
+    priv ai_family: c_int,
+    priv ai_socktype: c_int,
+    priv ai_protocol: c_int,
+    priv ai_addrlen: size_t,
+    priv ai_canonname: *char,
     ai_addr: *sockaddr,
     ai_next: *addrinfo
 }
@@ -960,8 +960,8 @@ pub unsafe fn freeaddrinfo(ai: *addrinfo) {
 }
 
 pub struct uv_err_data {
-    err_name: ~str,
-    err_msg: ~str,
+    priv err_name: ~str,
+    priv err_msg: ~str,
 }
 
 extern {
diff --git a/src/libstd/run.rs b/src/libstd/run.rs
index 36e73a6dd51..c4cb8be2061 100644
--- a/src/libstd/run.rs
+++ b/src/libstd/run.rs
@@ -34,7 +34,6 @@ pub struct Process {
 
 /// Options that can be given when starting a Process.
 pub struct ProcessOptions<'self> {
-
     /**
      * If this is None then the new process will have the same initial
      * environment as the parent process.
@@ -99,7 +98,6 @@ impl <'self> ProcessOptions<'self> {
 
 /// The output of a finished process.
 pub struct ProcessOutput {
-
     /// The status (exit code) of the process.
     status: int,
 
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 883934124a6..f134788942c 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -998,7 +998,6 @@ pub fn utf8_char_width(b: u8) -> uint {
 pub struct CharRange {
     /// Current `char`
     ch: char,
-
     /// Index of the first byte of the next `char`
     next: uint
 }
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index 970a62b676f..30c99c62885 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -108,7 +108,7 @@ pub enum SchedMode {
  *
  */
 pub struct SchedOpts {
-    mode: SchedMode,
+    priv mode: SchedMode,
 }
 
 /**
@@ -144,11 +144,11 @@ pub struct SchedOpts {
  *           scheduler other tasks will be impeded or even blocked indefinitely.
  */
 pub struct TaskOpts {
-    linked: bool,
-    supervised: bool,
-    watched: bool,
-    indestructible: bool,
-    notify_chan: Option<Chan<TaskResult>>,
+    priv linked: bool,
+    priv supervised: bool,
+    priv watched: bool,
+    priv indestructible: bool,
+    priv notify_chan: Option<Chan<TaskResult>>,
     name: Option<SendStr>,
     sched: SchedOpts,
     stack_size: Option<uint>
@@ -170,9 +170,9 @@ pub struct TaskOpts {
 // FIXME (#3724): Replace the 'consumed' bit with move mode on self
 pub struct TaskBuilder {
     opts: TaskOpts,
-    gen_body: Option<~fn(v: ~fn()) -> ~fn()>,
-    can_not_copy: Option<util::NonCopyable>,
-    consumed: bool,
+    priv gen_body: Option<~fn(v: ~fn()) -> ~fn()>,
+    priv can_not_copy: Option<util::NonCopyable>,
+    priv consumed: bool,
 }
 
 /**
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index 7cf0f04c7e9..dec13eded39 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -308,10 +308,10 @@ fn each_ancestor(list:        &mut AncestorList,
 // One of these per task.
 pub struct Taskgroup {
     // List of tasks with whose fates this one's is intertwined.
-    tasks:      TaskGroupArc, // 'none' means the group has failed.
+    priv tasks:      TaskGroupArc, // 'none' means the group has failed.
     // Lists of tasks who will kill us if they fail, but whom we won't kill.
-    ancestors:  AncestorList,
-    notifier:   Option<AutoNotify>,
+    priv ancestors:  AncestorList,
+    priv notifier:   Option<AutoNotify>,
 }
 
 impl Drop for Taskgroup {
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 68fdfd73013..ee44bf4d996 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -49,23 +49,23 @@ pub struct TyDesc {
     align: uint,
 
     // Called on a copy of a value of type `T` *after* memcpy
-    take_glue: GlueFn,
+    priv take_glue: GlueFn,
 
     // Called when a value of type `T` is no longer needed
     drop_glue: GlueFn,
 
     // Called by drop glue when a value of type `T` can be freed
-    free_glue: GlueFn,
+    priv free_glue: GlueFn,
 
     // Called by reflection visitor to visit a value of type `T`
-    visit_glue: GlueFn,
+    priv visit_glue: GlueFn,
 
     // If T represents a box pointer (`@U` or `~U`), then
     // `borrow_offset` is the amount that the pointer must be adjusted
     // to find the payload.  This is always derivable from the type
     // `U`, but in the case of `@Trait` or `~Trait` objects, the type
     // `U` is unknown.
-    borrow_offset: uint,
+    priv borrow_offset: uint,
 
     // Name corresponding to the type
     name: &'static str
diff --git a/src/libstd/unstable/raw.rs b/src/libstd/unstable/raw.rs
index ac0e83df7ef..b5d7cc47fdc 100644
--- a/src/libstd/unstable/raw.rs
+++ b/src/libstd/unstable/raw.rs
@@ -15,7 +15,7 @@ use unstable::intrinsics::TyDesc;
 pub struct Box<T> {
     ref_count: uint,
     type_desc: *TyDesc,
-    prev: *Box<T>,
+    priv prev: *Box<T>,
     next: *Box<T>,
     data: T
 }
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
index 4c6ad469d8c..9d15dd031e0 100644
--- a/src/libstd/unstable/sync.rs
+++ b/src/libstd/unstable/sync.rs
@@ -304,7 +304,7 @@ pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
 type rust_little_lock = *libc::c_void;
 
 pub struct LittleLock {
-    l: rust_little_lock,
+    priv l: rust_little_lock,
 }
 
 impl Drop for LittleLock {
@@ -353,7 +353,7 @@ struct ExData<T> {
  * need to block or deschedule while accessing shared state, use extra::sync::RWArc.
  */
 pub struct Exclusive<T> {
-    x: UnsafeArc<ExData<T>>
+    priv x: UnsafeArc<ExData<T>>
 }
 
 impl<T:Send> Clone for Exclusive<T> {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 01033e829f6..372f1950c1d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -227,7 +227,7 @@ pub enum MethodProvenance {
 pub enum Def {
     DefFn(DefId, purity),
     DefStaticMethod(/* method */ DefId, MethodProvenance, purity),
-    DefSelf(NodeId),
+    DefSelf(NodeId, bool /* is_mutbl */),
     DefSelfTy(/* trait id */ NodeId),
     DefMod(DefId),
     DefForeignMod(DefId),
@@ -921,10 +921,10 @@ pub enum ret_style {
 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum explicit_self_ {
     sty_static,                                // no self
-    sty_value,                                 // `self`
-    sty_region(Option<Lifetime>, Mutability), // `&'lt self`
+    sty_value(Mutability),                     // `self`
+    sty_region(Option<Lifetime>, Mutability),  // `&'lt self`
     sty_box(Mutability),                       // `@self`
-    sty_uniq                                   // `~self`
+    sty_uniq(Mutability)                       // `~self`
 }
 
 pub type explicit_self = Spanned<explicit_self_>;
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index bdebc9872e6..1d9d5512ff4 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -66,7 +66,7 @@ pub fn def_id_of_def(d: Def) -> DefId {
       DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
         id
       }
-      DefArg(id, _) | DefLocal(id, _) | DefSelf(id) | DefSelfTy(id)
+      DefArg(id, _) | DefLocal(id, _) | DefSelf(id, _) | DefSelfTy(id)
       | DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
       | DefTyParamBinder(id) | DefLabel(id) => {
         local_def(id)
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index 83c73e3d85f..c60259304ae 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -240,13 +240,13 @@ pub fn get_explicit_self(cx: @ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
     let self_path = cx.expr_self(span);
     match *self_ptr {
         None => {
-            (self_path, respan(span, ast::sty_value))
+            (self_path, respan(span, ast::sty_value(ast::MutImmutable)))
         }
         Some(ref ptr) => {
             let self_ty = respan(
                 span,
                 match *ptr {
-                    Send => ast::sty_uniq,
+                    Send => ast::sty_uniq(ast::MutImmutable),
                     Managed(mutbl) => ast::sty_box(mutbl),
                     Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ed6019e1a55..605e259cf0c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3438,15 +3438,11 @@ impl Parser {
 
     // parse the argument list and result type of a function
     // that may have a self type.
-    fn parse_fn_decl_with_self(
-        &self,
-        parse_arg_fn:
-        &fn(&Parser) -> arg
-    ) -> (explicit_self, fn_decl) {
-        fn maybe_parse_explicit_self(
-            cnstr: &fn(v: Mutability) -> ast::explicit_self_,
-            p: &Parser
-        ) -> ast::explicit_self_ {
+    fn parse_fn_decl_with_self(&self, parse_arg_fn: &fn(&Parser) -> arg)
+        -> (explicit_self, fn_decl) {
+
+        fn maybe_parse_explicit_self(cnstr: &fn(v: Mutability) -> ast::explicit_self_,
+                                     p: &Parser) -> ast::explicit_self_ {
             // We need to make sure it isn't a type
             if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) ||
                 ((p.look_ahead(1, |t| token::is_keyword(keywords::Const, t)) ||
@@ -3524,25 +3520,39 @@ impl Parser {
                     self.span_err(*self.last_span,
                                   "mutability declaration not allowed here");
                 }
-                sty_uniq
+                sty_uniq(MutImmutable)
             }, self)
           }
           token::IDENT(*) if self.is_self_ident() => {
             self.bump();
-            sty_value
+            sty_value(MutImmutable)
           }
           token::BINOP(token::STAR) => {
             // Possibly "*self" or "*mut self" -- not supported. Try to avoid
             // emitting cryptic "unexpected token" errors.
             self.bump();
-            if self.token_is_mutability(self.token) {
-                self.bump();
-            }
+            let mutability = if self.token_is_mutability(self.token) {
+                self.parse_mutability()
+            } else { MutImmutable };
             if self.is_self_ident() {
                 self.span_err(*self.span, "cannot pass self by unsafe pointer");
                 self.bump();
             }
-            sty_value
+            sty_value(mutability)
+          }
+          _ if self.token_is_mutability(self.token) &&
+               self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
+            let mutability = self.parse_mutability();
+            self.expect_self_ident();
+            sty_value(mutability)
+          }
+          _ if self.token_is_mutability(self.token) &&
+               self.look_ahead(1, |t| *t == token::TILDE) &&
+               self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
+            let mutability = self.parse_mutability();
+            self.bump();
+            self.expect_self_ident();
+            sty_uniq(mutability)
           }
           _ => {
             sty_static
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b245bd75ace..0e330da31e6 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1686,8 +1686,14 @@ pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_in
 pub fn print_explicit_self(s: @ps, explicit_self: ast::explicit_self_) -> bool {
     match explicit_self {
         ast::sty_static => { return false; }
-        ast::sty_value => { word(s.s, "self"); }
-        ast::sty_uniq => { word(s.s, "~self"); }
+        ast::sty_value(m) => {
+            print_mutability(s, m);
+            word(s.s, "self");
+        }
+        ast::sty_uniq(m) => {
+            print_mutability(s, m);
+            word(s.s, "~self");
+        }
         ast::sty_region(ref lt, m) => {
             word(s.s, "&");
             print_opt_lifetime(s, lt);
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 17f05b59090..77020537661 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -672,6 +672,8 @@ extern "C" CDECL void
 rust_win32_rand_acquire(HCRYPTPROV* phProv) {
     win32_require
         (_T("CryptAcquireContext"),
+         // changes to the parameters here should be reflected in the docs of
+         // std::rand::os::OSRng
          CryptAcquireContext(phProv, NULL, NULL, PROV_RSA_FULL,
                              CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
 
diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs
index f549f747ef7..dbd1edffe78 100644
--- a/src/test/bench/core-std.rs
+++ b/src/test/bench/core-std.rs
@@ -90,7 +90,7 @@ fn vec_plus() {
     let mut v = ~[];
     let mut i = 0;
     while i < 1500 {
-        let rv = vec::from_elem(r.gen_integer_range(0u, i + 1), i);
+        let rv = vec::from_elem(r.gen_range(0u, i + 1), i);
         if r.gen() {
             v.push_all_move(rv);
         } else {
@@ -106,7 +106,7 @@ fn vec_append() {
     let mut v = ~[];
     let mut i = 0;
     while i < 1500 {
-        let rv = vec::from_elem(r.gen_integer_range(0u, i + 1), i);
+        let rv = vec::from_elem(r.gen_range(0u, i + 1), i);
         if r.gen() {
             v = vec::append(v, rv);
         }
@@ -122,7 +122,7 @@ fn vec_push_all() {
 
     let mut v = ~[];
     for i in range(0u, 1500) {
-        let mut rv = vec::from_elem(r.gen_integer_range(0u, i + 1), i);
+        let mut rv = vec::from_elem(r.gen_range(0u, i + 1), i);
         if r.gen() {
             v.push_all(rv);
         }
diff --git a/src/test/compile-fail/issue-5216.rs b/src/test/compile-fail/issue-5216.rs
new file mode 100644
index 00000000000..9f88ba72f05
--- /dev/null
+++ b/src/test/compile-fail/issue-5216.rs
@@ -0,0 +1,20 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn f() { }
+struct S(&fn()); //~ ERROR Illegal anonymous lifetime
+pub static C: S = S(f); //~ ERROR Illegal anonymous lifetime
+
+
+fn g() { }
+type T = &fn(); //~ ERROR Illegal anonymous lifetime
+pub static D: T = g; //~ ERROR Illegal anonymous lifetime
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-5500-1.rs b/src/test/compile-fail/issue-5500-1.rs
new file mode 100644
index 00000000000..f709aadf4ac
--- /dev/null
+++ b/src/test/compile-fail/issue-5500-1.rs
@@ -0,0 +1,22 @@
+// Copyright 2013 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.
+
+// xfail-test
+
+struct TrieMapIterator<'self> {
+    priv node: &'self uint
+}
+
+fn main() {
+    let a = 5;
+    let _iter = TrieMapIterator{node: &a};  //~ ERROR bad
+    _iter.node = &
+    fail!()
+}
diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/compile-fail/issue-5500.rs
new file mode 100644
index 00000000000..7bf20037f5a
--- /dev/null
+++ b/src/test/compile-fail/issue-5500.rs
@@ -0,0 +1,13 @@
+// Copyright 2013 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.
+
+// xfail-test
+
+fn main() { &fail!() } //~ ERROR bad
diff --git a/src/test/run-pass/by-value-self-in-mut-slot.rs b/src/test/run-pass/by-value-self-in-mut-slot.rs
new file mode 100644
index 00000000000..aa88004cd11
--- /dev/null
+++ b/src/test/run-pass/by-value-self-in-mut-slot.rs
@@ -0,0 +1,30 @@
+// Copyright 2013 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.
+
+struct X {
+    a: int
+}
+
+trait Changer {
+    fn change(mut self) -> Self;
+}
+
+impl Changer for X {
+    fn change(mut self) -> X {
+        self.a = 55;
+        self
+    }
+}
+
+pub fn main() {
+    let x = X { a: 32 };
+    let new_x = x.change();
+    assert_eq!(new_x.a, 55);
+}
diff --git a/src/test/run-pass/issue-6334.rs b/src/test/run-pass/issue-6334.rs
new file mode 100644
index 00000000000..740a2212726
--- /dev/null
+++ b/src/test/run-pass/issue-6334.rs
@@ -0,0 +1,56 @@
+// Copyright 2013 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.
+
+// xfail-test
+
+// Tests that everything still compiles and runs fine even when
+// we reorder the bounds.
+
+trait A {
+    fn a(&self) -> uint;
+}
+
+trait B {
+    fn b(&self) -> uint;
+}
+
+trait C {
+    fn combine<T:A+B>(&self, t: &T) -> uint;
+}
+
+struct Foo;
+
+impl A for Foo {
+    fn a(&self) -> uint { 1 }
+}
+
+impl B for Foo {
+    fn b(&self) -> uint { 2 }
+}
+
+struct Bar;
+
+impl C for Bar {
+    // Note below: bounds in impl decl are in reverse order.
+    fn combine<T:B+A>(&self, t: &T) -> uint {
+        (t.a() * 100) + t.b()
+    }
+}
+
+fn use_c<S:C, T:B+A>(s: &S, t: &T) -> uint {
+    s.combine(t)
+}
+
+fn main() {
+    let foo = Foo;
+    let bar = Bar;
+    let r = use_c(&bar, &foo);
+    assert_eq!(r, 102);
+}
diff --git a/src/test/run-pass/self-in-mut-slot-default-method.rs b/src/test/run-pass/self-in-mut-slot-default-method.rs
new file mode 100644
index 00000000000..08d10fd1170
--- /dev/null
+++ b/src/test/run-pass/self-in-mut-slot-default-method.rs
@@ -0,0 +1,43 @@
+// Copyright 2013 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.
+
+struct X {
+    a: int
+}
+
+trait Changer {
+    fn change(mut self) -> Self {
+        self.set_to(55);
+        self
+    }
+
+    fn change_again(mut ~self) -> ~Self {
+        self.set_to(45);
+        self
+    }
+
+    fn set_to(&mut self, a: int);
+}
+
+impl Changer for X {
+    fn set_to(&mut self, a: int) {
+        self.a = a;
+    }
+}
+
+pub fn main() {
+    let x = X { a: 32 };
+    let new_x = x.change();
+    assert_eq!(new_x.a, 55);
+
+    let x = ~new_x;
+    let new_x = x.change_again();
+    assert_eq!(new_x.a, 45);
+}
diff --git a/src/test/run-pass/uniq-self-in-mut-slot.rs b/src/test/run-pass/uniq-self-in-mut-slot.rs
new file mode 100644
index 00000000000..7c2f5221176
--- /dev/null
+++ b/src/test/run-pass/uniq-self-in-mut-slot.rs
@@ -0,0 +1,30 @@
+// Copyright 2013 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.
+
+struct X {
+    a: int
+}
+
+trait Changer {
+    fn change(mut ~self) -> ~Self;
+}
+
+impl Changer for X {
+    fn change(mut ~self) -> ~X {
+        self.a = 55;
+        self
+    }
+}
+
+pub fn main() {
+    let x = ~X { a: 32 };
+    let new_x = x.change();
+    assert_eq!(new_x.a, 55);
+}