about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-08-27 23:25:38 +0000
committerbors <bors@rust-lang.org>2015-08-27 23:25:38 +0000
commit8dba06aeee28e9ed6a1b9918a91cbef242af53d3 (patch)
tree3eafdb047257f17e55f56408801e9df45cbbf5f4
parent79dd92fc1638463ab8af1d275686c4751ce91465 (diff)
parenta63cd9b5a165ca86529e678b9fea642bdae2e156 (diff)
downloadrust-8dba06aeee28e9ed6a1b9918a91cbef242af53d3.tar.gz
rust-8dba06aeee28e9ed6a1b9918a91cbef242af53d3.zip
Auto merge of #28052 - Manishearth:rollup, r=Manishearth
- Successful merges: #28010, #28013, #28022, #28029, #28033, #28039, #28045, #28048
- Failed merges: 
-rw-r--r--src/doc/trpl/testing.md15
-rw-r--r--src/libcore/macros.rs45
-rw-r--r--src/libcore/option.rs20
-rw-r--r--src/libcore/result.rs20
-rw-r--r--src/libcoretest/iter.rs53
-rw-r--r--src/libcoretest/option.rs9
-rw-r--r--src/libcoretest/result.rs33
-rw-r--r--src/librustc_typeck/diagnostics.rs215
-rw-r--r--src/libstd/path.rs7
-rw-r--r--src/libsyntax/codemap.rs43
-rw-r--r--src/libsyntax/diagnostic.rs8
-rw-r--r--src/libsyntax/ext/asm.rs5
-rw-r--r--src/libsyntax/ext/base.rs9
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs5
-rw-r--r--src/libsyntax/ext/expand.rs60
-rw-r--r--src/libsyntax/std_inject.rs6
-rw-r--r--src/libsyntax/test.rs8
-rw-r--r--src/rustbook/static/rustbook.css4
-rw-r--r--src/test/compile-fail-fulldeps/qquote.rs3
-rw-r--r--src/test/run-fail-fulldeps/qquote.rs3
-rw-r--r--src/test/run-pass-fulldeps/qquote.rs4
21 files changed, 430 insertions, 145 deletions
diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md
index 78803afd5c1..587f60343c3 100644
--- a/src/doc/trpl/testing.md
+++ b/src/doc/trpl/testing.md
@@ -120,13 +120,26 @@ And that's reflected in the summary line:
 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
 ```
 
-We also get a non-zero status code:
+We also get a non-zero status code. We can use `$?` on OS X and Linux:
 
 ```bash
 $ echo $?
 101
 ```
 
+On Windows, if you’re using `cmd`:
+
+```bash
+> echo %ERRORLEVEL%
+```
+
+And if you’re using PowerShell:
+
+```bash
+> echo $LASTEXITCODE # the code itself
+> echo $? # a boolean, fail or succeed
+```
+
 This is useful if you want to integrate `cargo test` into other tooling.
 
 We can invert our test's failure with another attribute: `should_panic`:
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 9f4d61a50d5..21038f25be3 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -254,6 +254,51 @@ macro_rules! unreachable {
 
 /// A standardised placeholder for marking unfinished code. It panics with the
 /// message `"not yet implemented"` when executed.
+///
+/// This can be useful if you are prototyping and are just looking to have your
+/// code typecheck, or if you're implementing a trait that requires multiple
+/// methods, and you're only planning on using one of them.
+///
+/// # Examples
+///
+/// Here's an example of some in-progress code. We have a trait `Foo`:
+///
+/// ```
+/// trait Foo {
+///     fn bar(&self);
+///     fn baz(&self);
+/// }
+/// ```
+///
+/// We want to implement `Foo` on one of our types, but we also want to work on
+/// just `bar()` first. In order for our code to compile, we need to implement
+/// `baz()`, so we can use `unimplemented!`:
+///
+/// ```
+/// # trait Foo {
+/// #     fn foo(&self);
+/// #     fn bar(&self);
+/// # }
+/// struct MyStruct;
+///
+/// impl Foo for MyStruct {
+///     fn foo(&self) {
+///         // implementation goes here
+///     }
+///
+///     fn bar(&self) {
+///         // let's not worry about implementing bar() for now
+///         unimplemented!();
+///     }
+/// }
+///
+/// fn main() {
+///     let s = MyStruct;
+///     s.foo();
+///
+///     // we aren't even using bar() yet, so this is fine.
+/// }
+/// ```
 #[macro_export]
 #[unstable(feature = "core",
            reason = "relationship with panic is unclear")]
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index e64048c82d8..a36a120689c 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -779,6 +779,26 @@ impl<T> IntoIterator for Option<T> {
     }
 }
 
+#[stable(since = "1.4.0", feature = "option_iter")]
+impl<'a, T> IntoIterator for &'a Option<T> {
+    type Item = &'a T;
+    type IntoIter = Iter<'a, T>;
+
+    fn into_iter(self) -> Iter<'a, T> {
+        self.iter()
+    }
+}
+
+#[stable(since = "1.4.0", feature = "option_iter")]
+impl<'a, T> IntoIterator for &'a mut Option<T> {
+    type Item = &'a mut T;
+    type IntoIter = IterMut<'a, T>;
+
+    fn into_iter(mut self) -> IterMut<'a, T> {
+        self.iter_mut()
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // The Option Iterators
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 8300faa5a16..2546d9cd63d 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -815,6 +815,26 @@ impl<T, E> IntoIterator for Result<T, E> {
     }
 }
 
+#[stable(since = "1.4.0", feature = "result_iter")]
+impl<'a, T, E> IntoIterator for &'a Result<T, E> {
+    type Item = &'a T;
+    type IntoIter = Iter<'a, T>;
+
+    fn into_iter(self) -> Iter<'a, T> {
+        self.iter()
+    }
+}
+
+#[stable(since = "1.4.0", feature = "result_iter")]
+impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
+    type Item = &'a mut T;
+    type IntoIter = IterMut<'a, T>;
+
+    fn into_iter(mut self) -> IterMut<'a, T> {
+        self.iter_mut()
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // The Result Iterators
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index 87e69581c54..9def44191db 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use core::iter::*;
-use core::iter::order::*;
 use core::{i8, i16, isize};
 use core::usize;
 
@@ -21,51 +20,51 @@ fn test_lt() {
     let xs = [1,2,3];
     let ys = [1,2,0];
 
-    assert!(!lt(xs.iter(), ys.iter()));
-    assert!(!le(xs.iter(), ys.iter()));
-    assert!( gt(xs.iter(), ys.iter()));
-    assert!( ge(xs.iter(), ys.iter()));
+    assert!(!xs.iter().lt(ys.iter()));
+    assert!(!xs.iter().le(ys.iter()));
+    assert!( xs.iter().gt(ys.iter()));
+    assert!( xs.iter().ge(ys.iter()));
 
-    assert!( lt(ys.iter(), xs.iter()));
-    assert!( le(ys.iter(), xs.iter()));
-    assert!(!gt(ys.iter(), xs.iter()));
-    assert!(!ge(ys.iter(), xs.iter()));
+    assert!( ys.iter().lt(xs.iter()));
+    assert!( ys.iter().le(xs.iter()));
+    assert!(!ys.iter().gt(xs.iter()));
+    assert!(!ys.iter().ge(xs.iter()));
 
-    assert!( lt(empty.iter(), xs.iter()));
-    assert!( le(empty.iter(), xs.iter()));
-    assert!(!gt(empty.iter(), xs.iter()));
-    assert!(!ge(empty.iter(), xs.iter()));
+    assert!( empty.iter().lt(xs.iter()));
+    assert!( empty.iter().le(xs.iter()));
+    assert!(!empty.iter().gt(xs.iter()));
+    assert!(!empty.iter().ge(xs.iter()));
 
     // Sequence with NaN
     let u = [1.0f64, 2.0];
     let v = [0.0f64/0.0, 3.0];
 
-    assert!(!lt(u.iter(), v.iter()));
-    assert!(!le(u.iter(), v.iter()));
-    assert!(!gt(u.iter(), v.iter()));
-    assert!(!ge(u.iter(), v.iter()));
+    assert!(!u.iter().lt(v.iter()));
+    assert!(!u.iter().le(v.iter()));
+    assert!(!u.iter().gt(v.iter()));
+    assert!(!u.iter().ge(v.iter()));
 
     let a = [0.0f64/0.0];
     let b = [1.0f64];
     let c = [2.0f64];
 
-    assert!(lt(a.iter(), b.iter()) == (a[0] <  b[0]));
-    assert!(le(a.iter(), b.iter()) == (a[0] <= b[0]));
-    assert!(gt(a.iter(), b.iter()) == (a[0] >  b[0]));
-    assert!(ge(a.iter(), b.iter()) == (a[0] >= b[0]));
+    assert!(a.iter().lt(b.iter()) == (a[0] <  b[0]));
+    assert!(a.iter().le(b.iter()) == (a[0] <= b[0]));
+    assert!(a.iter().gt(b.iter()) == (a[0] >  b[0]));
+    assert!(a.iter().ge(b.iter()) == (a[0] >= b[0]));
 
-    assert!(lt(c.iter(), b.iter()) == (c[0] <  b[0]));
-    assert!(le(c.iter(), b.iter()) == (c[0] <= b[0]));
-    assert!(gt(c.iter(), b.iter()) == (c[0] >  b[0]));
-    assert!(ge(c.iter(), b.iter()) == (c[0] >= b[0]));
+    assert!(c.iter().lt(b.iter()) == (c[0] <  b[0]));
+    assert!(c.iter().le(b.iter()) == (c[0] <= b[0]));
+    assert!(c.iter().gt(b.iter()) == (c[0] >  b[0]));
+    assert!(c.iter().ge(b.iter()) == (c[0] >= b[0]));
 }
 
 #[test]
 fn test_multi_iter() {
     let xs = [1,2,3,4];
     let ys = [4,3,2,1];
-    assert!(eq(xs.iter(), ys.iter().rev()));
-    assert!(lt(xs.iter(), xs.iter().skip(2)));
+    assert!(xs.iter().eq(ys.iter().rev()));
+    assert!(xs.iter().lt(xs.iter().skip(2)));
 }
 
 #[test]
diff --git a/src/libcoretest/option.rs b/src/libcoretest/option.rs
index 04271ed5dd1..3e564cf1970 100644
--- a/src/libcoretest/option.rs
+++ b/src/libcoretest/option.rs
@@ -180,11 +180,14 @@ fn test_iter() {
     assert_eq!(it.next(), Some(&val));
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert!(it.next().is_none());
+
+    let mut it = (&x).into_iter();
+    assert_eq!(it.next(), Some(&val));
 }
 
 #[test]
 fn test_mut_iter() {
-    let val = 5;
+    let mut val = 5;
     let new_val = 11;
 
     let mut x = Some(val);
@@ -205,6 +208,10 @@ fn test_mut_iter() {
         assert!(it.next().is_none());
     }
     assert_eq!(x, Some(new_val));
+
+    let mut y = Some(val);
+    let mut it = (&mut y).into_iter();
+    assert_eq!(it.next(), Some(&mut val));
 }
 
 #[test]
diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs
index 02ea6b10e6e..6e9f653dcd8 100644
--- a/src/libcoretest/result.rs
+++ b/src/libcoretest/result.rs
@@ -150,3 +150,36 @@ pub fn test_expect_err() {
     let err: Result<isize, &'static str> = Err("All good");
     err.expect("Got expected error");
 }
+
+#[test]
+pub fn test_iter() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let mut it = ok.iter();
+    assert_eq!(it.size_hint(), (1, Some(1)));
+    assert_eq!(it.next(), Some(&100));
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert!(it.next().is_none());
+    assert_eq!((&ok).into_iter().next(), Some(&100));
+
+    let err: Result<isize, &'static str> = Err("error");
+    assert_eq!(err.iter().next(), None);
+}
+
+#[test]
+pub fn test_iter_mut() {
+    let mut ok: Result<isize, &'static str> = Ok(100);
+    for loc in ok.iter_mut() {
+        *loc = 200;
+    }
+    assert_eq!(ok, Ok(200));
+    for loc in &mut ok {
+        *loc = 300;
+    }
+    assert_eq!(ok, Ok(300));
+
+    let mut err: Result<isize, &'static str> = Err("error");
+    for loc in err.iter_mut() {
+        *loc = 200;
+    }
+    assert_eq!(err, Err("error"));
+}
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 0223079b8bf..0dbfffe5c64 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -73,10 +73,39 @@ the enum.
 "##,
 
 E0025: r##"
-Each field of a struct can only be bound once in a pattern. Each occurrence of a
-field name binds the value of that field, so to fix this error you will have to
-remove or alter the duplicate uses of the field name. Perhaps you misspelt
-another field name?
+Each field of a struct can only be bound once in a pattern. Erroneous code
+example:
+
+```
+struct Foo {
+    a: u8,
+    b: u8,
+}
+
+fn main(){
+    let x = Foo { a:1, b:2 };
+
+    let Foo { a: x, a: y } = x;
+    // error: field `a` bound multiple times in the pattern
+}
+```
+
+Each occurrence of a field name binds the value of that field, so to fix this
+error you will have to remove or alter the duplicate uses of the field name.
+Perhaps you misspelled another field name? Example:
+
+```
+struct Foo {
+    a: u8,
+    b: u8,
+}
+
+fn main(){
+    let x = Foo { a:1, b:2 };
+
+    let Foo { a: x, b: y } = x; // ok!
+}
+```
 "##,
 
 E0026: r##"
@@ -401,10 +430,35 @@ extern "C" {
 "##,
 
 E0046: r##"
+Items are missing in a trait implementation. Erroneous code example:
+
+```
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {}
+// error: not all trait items implemented, missing: `foo`
+```
+
 When trying to make some type implement a trait `Foo`, you must, at minimum,
 provide implementations for all of `Foo`'s required methods (meaning the
 methods that do not have default implementations), as well as any required
-trait items like associated types or constants.
+trait items like associated types or constants. Example:
+
+```
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo() {} // ok!
+}
+```
 "##,
 
 E0049: r##"
@@ -615,14 +669,62 @@ variadic functions (except for its C-FFI).
 
 E0062: r##"
 This error indicates that during an attempt to build a struct or struct-like
-enum variant, one of the fields was specified more than once. Each field should
-be specified exactly one time.
+enum variant, one of the fields was specified more than once. Erroneous code
+example:
+
+```
+struct Foo {
+    x: i32
+}
+
+fn main() {
+    let x = Foo {
+                x: 0,
+                x: 0, // error: field `x` specified more than once
+            };
+}
+```
+
+Each field should be specified exactly one time. Example:
+
+```
+struct Foo {
+    x: i32
+}
+
+fn main() {
+    let x = Foo { x: 0 }; // ok!
+}
+```
 "##,
 
 E0063: r##"
 This error indicates that during an attempt to build a struct or struct-like
-enum variant, one of the fields was not provided. Each field should be
-specified exactly once.
+enum variant, one of the fields was not provided. Erroneous code example:
+
+```
+struct Foo {
+    x: i32,
+    y: i32
+}
+
+fn main() {
+    let x = Foo { x: 0 }; // error: missing field: `y`
+}
+```
+
+Each field should be specified exactly once. Example:
+
+```
+struct Foo {
+    x: i32,
+    y: i32
+}
+
+fn main() {
+    let x = Foo { x: 0, y: 0 }; // ok!
+}
+```
 "##,
 
 E0066: r##"
@@ -1025,7 +1127,7 @@ fn main() {
 }
 ```
 
-The number of supplied parameters much exactly match the number of defined type
+The number of supplied parameters must exactly match the number of defined type
 parameters.
 "##,
 
@@ -1620,6 +1722,12 @@ extern {
 E0131: r##"
 It is not possible to define `main` with type parameters, or even with function
 parameters. When `main` is present, it must take no arguments and return `()`.
+Erroneous code example:
+
+```
+fn main<T>() { // error: main function is not allowed to have type parameters
+}
+```
 "##,
 
 E0132: r##"
@@ -1627,7 +1735,7 @@ It is not possible to declare type parameters on a function that has the `start`
 attribute. Such a function must have the following type signature:
 
 ```
-fn(isize, *const *const u8) -> isize
+fn(isize, *const *const u8) -> isize;
 ```
 "##,
 
@@ -1779,7 +1887,7 @@ rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
 
 E0193: r##"
 `where` clauses must use generic type parameters: it does not make sense to use
-them otherwise.  An example causing this error:
+them otherwise. An example causing this error:
 
 ```
 trait Foo {
@@ -1881,7 +1989,6 @@ unsafe impl Foo { }
 // converting it to this will fix it
 impl Foo { }
 ```
-
 "##,
 
 E0198: r##"
@@ -1898,7 +2005,6 @@ unsafe impl !Clone for Foo { }
 // this will compile
 impl !Clone for Foo { }
 ```
-
 "##,
 
 E0199: r##"
@@ -1916,7 +2022,6 @@ unsafe impl Bar for Foo { }
 // this will compile
 impl Bar for Foo { }
 ```
-
 "##,
 
 E0200: r##"
@@ -1934,7 +2039,6 @@ impl Bar for Foo { }
 // this will compile
 unsafe impl Bar for Foo { }
 ```
-
 "##,
 
 E0201: r##"
@@ -2717,6 +2821,36 @@ It is also possible to overload most operators for your own type by
 implementing traits from `std::ops`.
 "##,
 
+E0370: r##"
+The maximum value of an enum was reached, so it cannot be automatically
+set in the next enum value. Erroneous code example:
+
+```
+enum Foo {
+    X = 0x7fffffffffffffff,
+    Y // error: enum discriminant overflowed on value after
+      //        9223372036854775807: i64; set explicitly via
+      //        Y = -9223372036854775808 if that is desired outcome
+}
+```
+
+To fix this, please set manually the next enum value or put the enum variant
+with the maximum value at the end of the enum. Examples:
+
+```
+enum Foo {
+    X = 0x7fffffffffffffff,
+    Y = 0, // ok!
+}
+
+// or:
+enum Foo {
+    Y = 0, // ok!
+    X = 0x7fffffffffffffff,
+}
+```
+"##,
+
 E0371: r##"
 When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a
 definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement
@@ -2869,44 +3003,44 @@ https://doc.rust-lang.org/std/marker/struct.PhantomData.html
 }
 
 register_diagnostics! {
-    E0068,
-    E0085,
-    E0086,
+//  E0068,
+//  E0085,
+//  E0086,
     E0090,
     E0103, // @GuillaumeGomez: I was unable to get this error, try your best!
     E0104,
     E0118,
     E0122,
-    E0123,
-    E0127,
-    E0129,
-    E0141,
+//  E0123,
+//  E0127,
+//  E0129,
+//  E0141,
 //  E0159, // use of trait `{}` as struct constructor
     E0163,
     E0164,
     E0167,
 //  E0168,
-    E0173, // manual implementations of unboxed closure traits are experimental
+//  E0173, // manual implementations of unboxed closure traits are experimental
     E0174, // explicit use of unboxed closure methods are experimental
     E0182,
     E0183,
-    E0187, // can't infer the kind of the closure
-    E0188, // can not cast a immutable reference to a mutable pointer
-    E0189, // deprecated: can only cast a boxed pointer to a boxed object
-    E0190, // deprecated: can only cast a &-pointer to an &-object
+//  E0187, // can't infer the kind of the closure
+//  E0188, // can not cast a immutable reference to a mutable pointer
+//  E0189, // deprecated: can only cast a boxed pointer to a boxed object
+//  E0190, // deprecated: can only cast a &-pointer to an &-object
     E0196, // cannot determine a type for this closure
     E0203, // type parameter has more than one relaxed default bound,
            // and only one is supported
     E0208,
-    E0209, // builtin traits can only be implemented on structs or enums
+//  E0209, // builtin traits can only be implemented on structs or enums
     E0212, // cannot extract an associated type from a higher-ranked trait bound
-    E0213, // associated types are not accepted in this context
+//  E0213, // associated types are not accepted in this context
     E0214, // parenthesized parameters may only be used with a trait
 //  E0215, // angle-bracket notation is not stable with `Fn`
 //  E0216, // parenthetical notation is only stable with `Fn`
-    E0217, // ambiguous associated type, defined in multiple supertraits
-    E0218, // no associated type defined
-    E0219, // associated type defined in higher-ranked supertrait
+//  E0217, // ambiguous associated type, defined in multiple supertraits
+//  E0218, // no associated type defined
+//  E0219, // associated type defined in higher-ranked supertrait
 //  E0222, // Error code E0045 (variadic function must have C calling
            // convention) duplicate
     E0224, // at least one non-builtin train is required for an object type
@@ -2916,25 +3050,24 @@ register_diagnostics! {
     E0229, // associated type bindings are not allowed here
     E0230, // there is no type parameter on trait
     E0231, // only named substitution parameters are allowed
-    E0233,
-    E0234,
+//  E0233,
+//  E0234,
 //  E0235, // structure constructor specifies a structure of type but
     E0236, // no lang item for range syntax
     E0237, // no lang item for range syntax
     E0238, // parenthesized parameters may only be used with a trait
-    E0239, // `next` method of `Iterator` trait has unexpected type
-    E0240,
-    E0241,
+//  E0239, // `next` method of `Iterator` trait has unexpected type
+//  E0240,
+//  E0241,
     E0242, // internal error looking up a definition
     E0245, // not a trait
-    E0246, // invalid recursive type
+//  E0246, // invalid recursive type
     E0247, // found module name used as a type
-    E0319, // trait impls for defaulted traits allowed just for structs/enums
+//  E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
     E0321, // extended coherence rules for defaulted traits violated
     E0328, // cannot implement Unsize explicitly
     E0329, // associated const depends on type parameter or Self.
-    E0370, // discriminant overflow
     E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with one field being coerced, none found
     E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index b5e08752344..66893ffd330 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -598,8 +598,11 @@ impl<'a> Components<'a> {
     /// how much of the prefix is left from the point of view of iteration?
     #[inline]
     fn prefix_remaining(&self) -> usize {
-        if self.front == State::Prefix { self.prefix_len() }
-        else { 0 }
+        if self.front == State::Prefix {
+            self.prefix_len()
+        } else {
+            0
+        }
     }
 
     // Given the iteration so far, how much of the pre-State::Body path is left?
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 0aeb572b6bc..e07cd7b5847 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -29,6 +29,8 @@ use std::io::{self, Read};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
+use parse::token::intern;
+use ast::Name;
 
 // _____________________________________________________________________________
 // Pos, BytePos, CharPos
@@ -257,21 +259,38 @@ pub struct FileMapAndBytePos { pub fm: Rc<FileMap>, pub pos: BytePos }
 //
 
 /// The source of expansion.
-#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
+#[derive(Clone, Hash, Debug, PartialEq, Eq)]
 pub enum ExpnFormat {
     /// e.g. #[derive(...)] <item>
-    MacroAttribute,
+    MacroAttribute(Name),
     /// e.g. `format!()`
-    MacroBang,
+    MacroBang(Name),
     /// Syntax sugar expansion performed by the compiler (libsyntax::expand).
-    CompilerExpansion,
+    CompilerExpansion(CompilerExpansionFormat),
+}
+
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
+pub enum CompilerExpansionFormat {
+    IfLet,
+    PlacementIn,
+    WhileLet,
+    ForLoop,
+    Closure,
 }
 
+impl CompilerExpansionFormat {
+    pub fn name(self) -> &'static str {
+        match self {
+            CompilerExpansionFormat::IfLet => "if let expansion",
+            CompilerExpansionFormat::PlacementIn => "placement-in expansion",
+            CompilerExpansionFormat::WhileLet => "while let expansion",
+            CompilerExpansionFormat::ForLoop => "for loop expansion",
+            CompilerExpansionFormat::Closure => "closure expansion",
+        }
+    }
+}
 #[derive(Clone, Hash, Debug)]
 pub struct NameAndSpan {
-    /// The name of the macro that was invoked to create the thing
-    /// with this Span.
-    pub name: String,
     /// The format with which the macro was invoked.
     pub format: ExpnFormat,
     /// Whether the macro is allowed to use #[unstable]/feature-gated
@@ -284,6 +303,16 @@ pub struct NameAndSpan {
     pub span: Option<Span>
 }
 
+impl NameAndSpan {
+    pub fn name(&self) -> Name {
+        match self.format {
+            ExpnFormat::MacroAttribute(s) => s,
+            ExpnFormat::MacroBang(s) => s,
+            ExpnFormat::CompilerExpansion(ce) => intern(ce.name()),
+        }
+    }
+}
+
 /// Extra information for tracking spans of macro and syntax sugar expansion
 #[derive(Hash, Debug)]
 pub struct ExpnInfo {
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 7476302b2f0..067e3fff3eb 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -733,14 +733,14 @@ impl EmitterWriter {
                     let ss = ei.callee.span.map_or(String::new(),
                                                    |span| cm.span_to_string(span));
                     let (pre, post) = match ei.callee.format {
-                        codemap::MacroAttribute => ("#[", "]"),
-                        codemap::MacroBang => ("", "!"),
-                        codemap::CompilerExpansion => ("", ""),
+                        codemap::MacroAttribute(..) => ("#[", "]"),
+                        codemap::MacroBang(..) => ("", "!"),
+                        codemap::CompilerExpansion(..) => ("", ""),
                     };
                     try!(self.print_diagnostic(&ss, Note,
                                                &format!("in expansion of {}{}{}",
                                                         pre,
-                                                        ei.callee.name,
+                                                        ei.callee.name(),
                                                         post),
                                                None));
                     let ss = cm.span_to_string(ei.call_site);
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index 69159690328..c48b740d83a 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -19,7 +19,7 @@ use codemap::Span;
 use ext::base;
 use ext::base::*;
 use feature_gate;
-use parse::token::InternedString;
+use parse::token::{intern, InternedString};
 use parse::token;
 use ptr::P;
 
@@ -211,8 +211,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     let expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
         call_site: sp,
         callee: codemap::NameAndSpan {
-            name: "asm".to_string(),
-            format: codemap::MacroBang,
+            format: codemap::MacroBang(intern("asm")),
             span: None,
             allow_internal_unstable: false,
         },
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index ef11a2bd66e..ef49ef11497 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -714,13 +714,14 @@ impl<'a> ExtCtxt<'a> {
         loop {
             if self.codemap().with_expn_info(expn_id, |info| {
                 info.map_or(None, |i| {
-                    if i.callee.name == "include" {
+                    if i.callee.name() == "include" {
                         // Stop going up the backtrace once include! is encountered
                         return None;
                     }
                     expn_id = i.call_site.expn_id;
-                    if i.callee.format != CompilerExpansion {
-                        last_macro = Some(i.call_site)
+                    match i.callee.format {
+                        CompilerExpansion(..) => (),
+                        _ => last_macro = Some(i.call_site),
                     }
                     return Some(());
                 })
@@ -744,7 +745,7 @@ impl<'a> ExtCtxt<'a> {
         if self.recursion_count > self.ecfg.recursion_limit {
             panic!(self.span_fatal(ei.call_site,
                             &format!("recursion limit reached while expanding the macro `{}`",
-                                    ei.callee.name)));
+                                    ei.callee.name())));
         }
 
         let mut call_site = ei.call_site;
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 2986e968045..3196380ec6c 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -205,7 +205,7 @@ use codemap::Span;
 use diagnostic::SpanHandler;
 use fold::MoveMap;
 use owned_slice::OwnedSlice;
-use parse::token::InternedString;
+use parse::token::{intern, InternedString};
 use parse::token::special_idents;
 use ptr::P;
 
@@ -1436,8 +1436,7 @@ impl<'a> TraitDef<'a> {
         to_set.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
             call_site: to_set,
             callee: codemap::NameAndSpan {
-                name: format!("derive({})", trait_name),
-                format: codemap::MacroAttribute,
+                format: codemap::MacroAttribute(intern(&format!("derive({})", trait_name))),
                 span: Some(self.span),
                 allow_internal_unstable: false,
             }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 4f89b3494d4..3459caecb26 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -19,7 +19,8 @@ use ext::build::AstBuilder;
 use attr;
 use attr::AttrMetaMethods;
 use codemap;
-use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, CompilerExpansion};
+use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
+use codemap::{CompilerExpansion, CompilerExpansionFormat};
 use ext::base::*;
 use feature_gate::{self, Features, GatedCfg};
 use fold;
@@ -43,12 +44,12 @@ fn mk_core_path(fld: &mut MacroExpander,
 }
 
 pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
-    fn push_compiler_expansion(fld: &mut MacroExpander, span: Span, expansion_desc: &str) {
+    fn push_compiler_expansion(fld: &mut MacroExpander, span: Span,
+                               expansion_type: CompilerExpansionFormat) {
         fld.cx.bt_push(ExpnInfo {
             call_site: span,
             callee: NameAndSpan {
-                name: expansion_desc.to_string(),
-                format: CompilerExpansion,
+                format: CompilerExpansion(expansion_type),
 
                 // This does *not* mean code generated after
                 // `push_compiler_expansion` is automatically exempt
@@ -111,7 +112,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
                 &fld.cx.parse_sess.span_diagnostic,
                 expr_span);
 
-            push_compiler_expansion(fld, expr_span, "placement-in expansion");
+            push_compiler_expansion(fld, expr_span, CompilerExpansionFormat::PlacementIn);
 
             let value_span = value_expr.span;
             let placer_span = placer.span;
@@ -223,7 +224,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             //     }
             //   }
 
-            push_compiler_expansion(fld, span, "while let expansion");
+            push_compiler_expansion(fld, span, CompilerExpansionFormat::WhileLet);
 
             // `<pat> => <body>`
             let pat_arm = {
@@ -262,7 +263,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             //     _ => [<elseopt> | ()]
             //   }
 
-            push_compiler_expansion(fld, span, "if let expansion");
+            push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet);
 
             // `<pat> => <body>`
             let pat_arm = {
@@ -334,7 +335,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
         ast::ExprIf(cond, blk, elseopt) => {
             let elseopt = elseopt.map(|els| els.and_then(|els| match els.node {
                 ast::ExprIfLet(..) => {
-                    push_compiler_expansion(fld, span, "if let expansion");
+                    push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet);
                     // wrap the if-let expr in a block
                     let span = els.span;
                     let blk = P(ast::Block {
@@ -378,7 +379,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             //     result
             //   }
 
-            push_compiler_expansion(fld, span, "for loop expansion");
+            push_compiler_expansion(fld, span, CompilerExpansionFormat::ForLoop);
 
             let span = fld.new_span(span);
 
@@ -458,7 +459,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
         }
 
         ast::ExprClosure(capture_clause, fn_decl, block) => {
-            push_compiler_expansion(fld, span, "closure expansion");
+            push_compiler_expansion(fld, span, CompilerExpansionFormat::Closure);
             let (rewritten_fn_decl, rewritten_block)
                 = expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
             let new_node = ast::ExprClosure(capture_clause,
@@ -542,8 +543,7 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac,
                         fld.cx.bt_push(ExpnInfo {
                                 call_site: span,
                                 callee: NameAndSpan {
-                                    name: extname.to_string(),
-                                    format: MacroBang,
+                                    format: MacroBang(extname),
                                     span: exp_span,
                                     allow_internal_unstable: allow_internal_unstable,
                                 },
@@ -721,8 +721,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     fld.cx.bt_push(ExpnInfo {
                         call_site: it.span,
                         callee: NameAndSpan {
-                            name: extname.to_string(),
-                            format: MacroBang,
+                            format: MacroBang(extname),
                             span: span,
                             allow_internal_unstable: allow_internal_unstable,
                         }
@@ -741,8 +740,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     fld.cx.bt_push(ExpnInfo {
                         call_site: it.span,
                         callee: NameAndSpan {
-                            name: extname.to_string(),
-                            format: MacroBang,
+                            format: MacroBang(extname),
                             span: span,
                             allow_internal_unstable: allow_internal_unstable,
                         }
@@ -762,8 +760,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     fld.cx.bt_push(ExpnInfo {
                         call_site: it.span,
                         callee: NameAndSpan {
-                            name: extname.to_string(),
-                            format: MacroBang,
+                            format: MacroBang(extname),
                             span: None,
                             // `macro_rules!` doesn't directly allow
                             // unstable (this is orthogonal to whether
@@ -1090,8 +1087,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
                     fld.cx.bt_push(ExpnInfo {
                         call_site: span,
                         callee: NameAndSpan {
-                            name: extname.to_string(),
-                            format: MacroBang,
+                            format: MacroBang(extname),
                             span: tt_span,
                             allow_internal_unstable: allow_internal_unstable,
                         }
@@ -1293,8 +1289,8 @@ fn expand_decorators(a: Annotatable,
                      new_attrs: &mut Vec<ast::Attribute>)
 {
     for attr in a.attrs() {
-        let mname = attr.name();
-        match fld.cx.syntax_env.find(&intern(&mname)) {
+        let mname = intern(&attr.name());
+        match fld.cx.syntax_env.find(&mname) {
             Some(rc) => match *rc {
                 Decorator(ref dec) => {
                     attr::mark_used(&attr);
@@ -1302,8 +1298,7 @@ fn expand_decorators(a: Annotatable,
                     fld.cx.bt_push(ExpnInfo {
                         call_site: attr.span,
                         callee: NameAndSpan {
-                            name: mname.to_string(),
-                            format: MacroAttribute,
+                            format: MacroAttribute(mname),
                             span: Some(attr.span),
                             // attributes can do whatever they like,
                             // for now.
@@ -1330,8 +1325,7 @@ fn expand_decorators(a: Annotatable,
                     fld.cx.bt_push(ExpnInfo {
                         call_site: attr.span,
                         callee: NameAndSpan {
-                            name: mname.to_string(),
-                            format: MacroAttribute,
+                            format: MacroAttribute(mname),
                             span: Some(attr.span),
                             // attributes can do whatever they like,
                             // for now.
@@ -1372,17 +1366,16 @@ fn expand_item_multi_modifier(mut it: Annotatable,
     }
 
     for attr in &modifiers {
-        let mname = attr.name();
+        let mname = intern(&attr.name());
 
-        match fld.cx.syntax_env.find(&intern(&mname)) {
+        match fld.cx.syntax_env.find(&mname) {
             Some(rc) => match *rc {
                 MultiModifier(ref mac) => {
                     attr::mark_used(attr);
                     fld.cx.bt_push(ExpnInfo {
                         call_site: attr.span,
                         callee: NameAndSpan {
-                            name: mname.to_string(),
-                            format: MacroAttribute,
+                            format: MacroAttribute(mname),
                             span: Some(attr.span),
                             // attributes can do whatever they like,
                             // for now
@@ -1421,17 +1414,16 @@ fn expand_item_modifiers(mut it: P<ast::Item>,
     }
 
     for attr in &modifiers {
-        let mname = attr.name();
+        let mname = intern(&attr.name());
 
-        match fld.cx.syntax_env.find(&intern(&mname)) {
+        match fld.cx.syntax_env.find(&mname) {
             Some(rc) => match *rc {
                 Modifier(ref mac) => {
                     attr::mark_used(attr);
                     fld.cx.bt_push(ExpnInfo {
                         call_site: attr.span,
                         callee: NameAndSpan {
-                            name: mname.to_string(),
-                            format: MacroAttribute,
+                            format: MacroAttribute(mname),
                             span: Some(attr.span),
                             // attributes can do whatever they like,
                             // for now
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index d41a8ff140c..d6974abd394 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -14,8 +14,7 @@ use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
 use codemap;
 use fold::Folder;
 use fold;
-use parse::token::InternedString;
-use parse::token::special_idents;
+use parse::token::{intern, InternedString, special_idents};
 use parse::{token, ParseSess};
 use ptr::P;
 use util::small_vector::SmallVector;
@@ -27,8 +26,7 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span {
     let info = ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            name: "std_inject".to_string(),
-            format: MacroAttribute,
+            format: MacroAttribute(intern("std_inject")),
             span: None,
             allow_internal_unstable: true,
         }
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 7fb8cdde311..7cd44e5fb4e 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -32,7 +32,7 @@ use ext::expand::ExpansionConfig;
 use fold::{Folder, MoveMap};
 use fold;
 use owned_slice::OwnedSlice;
-use parse::token::InternedString;
+use parse::token::{intern, InternedString};
 use parse::{token, ParseSess};
 use print::pprust;
 use {ast, ast_util};
@@ -298,8 +298,7 @@ fn generate_test_harness(sess: &ParseSess,
     cx.ext_cx.bt_push(ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            name: "test".to_string(),
-            format: MacroAttribute,
+            format: MacroAttribute(intern("test")),
             span: None,
             allow_internal_unstable: false,
         }
@@ -331,8 +330,7 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
     let info = ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            name: "test".to_string(),
-            format: MacroAttribute,
+            format: MacroAttribute(intern("test")),
             span: None,
             allow_internal_unstable: true,
         }
diff --git a/src/rustbook/static/rustbook.css b/src/rustbook/static/rustbook.css
index 3e0537c5551..6b9e7aa58f2 100644
--- a/src/rustbook/static/rustbook.css
+++ b/src/rustbook/static/rustbook.css
@@ -27,7 +27,7 @@ h1, h2, h3, h4, h5, h6 {
 
 @media only screen {
     #toc {
-        position: absolute;
+        position: fixed;
         left: 0px;
         top: 0px;
         bottom: 0px;
@@ -44,11 +44,9 @@ h1, h2, h3, h4, h5, h6 {
 
     #page-wrapper {
         position: absolute;
-        overflow-y: auto;
         left: 310px;
         right: 0px;
         top: 0px;
-        bottom: 0px;
         box-sizing: border-box;
         background: none repeat scroll 0% 0% #FFF;
         -webkit-overflow-scrolling: touch;
diff --git a/src/test/compile-fail-fulldeps/qquote.rs b/src/test/compile-fail-fulldeps/qquote.rs
index c83a154056b..7ffbbe69c3d 100644
--- a/src/test/compile-fail-fulldeps/qquote.rs
+++ b/src/test/compile-fail-fulldeps/qquote.rs
@@ -27,8 +27,7 @@ fn main() {
     cx.bt_push(syntax::codemap::ExpnInfo {
         call_site: DUMMY_SP,
         callee: syntax::codemap::NameAndSpan {
-            name: "".to_string(),
-            format: syntax::codemap::MacroBang,
+            format: syntax::codemap::MacroBang(parse::token::intern("")),
             allow_internal_unstable: false,
             span: None,
         }
diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs
index eac38037b4b..d42a777a019 100644
--- a/src/test/run-fail-fulldeps/qquote.rs
+++ b/src/test/run-fail-fulldeps/qquote.rs
@@ -31,8 +31,7 @@ fn main() {
     cx.bt_push(syntax::codemap::ExpnInfo {
         call_site: DUMMY_SP,
         callee: syntax::codemap::NameAndSpan {
-            name: "".to_string(),
-            format: syntax::codemap::MacroBang,
+            format: syntax::codemap::MacroBang(parse::token::intern("")),
             allow_internal_unstable: false,
             span: None,
         }
diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs
index e272a5fe4f6..ba713bb98f8 100644
--- a/src/test/run-pass-fulldeps/qquote.rs
+++ b/src/test/run-pass-fulldeps/qquote.rs
@@ -16,6 +16,7 @@ extern crate syntax;
 
 use syntax::codemap::DUMMY_SP;
 use syntax::print::pprust::*;
+use syntax::parse::token::intern;
 
 fn main() {
     let ps = syntax::parse::ParseSess::new();
@@ -27,8 +28,7 @@ fn main() {
     cx.bt_push(syntax::codemap::ExpnInfo {
         call_site: DUMMY_SP,
         callee: syntax::codemap::NameAndSpan {
-            name: "".to_string(),
-            format: syntax::codemap::MacroBang,
+            format: syntax::codemap::MacroBang(intern("")),
             allow_internal_unstable: false,
             span: None,
         }