From 0dd0a5bc033a95ce980ccd13004afeac35521409 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Thu, 5 Apr 2018 13:27:41 -0400
Subject: [PATCH 01/24] initialize the rustc book

---
 src/doc/rustc/.gitignore       | 1 +
 src/doc/rustc/book.toml        | 5 +++++
 src/doc/rustc/src/SUMMARY.md   | 3 +++
 src/doc/rustc/src/chapter_1.md | 1 +
 4 files changed, 10 insertions(+)
 create mode 100644 src/doc/rustc/.gitignore
 create mode 100644 src/doc/rustc/book.toml
 create mode 100644 src/doc/rustc/src/SUMMARY.md
 create mode 100644 src/doc/rustc/src/chapter_1.md

diff --git a/src/doc/rustc/.gitignore b/src/doc/rustc/.gitignore
new file mode 100644
index 0000000000000..7585238efedfc
--- /dev/null
+++ b/src/doc/rustc/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
new file mode 100644
index 0000000000000..821ad8fb09cde
--- /dev/null
+++ b/src/doc/rustc/book.toml
@@ -0,0 +1,5 @@
+[book]
+authors = ["steveklabnik"]
+multilingual = false
+src = "src"
+title = "The rustc book"
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
new file mode 100644
index 0000000000000..7390c82896e56
--- /dev/null
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -0,0 +1,3 @@
+# Summary
+
+- [Chapter 1](./chapter_1.md)
diff --git a/src/doc/rustc/src/chapter_1.md b/src/doc/rustc/src/chapter_1.md
new file mode 100644
index 0000000000000..b743fda354692
--- /dev/null
+++ b/src/doc/rustc/src/chapter_1.md
@@ -0,0 +1 @@
+# Chapter 1

From b99418d4b031d8586b6767283a8628ba5cbca1b1 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Thu, 5 Apr 2018 14:41:48 -0400
Subject: [PATCH 02/24] Add rustc book to the build system

---
 src/bootstrap/builder.rs | 4 ++--
 src/bootstrap/doc.rs     | 1 +
 src/bootstrap/test.rs    | 1 +
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 3f5ec4933d02b..16e29427c607e 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -323,7 +323,7 @@ impl<'a> Builder<'a> {
                 test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
                 test::RunMakeFullDeps,
                 test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
-                test::TheBook, test::UnstableBook,
+                test::TheBook, test::UnstableBook, test::RustcBook,
                 test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
                 // Run run-make last, since these won't pass without make on Windows
                 test::RunMake),
@@ -331,7 +331,7 @@ impl<'a> Builder<'a> {
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc,
                 doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample,
-                doc::CargoBook),
+                doc::RustcBook, doc::CargoBook),
             Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc,
                 dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src,
                 dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended,
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 4237ded2215c2..0618d1d89aa42 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -71,6 +71,7 @@ book!(
     Nomicon, "src/doc/nomicon", "nomicon";
     Reference, "src/doc/reference", "reference";
     Rustdoc, "src/doc/rustdoc", "rustdoc";
+    RustcBook, "src/doc/rustc", "rustc";
     RustByExample, "src/doc/rust-by-example", "rust-by-example";
 );
 
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index c175d2c69016f..569bd84172628 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1121,6 +1121,7 @@ test_book!(
     Nomicon, "src/doc/nomicon", "nomicon", default=false;
     Reference, "src/doc/reference", "reference", default=false;
     RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
+    RustcBook, "src/doc/rustc", "rustc", default=true;
     RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
     TheBook, "src/doc/book", "book", default=false;
     UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;

From 7de5b6034d035f8dc85cb073b2dde3b611a3d822 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Thu, 5 Apr 2018 14:53:58 -0400
Subject: [PATCH 03/24] update doc index to link to the rustc book

---
 src/doc/index.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/doc/index.md b/src/doc/index.md
index 2ea889da1fde2..3a4f51069fc3b 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -43,6 +43,10 @@ Rust's standard library has [extensive API documentation](std/index.html),
 with explanations of how to use various things, as well as example code for
 accomplishing various tasks.
 
+## The Rustc Book
+
+[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
+
 ## The Cargo Book
 
 [The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager.

From c942bf42fcb7dfb39ad68aebd0365c14818bdcfb Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 09:11:09 -0400
Subject: [PATCH 04/24] Add a TOC

---
 src/doc/rustc/src/SUMMARY.md                       | 14 ++++++++++++--
 src/doc/rustc/src/chapter_1.md                     |  1 -
 src/doc/rustc/src/codegen-options/index.md         |  1 +
 src/doc/rustc/src/command-line-arguments/index.md  |  1 +
 src/doc/rustc/src/contributing.md                  |  1 +
 src/doc/rustc/src/lints/groups.md                  |  1 +
 src/doc/rustc/src/lints/index.md                   |  1 +
 src/doc/rustc/src/lints/levels.md                  |  1 +
 .../rustc/src/lints/listing/allowed-by-default.md  |  1 +
 src/doc/rustc/src/lints/listing/deny-by-default.md |  1 +
 src/doc/rustc/src/lints/listing/index.md           |  1 +
 src/doc/rustc/src/lints/listing/warn-by-default.md |  1 +
 src/doc/rustc/src/what-is-rustc.md                 |  1 +
 13 files changed, 23 insertions(+), 3 deletions(-)
 delete mode 100644 src/doc/rustc/src/chapter_1.md
 create mode 100644 src/doc/rustc/src/codegen-options/index.md
 create mode 100644 src/doc/rustc/src/command-line-arguments/index.md
 create mode 100644 src/doc/rustc/src/contributing.md
 create mode 100644 src/doc/rustc/src/lints/groups.md
 create mode 100644 src/doc/rustc/src/lints/index.md
 create mode 100644 src/doc/rustc/src/lints/levels.md
 create mode 100644 src/doc/rustc/src/lints/listing/allowed-by-default.md
 create mode 100644 src/doc/rustc/src/lints/listing/deny-by-default.md
 create mode 100644 src/doc/rustc/src/lints/listing/index.md
 create mode 100644 src/doc/rustc/src/lints/listing/warn-by-default.md
 create mode 100644 src/doc/rustc/src/what-is-rustc.md

diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 7390c82896e56..197ff6ac410bb 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -1,3 +1,13 @@
-# Summary
+# The Rustc Book
 
-- [Chapter 1](./chapter_1.md)
+- [What is rustc?](what-is-rustc.md)
+- [Command-line arguments](command-line-arguments/index.md)
+- [Lints](lints/index.md)
+    - [Lint levels](lints/levels.md)
+    - [Lint Groups](lints/groups.md)
+    - [Lint listing](lints/listing/index.md)
+        - [Allowed-by-default lints](lints/listing/allowed-by-default.md)
+        - [Warn-by-default lints](lints/listing/warn-by-default.md)
+        - [Deny-by-default lints](lints/listing/deny-by-default.md)
+- [Codegen options](codegen-options/index.md)
+- [Contributing to `rustc`](contributing.md)
\ No newline at end of file
diff --git a/src/doc/rustc/src/chapter_1.md b/src/doc/rustc/src/chapter_1.md
deleted file mode 100644
index b743fda354692..0000000000000
--- a/src/doc/rustc/src/chapter_1.md
+++ /dev/null
@@ -1 +0,0 @@
-# Chapter 1
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
new file mode 100644
index 0000000000000..4350db56ef683
--- /dev/null
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -0,0 +1 @@
+# Codegen options
diff --git a/src/doc/rustc/src/command-line-arguments/index.md b/src/doc/rustc/src/command-line-arguments/index.md
new file mode 100644
index 0000000000000..162c0e48d4e93
--- /dev/null
+++ b/src/doc/rustc/src/command-line-arguments/index.md
@@ -0,0 +1 @@
+# Command-line arguments
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
new file mode 100644
index 0000000000000..e21b6fbd14aed
--- /dev/null
+++ b/src/doc/rustc/src/contributing.md
@@ -0,0 +1 @@
+# Contributing to rustc
diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md
new file mode 100644
index 0000000000000..f35b53b6b996e
--- /dev/null
+++ b/src/doc/rustc/src/lints/groups.md
@@ -0,0 +1 @@
+# Lint Groups
diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md
new file mode 100644
index 0000000000000..112c576a22c76
--- /dev/null
+++ b/src/doc/rustc/src/lints/index.md
@@ -0,0 +1 @@
+# Lints
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
new file mode 100644
index 0000000000000..6aed1e979f34d
--- /dev/null
+++ b/src/doc/rustc/src/lints/levels.md
@@ -0,0 +1 @@
+# Lint levels
diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md
new file mode 100644
index 0000000000000..19c4d94edbb52
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md
@@ -0,0 +1 @@
+# Allowed-by-default lints
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
new file mode 100644
index 0000000000000..0f6fd4fe9312c
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -0,0 +1 @@
+# Deny-by-default lints
diff --git a/src/doc/rustc/src/lints/listing/index.md b/src/doc/rustc/src/lints/listing/index.md
new file mode 100644
index 0000000000000..e279644e6449d
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/index.md
@@ -0,0 +1 @@
+# Lint listing
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
new file mode 100644
index 0000000000000..5342b954a09e0
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -0,0 +1 @@
+# Warn-by-default lints
diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md
new file mode 100644
index 0000000000000..ac4c33e4b7119
--- /dev/null
+++ b/src/doc/rustc/src/what-is-rustc.md
@@ -0,0 +1 @@
+# What is rustc?

From 4f6ed513d11baa71d39a1a048a6ccb67846775a1 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 09:12:02 -0400
Subject: [PATCH 05/24] fix authorship in book.toml

---
 src/doc/rustc/book.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
index 821ad8fb09cde..8adc05c513720 100644
--- a/src/doc/rustc/book.toml
+++ b/src/doc/rustc/book.toml
@@ -1,5 +1,5 @@
 [book]
-authors = ["steveklabnik"]
+authors = ["The Rust Project Developers"]
 multilingual = false
 src = "src"
 title = "The rustc book"

From 5424dc46b719a86d94578ab260798c21bc42ea7e Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 09:32:57 -0400
Subject: [PATCH 06/24] write headings for command line arguments

---
 src/doc/rustc/src/SUMMARY.md                  |  2 +-
 src/doc/rustc/src/command-line-arguments.md   | 57 +++++++++++++++++++
 .../rustc/src/command-line-arguments/index.md |  1 -
 3 files changed, 58 insertions(+), 2 deletions(-)
 create mode 100644 src/doc/rustc/src/command-line-arguments.md
 delete mode 100644 src/doc/rustc/src/command-line-arguments/index.md

diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 197ff6ac410bb..ba70c74532732 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -1,7 +1,7 @@
 # The Rustc Book
 
 - [What is rustc?](what-is-rustc.md)
-- [Command-line arguments](command-line-arguments/index.md)
+- [Command-line arguments](command-line-arguments.md)
 - [Lints](lints/index.md)
     - [Lint levels](lints/levels.md)
     - [Lint Groups](lints/groups.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
new file mode 100644
index 0000000000000..7ea3e806e4a58
--- /dev/null
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -0,0 +1,57 @@
+# Command-line arguments
+
+Here's a list of command-line arguments to `rustc` and what they do.
+
+## `-h`/`--help`: get help
+
+## `--cfg`: configure the compilation environment
+
+## `-L`: add a directory to the library search path.
+
+## `-l`: link the generated crate to a native library
+
+## `--crate-type`: a list of types of crates for the compiler to emit
+
+## `--crate-name`: specify the name of the crate being built
+
+## `--emit`: emit output other than a crate
+
+## `--print`: print compiler information
+
+## `-g`: include debug information
+
+## `-O`: optimize your code
+
+## `-o`: filename of the output
+
+## `--out-dir`: directory to write the output in
+
+## `--explain`: provide a detailed explanation of an error message
+
+## `--test`: build a test harness
+
+## `--target`: select a target triple to build
+
+## `-W`: set lint warnings
+
+## `-A`: set lint allowed
+
+## `-D`: set lint denied
+
+## `-F`: set lint forbidden
+
+## `--cap-lints`: set the most restrictive lint level
+
+## `-C`/`--codegen`: code generation options
+
+## `-V`/`--verision`: print a version
+
+## `-v`/`--verbose`: use verbose output
+
+## `--extern`: specify where an external library is located
+
+## `--sysroot`: Override the system root
+
+## `--error-format`: control how errors are produced
+
+## `--color`: configur coloring of output
\ No newline at end of file
diff --git a/src/doc/rustc/src/command-line-arguments/index.md b/src/doc/rustc/src/command-line-arguments/index.md
deleted file mode 100644
index 162c0e48d4e93..0000000000000
--- a/src/doc/rustc/src/command-line-arguments/index.md
+++ /dev/null
@@ -1 +0,0 @@
-# Command-line arguments

From cd553642488f0f0ca070647a080e93fe85719930 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 09:33:10 -0400
Subject: [PATCH 07/24] write 'what is rustc'

---
 src/doc/rustc/src/what-is-rustc.md | 67 ++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md
index ac4c33e4b7119..bed1b71c24e00 100644
--- a/src/doc/rustc/src/what-is-rustc.md
+++ b/src/doc/rustc/src/what-is-rustc.md
@@ -1 +1,68 @@
 # What is rustc?
+
+Welcome to "The rustc book"! `rustc` is the compiler for the Rust programming
+language, provided by the project itself. Compilers take your source code and
+produce binary code, either as a library or executable.
+
+Most Rust programmers don't invoke `rustc` directly, but instead do it through
+[Cargo](../cargo/index.html). It's all in service of `rustc` though! If you
+want to see how Cargo calls `rustc`, you can
+
+```bash
+$ cargo build --verbose
+```
+
+And it will print out each `rustc` invocation. This book can help you
+understand what each of these options does. Additionally, while most
+Rustaceans use Cargo, not all do: sometimes they integrate `rustc` into other
+build systems. This book should provide a guide to all of the options you'd
+need to do so.
+
+## Basic usage
+
+Let's say you've got a little hello world program in a file `hello.rs`:
+
+```rust
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+To turn this source code into an executable, you can use `rustc`:
+
+```bash
+$ rustc hello.rs
+$ ./hello # on a *NIX
+$ .\hello.exe # on Windows
+```
+
+Note that we only ever pass `rustc` the *crate root*, not every file we wish
+to compile. For example, if we had a `main.rs` that looked like this:
+
+```rust,ignore
+mod foo;
+
+fn main() {
+    foo::hello();
+}
+```
+
+And a `foo.rs` that had this:
+
+```rust,ignore
+fn hello() {
+    println!("Hello, world!");
+}
+```
+
+To compile this, we'd run this command:
+
+```bash
+$ rustc main.rs
+```
+
+No need to tell `rustc` about `foo.rs`; the `mod` statements give it
+everything that it needs. This is different than how you would use a C
+compiler, where you invoke the compiler on each file, and then link
+everything together. In other words, the *crate* is a translation unit, not a
+particular module.
\ No newline at end of file

From 78b076dadb0d8ac51be84ab3748e71a70abffa90 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 09:33:26 -0400
Subject: [PATCH 08/24] add targets to TOC

---
 src/doc/rustc/src/SUMMARY.md          | 3 +++
 src/doc/rustc/src/targets/built-in.md | 1 +
 src/doc/rustc/src/targets/custom.md   | 1 +
 src/doc/rustc/src/targets/index.md    | 1 +
 4 files changed, 6 insertions(+)
 create mode 100644 src/doc/rustc/src/targets/built-in.md
 create mode 100644 src/doc/rustc/src/targets/custom.md
 create mode 100644 src/doc/rustc/src/targets/index.md

diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index ba70c74532732..e4c0939fd4636 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -10,4 +10,7 @@
         - [Warn-by-default lints](lints/listing/warn-by-default.md)
         - [Deny-by-default lints](lints/listing/deny-by-default.md)
 - [Codegen options](codegen-options/index.md)
+- [Targets](targets/index.md)
+    - [Built-in Targets](targets/built-in.md)
+    - [Custom Targets](targets/custom.md)
 - [Contributing to `rustc`](contributing.md)
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
new file mode 100644
index 0000000000000..819d74457fe51
--- /dev/null
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -0,0 +1 @@
+# Built-in Targets
diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md
new file mode 100644
index 0000000000000..59039ce67bad9
--- /dev/null
+++ b/src/doc/rustc/src/targets/custom.md
@@ -0,0 +1 @@
+# Custom Targets
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
new file mode 100644
index 0000000000000..01d0a4c8c0e3b
--- /dev/null
+++ b/src/doc/rustc/src/targets/index.md
@@ -0,0 +1 @@
+# Targets

From 50b3a3d1216fd68b483c88b603ec6c742e51c054 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 12:32:16 -0400
Subject: [PATCH 09/24] add a lot of text about lints

---
 src/doc/rustc/src/lints/groups.md             |  28 ++
 src/doc/rustc/src/lints/index.md              |  27 ++
 src/doc/rustc/src/lints/levels.md             | 251 ++++++++++
 .../src/lints/listing/allowed-by-default.md   | 451 ++++++++++++++++++
 .../src/lints/listing/deny-by-default.md      |  15 +
 src/doc/rustc/src/lints/listing/index.md      |   4 +
 .../src/lints/listing/warn-by-default.md      |  48 ++
 7 files changed, 824 insertions(+)

diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md
index f35b53b6b996e..46b717f3387d2 100644
--- a/src/doc/rustc/src/lints/groups.md
+++ b/src/doc/rustc/src/lints/groups.md
@@ -1 +1,29 @@
 # Lint Groups
+
+`rustc` has the concept of a "lint group", where you can toggle several warnings
+through one name.
+
+For example, the `nonstandard-style` lint sets `non-camel-case-types`,
+`non-snake-case`, and `non-upper-case-globals` all at once. So these are
+equivalent:
+
+```bash
+$ rustc -D nonstandard-style
+$ rustc -D non-camel-case-types -D non-snake-case -D non-upper-case-globals
+```
+
+Here's a list of each lint group, and the lints that they are made up of:
+
+| group               | description                                                   | lints                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
+|---------------------|---------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| nonstandard-style   | Violation of standard naming conventions                      | non-camel-case-types, non-snake-case, non-upper-case-globals                                                                                                                                                                                                                                                                                                                                                                                                                           |
+| warnings            | all lints that would be issuing warnings                      | all lints that would be issuing warnings                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+| edition-2018        | Lints that will be turned into errors in Rust 2018            | tyvar-behind-raw-pointer                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+| rust-2018-idioms    | Lints to nudge you toward idiomatic features of Rust 2018     | bare-trait-object, unreachable-pub                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+| unused              | These lints detect things being declared but not used         | unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comment, unused-extern-crates, unused-features, unused-parens                                                                                                                                                                                    |
+| future-incompatible | Lints that detect code that has future-compatibility problems | private-in-public, pub-use-of-private-extern-crate, patterns-in-fns-without-body, safe-extern-statics, invalid-type-param-default, legacy-directory-ownership, legacy-imports, legacy-constructor-visibility, missing-fragment-specifier, illegal-floating-point-literal-pattern, anonymous-parameters, parenthesized-params-in-types-and-modules, late-bound-lifetime-arguments, safe-packed-borrows, incoherent-fundamental-impls, tyvar-behind-raw-pointer, unstable-name-collision |
+
+Additionally, there's a `bad-style` lint group that's a deprecated alias for `nonstandard-style`.
+
+Finally, you can also see the table above by invoking `rustc -W help`. This will give you the exact values for the specific
+compiler you have installed.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md
index 112c576a22c76..4706a10c908ee 100644
--- a/src/doc/rustc/src/lints/index.md
+++ b/src/doc/rustc/src/lints/index.md
@@ -1 +1,28 @@
 # Lints
+
+In software, a "lint" is a tool used to help improve your source code. The
+Rust compiler contains a number of lints, and when it compiles your code, it will
+also run the lints. These lints may produce a warning, an error, or nothing at all,
+depending on how you've configured things.
+
+Here's a small example:
+
+```rust
+$ cat main.rs
+fn main() {
+    let x = 5;
+}
+> rustc main.rs
+warning: unused variable: `x`
+ --> main.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^
+  |
+  = note: #[warn(unused_variables)] on by default
+  = note: to avoid this warning, consider using `_x` instead
+```
+
+This is the `unused_variables` lint, and it tells you that you've introduced
+a variable that you don't use in your code. That's not *wrong*, so it's not
+an error, but it might be a bug, so you get a warning.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
index 6aed1e979f34d..f2d7241e648a4 100644
--- a/src/doc/rustc/src/lints/levels.md
+++ b/src/doc/rustc/src/lints/levels.md
@@ -1 +1,252 @@
 # Lint levels
+
+In `rustc`, lints are divided into four *levels*:
+
+1. allow
+2. warn
+3. deny
+4. forbid
+
+Each lint has a default level (explained in the lint listing later in this
+chapter), and the compiler has a default warning level. First, let's explain
+what these levels mean, and then we'll talk about configuration.
+
+## allow
+
+These lints exist, but by default, do nothing. For example, consider this
+source:
+
+```rust
+pub fn foo() {}
+```
+
+Compiling this file produces no warnings:
+
+```rust
+$ rustc lib.rs --crate-type=lib
+$
+```
+
+But this code violates the `missing_docs` lint.
+
+These lints exist mostly to be manually turned on via configuration, as we'll
+talk about later in this section.
+
+## warn
+
+The 'warn' lint level will produce a warning if you violate the lint. For example,
+this code runs afoul of the `unused_variable` lint:
+
+```rust
+pub fn foo() {
+    let x = 5;
+}
+```
+
+This will produce this warning:
+
+```bash
+> rustc lib.rs --crate-type=lib
+warning: unused variable: `x`
+ --> lib.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^
+  |
+  = note: #[warn(unused_variables)] on by default
+  = note: to avoid this warning, consider using `_x` instead
+```
+
+## deny
+
+A 'deny' lint produces an error if you violate it. For example, this code
+runs into the `exceeding_bitshifts` lint.
+
+```rust
+fn main() {
+    100u8 << 10;
+}
+```
+
+```bash
+> rustc main.rs
+error: bitshift exceeds the type's number of bits
+ --> main.rs:2:13
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^
+  |
+  = note: #[deny(exceeding_bitshifts)] on by default
+```
+
+What's the difference between an error from a lint and a regular old error?
+Lints are configurable via levels, so in a similar way to 'allow' lints,
+warnings that are 'deny' by default let you allow them. Similarly, you may
+wish to set up a lint that is `warn` by default to produce an error instead.
+This lint level gives you that.
+
+## forbid
+
+'forbid' is a special lint level that's stronger than 'deny'. It's the same
+as 'deny' in that a lint at this level will produce an error, but unlike the
+'deny' level, the 'forbid' level can not be overridden to be anything lower
+than an error.
+
+## Configuring warning levels
+
+Remember our `missing_docs` example from the 'allow' lint level?
+
+```bash
+$ cat lib.rs
+pub fn foo() {}
+$ rustc lib.rs --crate-type=lib
+$
+```
+
+We can configure this lint to operate at a higher level, both with
+compiler flags, as well as with an attribute in the source code.
+
+You can also "cap" lints so that the compiler can choose to ignore
+certain lint levels. We'll talk about that last.
+
+### Via compiler flag
+
+The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints
+into allowed, warning, deny, or forbid levels, like this:
+
+```bash
+$ rustc lib.rs --crate-type=lib -W missing-docs
+warning: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+  |
+  = note: requested on the command line with `-W missing-docs`
+
+warning: missing documentation for a function
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+> rustc lib.rs --crate-type=lib -D missing-docs
+error: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+  |
+  = note: requested on the command line with `-D missing-docs`
+
+error: missing documentation for a function
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+```
+
+You can also pass each flag more than once for changing multiple lints:
+
+```bash
+rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables
+```
+
+And of course, you can mix these four flags together:
+
+```bash
+rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
+```
+
+### Via an attribute
+
+You can also modify the lint level with a crate-wide attribute:
+
+```bash
+> cat lib.rs
+#![warn(missing_docs)]
+
+pub fn foo() {}
+$ rustc lib.rs --crate-type=lib
+warning: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | / #![warn(missing_docs)]
+2 | |
+3 | | pub fn foo() {}
+  | |_______________^
+  |
+note: lint level defined here
+ --> lib.rs:1:9
+  |
+1 | #![warn(missing_docs)]
+  |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+ --> lib.rs:3:1
+  |
+3 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+```
+
+All four, `warn`, `allow`, `deny`, and `forbid` all work this way.
+
+You can also pass in multiple lints per attribute:
+
+```rust
+#![warn(missing_docs, unused_variables)]
+
+pub fn foo() {}
+```
+
+And use multiple attributes together:
+
+```rust
+#![warn(missing_docs)]
+#![deny(unused_variables)]
+
+pub fn foo() {}
+```
+
+### Capping lints
+
+`rustc` supports a flag, `--cap-lints LEVEL` that sets the "lint cap level."
+This is the maximum level for all lints. So for example, if we take our
+code sample from the "deny" lint level above:
+
+```rust
+fn main() {
+    100u8 << 10;
+}
+```
+
+And we compile it, capping lints to warn:
+
+```bash
+$ rustc lib.rs --cap-lints warn
+warning: bitshift exceeds the type's number of bits
+ --> lib.rs:2:5
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^
+  |
+  = note: #[warn(exceeding_bitshifts)] on by default
+
+warning: this expression will panic at run-time
+ --> lib.rs:2:5
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^ attempt to shift left with overflow
+```
+
+It now only warns, rather than errors. We can go further and allow all lints:
+
+```bash
+$ rustc lib.rs --cap-lints allow
+$
+```
+
+This feature is used heavily by Cargo; it will pass `--cap-lints allow` when
+compiling your dependencies, so that if they have any warnings, they do not
+pollute the output of your build.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md
index 19c4d94edbb52..61c7c5e88969e 100644
--- a/src/doc/rustc/src/lints/listing/allowed-by-default.md
+++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md
@@ -1 +1,452 @@
 # Allowed-by-default lints
+
+These lints are all set to the 'allow' level by default. As such, they won't show up
+unless you set them to a higher lint level with a flag or attribute.
+
+## anonymous-parameters
+
+This lint detects anonymous parameters. Some example code that triggers this lint:
+
+```rust
+trait Foo {
+    fn foo(usize);
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: use of deprecated anonymous parameter
+ --> src/lib.rs:5:11
+  |
+5 |     fn foo(usize);
+  |           ^
+  |
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+```
+
+This syntax is mostly a historical accident, and can be worked around quite
+easily:
+
+```rust
+trait Foo {
+    fn foo(_: usize);
+}
+```
+
+## bare-trait-object
+
+This lint suggests using `dyn Trait` for trait objects. Some example code
+that triggers this lint:
+
+```rust
+#![feature(dyn_trait)]
+
+trait Trait { }
+
+fn takes_trait_object(_: Box<Trait>) {
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trait objects without an explicit `dyn` are deprecated
+ --> src/lib.rs:7:30
+  |
+7 | fn takes_trait_object(_: Box<Trait>) {
+  |                              ^^^^^ help: use `dyn`: `dyn Trait`
+  |
+```
+
+To fix it, do as the help message suggests:
+
+```rust
+#![feature(dyn_trait)]
+#![deny(bare_trait_object)]
+
+trait Trait { }
+
+fn takes_trait_object(_: Box<dyn Trait>) {
+}
+```
+
+## box-pointers
+
+This lints use of the Box type. Some example code that triggers this lint:
+
+```rust
+struct Foo {
+    x: Box<isize>,
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type uses owned (Box type) pointers: std::boxed::Box<isize>
+ --> src/lib.rs:6:5
+  |
+6 |     x: Box<isize> //~ ERROR type uses owned
+  |     ^^^^^^^^^^^^^
+  |
+```
+
+This lint is mostly historical, and not particularly useful. `Box<T>` used to
+be built into the language, and the only way to do heap allocation. Today's
+Rust can call into other allocators, etc.
+
+## elided-lifetime-in-path
+
+This lint detects the use of hidden lifetime parameters. Some example code
+that triggers this lint:
+
+```rust
+struct Foo<'a> {
+    x: &'a u32
+}
+
+fn foo(x: &Foo) {
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: hidden lifetime parameters are deprecated, try `Foo<'_>`
+ --> src/lib.rs:5:12
+  |
+5 | fn foo(x: &Foo) {
+  |            ^^^
+  |
+```
+
+Lifetime elision elides this lifetime, but that is being deprecated.
+
+## missing-copy-implementations
+
+This lint detects potentially-forgotten implementations of `Copy`. Some
+example code that triggers this lint:
+
+```rust
+pub struct Foo {
+    pub field: i32
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type could implement `Copy`; consider adding `impl Copy`
+ --> src/main.rs:3:1
+  |
+3 | / pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy`
+4 | |     pub field: i32
+5 | | }
+  | |_^
+  |
+```
+
+You can fix the lint by deriving `Copy`.
+
+This lint is set to 'allow' because this code isn't bad; it's common to write
+newtypes like this specifically so that a `Copy` type is no longer `Copy`.
+
+## missing-debug-implementations
+
+This lint detects missing implementations of `fmt::Debug`. Some example code
+that triggers this lint:
+
+```rust
+pub struct Foo;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
+ --> src/main.rs:3:1
+  |
+3 | pub struct Foo;
+  | ^^^^^^^^^^^^^^^
+  |
+```
+
+You can fix the lint by deriving `Debug`.
+
+## missing-docs
+
+This lint detects missing documentation for public items. Some example code
+that triggers this lint:
+
+```rust
+pub fn foo() {}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: missing documentation for crate
+ --> src/main.rs:1:1
+  |
+1 | / #![deny(missing_docs)]
+2 | |
+3 | | pub fn foo() {}
+4 | |
+5 | | fn main() {}
+  | |____________^
+  |
+
+error: missing documentation for a function
+ --> src/main.rs:3:1
+  |
+3 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+
+```
+
+To fix the lint, add documentation to all items.
+
+## single-use-lifetime
+
+This lint detects lifetimes that are only used once. Some example code that
+triggers this lint:
+
+```rust
+struct Foo<'x> {
+    x: &'x u32
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: lifetime name `'x` only used once
+ --> src/main.rs:3:12
+  |
+3 | struct Foo<'x> {
+  |            ^^
+  |
+```
+
+## trivial-casts
+
+This lint detects trivial casts which could be removed. Some example code
+that triggers this lint:
+
+```rust
+let x: &u32 = &42;
+let _ = x as *const u32;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trivial cast: `&u32` as `*const u32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
+ --> src/main.rs:5:13
+  |
+5 |     let _ = x as *const u32;
+  |             ^^^^^^^^^^^^^^^
+  |
+note: lint level defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(trivial_casts)]
+  |         ^^^^^^^^^^^^^
+```
+
+## trivial-numeric-casts
+
+This lint detects trivial casts of numeric types which could be removed. Some
+example code that triggers this lint:
+
+```rust
+let x = 42i32 as i32;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trivial numeric cast: `i32` as `i32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
+ --> src/main.rs:4:13
+  |
+4 |     let x = 42i32 as i32;
+  |             ^^^^^^^^^^^^
+  |
+```
+
+## unreachable-pub
+
+This lint triggers for `pub` items not reachable from the crate root. Some
+example code that triggers this lint:
+
+```rust
+mod foo {
+    pub mod bar {
+        
+    }
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unreachable `pub` item
+ --> src/main.rs:4:5
+  |
+4 |     pub mod bar {
+  |     ---^^^^^^^^
+  |     |
+  |     help: consider restricting its visibility: `pub(crate)`
+  |
+```
+
+## unsafe-code
+
+This lint catches usage of `unsafe` code. Some example code that triggers this lint:
+
+```rust
+fn main() {
+    unsafe {
+
+    }
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: usage of an `unsafe` block
+ --> src/main.rs:4:5
+  |
+4 | /     unsafe {
+5 | |         
+6 | |     }
+  | |_____^
+  |
+```
+
+## unstable-features
+
+This lint is deprecated and no longer used.
+
+## unused-extern-crates
+
+This lint guards against `extern crate` items that are never used. Some
+example code that triggers this lint:
+
+```rust
+extern crate semver;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused extern crate
+ --> src/main.rs:3:1
+  |
+3 | extern crate semver;
+  | ^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-import-braces
+
+This lint catches unnecessary braces around an imported item. Some example
+code that triggers this lint:
+
+```rust
+use test::{A};
+
+mod test {
+    struct A;
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: braces around A is unnecessary
+ --> src/main.rs:3:1
+  |
+3 | use test::{A};
+  | ^^^^^^^^^^^^^^
+  |
+```
+
+To fix it, `use test::A;`
+
+## unused-qualifications
+
+This lint detects unnecessarily qualified names. Some example code that triggers this lint:
+
+```rust
+mod foo {
+    pub fn bar() {}
+}
+
+fn main() {
+    use foo::bar;
+    foo::bar();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unnecessary qualification
+ --> src/main.rs:9:5
+  |
+9 |     foo::bar();
+  |     ^^^^^^^^
+  |
+```
+
+You can call `bar()` directly, without the `foo::`.
+
+## unused-results
+
+This lint checks for the unused result of an expression in a statement. Some
+example code that triggers this lint:
+
+```rust
+fn foo<T>() -> T { panic!() }
+
+fn main() {
+    foo::<usize>();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused result
+ --> src/main.rs:6:5
+  |
+6 |     foo::<usize>();
+  |     ^^^^^^^^^^^^^^^
+  |
+```
+
+## variant-size-differences
+
+This lint detects enums with widely varying variant sizes. Some example code that triggers this lint:
+
+```rust
+enum En {
+    V0(u8),
+    VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: enum variant is more than three times larger (1024 bytes) than the next largest
+ --> src/main.rs:5:5
+  |
+5 |     VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+  |     ^^^^^^^^^^^^^^^^
+  |
+```
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
index 0f6fd4fe9312c..54e857c885dbe 100644
--- a/src/doc/rustc/src/lints/listing/deny-by-default.md
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -1 +1,16 @@
 # Deny-by-default lints
+
+These lints are all set to the 'deny' level by default.
+
+                          exceeding-bitshifts  deny     shift exceeds the type's number of bits
+                   invalid-type-param-default  deny     type parameter default erroneously allowed in invalid location
+                legacy-constructor-visibility  deny     detects use of struct constructors that would be invisible with new visibility rules
+                   legacy-directory-ownership  deny     non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files not named `mod.rs`
+                               legacy-imports  deny     detects names that resolve to ambiguous glob imports with RFC 1560
+                   missing-fragment-specifier  deny     detects missing fragment specifiers in unused `macro_rules!` patterns
+                           mutable-transmutes  deny     mutating transmuted &mut T from &T may cause undefined behavior
+                        no-mangle-const-items  deny     const items will not have their symbols exported
+    parenthesized-params-in-types-and-modules  deny     detects parenthesized generic parameters in type and module names
+              pub-use-of-private-extern-crate  deny     detect public re-exports of private extern crates
+                          safe-extern-statics  deny     safe access to extern statics was erroneously allowed
+                          unknown-crate-types  deny     unknown crate type found in #[crate_type] directive
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/listing/index.md b/src/doc/rustc/src/lints/listing/index.md
index e279644e6449d..18cd2fe32a3cc 100644
--- a/src/doc/rustc/src/lints/listing/index.md
+++ b/src/doc/rustc/src/lints/listing/index.md
@@ -1 +1,5 @@
 # Lint listing
+
+This section lists out all of the lints, grouped by their default lint levels.
+
+You can also see this list by running `rustc -W help`.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
index 5342b954a09e0..531cf7606b1ff 100644
--- a/src/doc/rustc/src/lints/listing/warn-by-default.md
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -1 +1,49 @@
 # Warn-by-default lints
+
+These lints are all set to the 'warn' level by default.
+
+                                    const-err  warn     constant evaluation detected erroneous expression
+                                    dead-code  warn     detect unused, unexported items
+                                   deprecated  warn     detects use of deprecated items
+       illegal-floating-point-literal-pattern  warn     floating-point literals cannot be used in patterns
+                              improper-ctypes  warn     proper use of libc types in foreign modules
+                 incoherent-fundamental-impls  warn     potentially-conflicting impls were erroneously allowed
+                late-bound-lifetime-arguments  warn     detects generic lifetime arguments in path segments with late bound lifetime parameters
+                         non-camel-case-types  warn     types, variants, traits and type parameters should have camel case names
+                 non-shorthand-field-patterns  warn     using `Struct { x: x }` instead of `Struct { x }` in a pattern
+                               non-snake-case  warn     variables, methods, functions, lifetime parameters and modules should have snake case names
+                       non-upper-case-globals  warn     static constants should have uppercase identifiers
+                      no-mangle-generic-items  warn     generic items must be mangled
+                         overflowing-literals  warn     literal out of range for its type
+                              path-statements  warn     path statements with no effect
+                 patterns-in-fns-without-body  warn     patterns in functions without body were erroneously allowed
+                            plugin-as-library  warn     compiler plugin used as ordinary library in non-plugin crate
+                            private-in-public  warn     detect private items in public interfaces not caught by the old implementation
+                        private-no-mangle-fns  warn     functions marked #[no_mangle] should be exported
+                    private-no-mangle-statics  warn     statics marked #[no_mangle] should be exported
+                    renamed-and-removed-lints  warn     lints that have been renamed or removed
+                          safe-packed-borrows  warn     safe borrows of fields of packed structs were was erroneously allowed
+                              stable-features  warn     stable features found in #[feature] directive
+                            type-alias-bounds  warn     bounds in type aliases are not enforced
+                     tyvar-behind-raw-pointer  warn     raw pointer to an inference variable
+                      unconditional-recursion  warn     functions that cannot return without calling themselves
+                      unions-with-drop-fields  warn     use of unions that contain fields with possibly non-trivial drop code
+                                unknown-lints  warn     unrecognized lint attribute
+                             unreachable-code  warn     detects unreachable code paths
+                         unreachable-patterns  warn     detects unreachable patterns
+                      unstable-name-collision  warn     detects name collision with an existing but unstable method
+                            unused-allocation  warn     detects unnecessary allocations that can be eliminated
+                           unused-assignments  warn     detect assignments that will never be read
+                            unused-attributes  warn     detects attributes that were not used by the compiler
+                           unused-comparisons  warn     comparisons made useless by limits of the types involved
+                           unused-doc-comment  warn     detects doc comments that aren't used by rustdoc
+                              unused-features  warn     unused or unknown features found in crate-level #[feature] directives
+                               unused-imports  warn     imports that are never used
+                                unused-macros  warn     detects macros that were not used
+                              unused-must-use  warn     unused result of a type flagged as #[must_use]
+                                   unused-mut  warn     detect mut variables which don't need to be mutable
+                                unused-parens  warn     `if`, `match`, `while` and `return` do not need parentheses
+                                unused-unsafe  warn     unnecessary use of an `unsafe` block
+                             unused-variables  warn     detect variables which are not used in any way
+                                     warnings  warn     mass-change the level for lints which produce warnings
+                                   while-true  warn     suggest using `loop { }` instead of `while true { }`
\ No newline at end of file

From df81ca37645835d41ae67d9f8e682244f40d53e7 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 13:08:33 -0400
Subject: [PATCH 10/24] document deny by default lints

---
 .../src/lints/listing/deny-by-default.md      | 249 +++++++++++++++++-
 1 file changed, 237 insertions(+), 12 deletions(-)

diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
index 54e857c885dbe..a361c117b10c9 100644
--- a/src/doc/rustc/src/lints/listing/deny-by-default.md
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -2,15 +2,240 @@
 
 These lints are all set to the 'deny' level by default.
 
-                          exceeding-bitshifts  deny     shift exceeds the type's number of bits
-                   invalid-type-param-default  deny     type parameter default erroneously allowed in invalid location
-                legacy-constructor-visibility  deny     detects use of struct constructors that would be invisible with new visibility rules
-                   legacy-directory-ownership  deny     non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files not named `mod.rs`
-                               legacy-imports  deny     detects names that resolve to ambiguous glob imports with RFC 1560
-                   missing-fragment-specifier  deny     detects missing fragment specifiers in unused `macro_rules!` patterns
-                           mutable-transmutes  deny     mutating transmuted &mut T from &T may cause undefined behavior
-                        no-mangle-const-items  deny     const items will not have their symbols exported
-    parenthesized-params-in-types-and-modules  deny     detects parenthesized generic parameters in type and module names
-              pub-use-of-private-extern-crate  deny     detect public re-exports of private extern crates
-                          safe-extern-statics  deny     safe access to extern statics was erroneously allowed
-                          unknown-crate-types  deny     unknown crate type found in #[crate_type] directive
\ No newline at end of file
+## exceeding-bitshifts
+
+This lint detects that a shift exceeds the type's number of bits. Some
+example code that triggers this lint:
+
+```rust
+1_i32 << 32;
+```
+
+This will produce:
+
+```text
+error: bitshift exceeds the type's number of bits
+ --> src/main.rs:2:5
+  |
+2 |     1_i32 << 32;
+  |     ^^^^^^^^^^^
+  |
+```
+
+## invalid-type-param-default
+
+This lint detects type parameter default erroneously allowed in invalid location. Some
+example code that triggers this lint:
+
+```rust
+fn foo<T=i32>(t: T) {}
+```
+
+This will produce:
+
+```text
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+ --> src/main.rs:4:8
+  |
+4 | fn foo<T=i32>(t: T) {}
+  |        ^
+  |
+  = note: #[deny(invalid_type_param_default)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+```
+
+## legacy-constructor-visibility
+
+[RFC 1506](https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md) modified some
+visibility rules, and changed the visibility of struct constructors. Some
+example code that triggers this lint:
+
+```rust
+mod m {
+    pub struct S(u8);
+    
+    fn f() {
+        // this is trying to use S from the 'use' line, but becuase the `u8` is
+        // not pub, it is private
+        ::S;
+    }
+}
+
+use m::S;
+```
+
+This will produce:
+
+```text
+error: private struct constructors are not usable through re-exports in outer modules
+ --> src/main.rs:5:9
+  |
+5 |         ::S;
+  |         ^^^
+  |
+  = note: #[deny(legacy_constructor_visibility)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #39207 <https://github.com/rust-lang/rust/issues/39207>
+```
+
+
+## legacy-directory-ownership
+
+The legacy_directory_ownership warning is issued when
+
+* There is a non-inline module with a #[path] attribute (e.g. #[path = "foo.rs"] mod bar;),
+* The module's file ("foo.rs" in the above example) is not named "mod.rs", and
+* The module's file contains a non-inline child module without a #[path] attribute.
+
+The warning can be fixed by renaming the parent module to "mod.rs" and moving
+it into its own directory if appropriate.
+
+## legacy-imports
+
+This lint detects names that resolve to ambiguous glob imports. Some example
+code that triggers this lint:
+
+```rust
+pub struct Foo;
+
+mod bar {
+    struct Foo;
+
+    mod baz {
+        use *;
+        use bar::*;
+        fn f(_: Foo) {}
+    }
+}
+```
+
+This will produce:
+
+```text
+error: `Foo` is ambiguous
+ --> src/main.rs:9:17
+  |
+7 |         use *;
+  |             - `Foo` could refer to the name imported here
+8 |         use bar::*;
+  |             ------ `Foo` could also refer to the name imported here
+9 |         fn f(_: Foo) {}
+  |                 ^^^
+  |
+  = note: #[deny(legacy_imports)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #38260 <https://github.com/rust-lang/rust/issues/38260>
+```
+
+
+## missing-fragment-specifier
+
+The missing_fragment_specifier warning is issued when an unused pattern in a
+`macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not
+followed by a fragment specifier (e.g. `:expr`).
+
+This warning can always be fixed by removing the unused pattern in the
+`macro_rules!` macro definition.
+
+## mutable-transmutes
+
+This lint catches transmuting from `&T` to `&mut T` becuase it is undefined
+behavior. Some example code that triggers this lint:
+
+```rust
+unsafe {
+    let y = std::mem::transmute::<&i32, &mut i32>(&5);
+}
+```
+
+This will produce:
+
+```text
+error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
+ --> src/main.rs:3:17
+  |
+3 |         let y = std::mem::transmute::<&i32, &mut i32>(&5);
+  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+
+## no-mangle-const-items
+
+This lint detects any `const` items with the `#[no_mangle]` attribute.
+Constants do not have their symbols exported, and therefore, this probably
+means you meant to use a `static`, not a `const. Some example code that
+triggers this lint:
+
+```rust
+#[no_mangle]
+const FOO: i32 = 5;
+```
+
+This will produce:
+
+```text
+error: const items should never be #[no_mangle]
+ --> src/main.rs:3:1
+  |
+3 | const FOO: i32 = 5;
+  | -----^^^^^^^^^^^^^^
+  | |
+  | help: try a static value: `pub static`
+  |
+```
+
+## parenthesized-params-in-types-and-modules
+
+This lint detects incorrect parentheses. Some example code that triggers this
+lint:
+
+```rust
+let x = 5 as usize();
+```
+
+This will produce:
+
+```text
+error: parenthesized parameters may only be used with a trait
+ --> src/main.rs:2:21
+  |
+2 |   let x = 5 as usize();
+  |                     ^^
+  |
+  = note: #[deny(parenthesized_params_in_types_and_modules)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+```
+
+To fix it, remove the `()`s.
+
+## pub-use-of-private-extern-crate
+
+This lint detects a specific situation of re-exporting a private `extern crate`;
+
+## safe-extern-statics
+
+In older versions of Rust, there was a soundness issue where `extern static`s were allowed
+to be accessed in safe code. This lint now catches and denies this kind of code.
+
+## unknown-crate-types
+
+This lint detects an unknown crate type found in a `#[crate_type]` directive. Some
+example code that triggers this lint:
+
+```rust
+#![crate_type="lol"]
+```
+
+This will produce:
+
+```text
+error: invalid `crate_type` value
+ --> src/lib.rs:1:1
+  |
+1 | #![crate_type="lol"]
+  | ^^^^^^^^^^^^^^^^^^^^
+  |
+```
\ No newline at end of file

From 758a77d46c684fc646e8ec08065d23eb53c6444d Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 15:06:53 -0400
Subject: [PATCH 11/24] more lints

---
 .../src/lints/listing/allowed-by-default.md   |    2 +-
 .../src/lints/listing/warn-by-default.md      | 1079 ++++++++++++++++-
 2 files changed, 1035 insertions(+), 46 deletions(-)

diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md
index 61c7c5e88969e..a432c00e0609a 100644
--- a/src/doc/rustc/src/lints/listing/allowed-by-default.md
+++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md
@@ -436,7 +436,7 @@ This lint detects enums with widely varying variant sizes. Some example code tha
 ```rust
 enum En {
     V0(u8),
-    VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+    VBig([u8; 1024]),
 }
 ```
 
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
index 531cf7606b1ff..a8f3400687c2a 100644
--- a/src/doc/rustc/src/lints/listing/warn-by-default.md
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -2,48 +2,1037 @@
 
 These lints are all set to the 'warn' level by default.
 
-                                    const-err  warn     constant evaluation detected erroneous expression
-                                    dead-code  warn     detect unused, unexported items
-                                   deprecated  warn     detects use of deprecated items
-       illegal-floating-point-literal-pattern  warn     floating-point literals cannot be used in patterns
-                              improper-ctypes  warn     proper use of libc types in foreign modules
-                 incoherent-fundamental-impls  warn     potentially-conflicting impls were erroneously allowed
-                late-bound-lifetime-arguments  warn     detects generic lifetime arguments in path segments with late bound lifetime parameters
-                         non-camel-case-types  warn     types, variants, traits and type parameters should have camel case names
-                 non-shorthand-field-patterns  warn     using `Struct { x: x }` instead of `Struct { x }` in a pattern
-                               non-snake-case  warn     variables, methods, functions, lifetime parameters and modules should have snake case names
-                       non-upper-case-globals  warn     static constants should have uppercase identifiers
-                      no-mangle-generic-items  warn     generic items must be mangled
-                         overflowing-literals  warn     literal out of range for its type
-                              path-statements  warn     path statements with no effect
-                 patterns-in-fns-without-body  warn     patterns in functions without body were erroneously allowed
-                            plugin-as-library  warn     compiler plugin used as ordinary library in non-plugin crate
-                            private-in-public  warn     detect private items in public interfaces not caught by the old implementation
-                        private-no-mangle-fns  warn     functions marked #[no_mangle] should be exported
-                    private-no-mangle-statics  warn     statics marked #[no_mangle] should be exported
-                    renamed-and-removed-lints  warn     lints that have been renamed or removed
-                          safe-packed-borrows  warn     safe borrows of fields of packed structs were was erroneously allowed
-                              stable-features  warn     stable features found in #[feature] directive
-                            type-alias-bounds  warn     bounds in type aliases are not enforced
-                     tyvar-behind-raw-pointer  warn     raw pointer to an inference variable
-                      unconditional-recursion  warn     functions that cannot return without calling themselves
-                      unions-with-drop-fields  warn     use of unions that contain fields with possibly non-trivial drop code
-                                unknown-lints  warn     unrecognized lint attribute
-                             unreachable-code  warn     detects unreachable code paths
-                         unreachable-patterns  warn     detects unreachable patterns
-                      unstable-name-collision  warn     detects name collision with an existing but unstable method
-                            unused-allocation  warn     detects unnecessary allocations that can be eliminated
-                           unused-assignments  warn     detect assignments that will never be read
-                            unused-attributes  warn     detects attributes that were not used by the compiler
-                           unused-comparisons  warn     comparisons made useless by limits of the types involved
-                           unused-doc-comment  warn     detects doc comments that aren't used by rustdoc
-                              unused-features  warn     unused or unknown features found in crate-level #[feature] directives
-                               unused-imports  warn     imports that are never used
-                                unused-macros  warn     detects macros that were not used
-                              unused-must-use  warn     unused result of a type flagged as #[must_use]
-                                   unused-mut  warn     detect mut variables which don't need to be mutable
-                                unused-parens  warn     `if`, `match`, `while` and `return` do not need parentheses
-                                unused-unsafe  warn     unnecessary use of an `unsafe` block
-                             unused-variables  warn     detect variables which are not used in any way
-                                     warnings  warn     mass-change the level for lints which produce warnings
-                                   while-true  warn     suggest using `loop { }` instead of `while true { }`
\ No newline at end of file
+## const-err
+
+This lint detects an erroneous expression while doing constant evaluation. Some
+example code that triggers this lint:
+
+```rust
+let b = 200u8 + 200u8;
+```
+
+This will produce:
+
+```text
+warning: attempt to add with overflow
+ --> src/main.rs:2:9
+  |
+2 | let b = 200u8 + 200u8;
+  |         ^^^^^^^^^^^^^
+  |
+```
+
+## dead-code
+
+This lint detects detect unused, unexported items. Some
+example code that triggers this lint:
+
+```rust
+fn foo() {}
+```
+
+This will produce:
+
+```text
+warning: function is never used: `foo`
+ --> src/lib.rs:2:1
+  |
+2 | fn foo() {}
+  | ^^^^^^^^
+  |
+```
+
+## deprecated
+
+This lint detects detects use of deprecated items. Some
+example code that triggers this lint:
+
+```rust
+#[deprecated]
+fn foo() {}
+
+fn bar() {
+    foo();
+}
+```
+
+This will produce:
+
+```text
+warning: use of deprecated item 'foo'
+ --> src/lib.rs:7:5
+  |
+7 |     foo();
+  |     ^^^
+  |
+```
+
+## illegal-floating-point-literal-pattern
+
+This lint detects floating-point literals used in patterns. Some example code
+that triggers this lint:
+
+```rust
+let x = 42.0;
+
+match x {
+    5.0 => {},
+    _ => {},
+}
+```
+
+This will produce:
+
+```text
+warning: floating-point literals cannot be used in patterns
+ --> src/main.rs:4:9
+  |
+4 |         5.0 => {},
+  |         ^^^
+  |
+  = note: #[warn(illegal_floating_point_literal_pattern)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+```
+
+## improper-ctypes
+
+This lint detects proper use of libc types in foreign modules. Some
+example code that triggers this lint:
+
+```rust
+extern "C" {
+    static STATIC: String;
+}
+```
+
+This will produce:
+
+```text
+warning: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
+ --> src/main.rs:2:20
+  |
+2 |     static STATIC: String;
+  |                    ^^^^^^
+  |
+```
+
+## incoherent-fundamental-impls
+
+This lint detects potentially-conflicting impls that were erroneously allowed. Some
+example code that triggers this lint:
+
+```rust
+pub trait Trait1<X> {
+    type Output;
+}
+
+pub trait Trait2<X> {}
+
+pub struct A;
+
+impl<X, T> Trait1<X> for T where T: Trait2<X> {
+    type Output = ();
+}
+
+impl<X> Trait1<Box<X>> for A {
+    type Output = i32;
+}
+```
+
+This will produce:
+
+```text
+warning: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
+  --> src/main.rs:13:1
+   |
+9  | impl<X, T> Trait1<X> for T where T: Trait2<X> {
+   | --------------------------------------------- first implementation here
+...
+13 | impl<X> Trait1<Box<X>> for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
+   |
+   = note: #[warn(incoherent_fundamental_impls)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
+   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
+```
+
+## late-bound-lifetime-arguments
+
+This lint detects detects generic lifetime arguments in path segments with
+late bound lifetime parameters. Some example code that triggers this lint:
+
+```rust
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+}
+
+fn main() {
+    S.late::<'static>(&0, &0);
+}
+```
+
+This will produce:
+
+```text
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> src/main.rs:8:14
+  |
+4 |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+  |             -- the late bound lifetime parameter is introduced here
+...
+8 |     S.late::<'static>(&0, &0);
+  |              ^^^^^^^
+  |
+  = note: #[warn(late_bound_lifetime_arguments)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+```
+
+## non-camel-case-types
+
+This lint detects types, variants, traits and type parameters that don't have
+camel case names. Some example code that triggers this lint:
+
+```rust
+struct s;
+```
+
+This will produce:
+
+```text
+warning: type `s` should have a camel case name such as `S`
+ --> src/main.rs:1:1
+  |
+1 | struct s;
+  | ^^^^^^^^^
+  |
+```
+
+## non-shorthand-field-patterns
+
+This lint detects using `Struct { x: x }` instead of `Struct { x }` in a pattern. Some
+example code that triggers this lint:
+
+```rust
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+
+fn main() {
+    let p = Point {
+        x: 5,
+        y: 5,
+    };
+
+    match p {
+        Point { x: x, y: y } => (),
+    }
+}
+```
+
+This will produce:
+
+```text
+warning: the `x:` in this pattern is redundant
+  --> src/main.rs:14:17
+   |
+14 |         Point { x: x, y: y } => (),
+   |                 --^^
+   |                 |
+   |                 help: remove this
+   |
+
+warning: the `y:` in this pattern is redundant
+  --> src/main.rs:14:23
+   |
+14 |         Point { x: x, y: y } => (),
+   |                       --^^
+   |                       |
+   |                       help: remove this
+
+```
+
+## non-snake-case
+
+This lint detects variables, methods, functions, lifetime parameters and
+modules that don't have snake case names. Some example code that triggers
+this lint:
+
+```rust
+let X = 5;
+```
+
+This will produce:
+
+```text
+warning: variable `X` should have a snake case name such as `x`
+ --> src/main.rs:2:9
+  |
+2 |     let X = 5;
+  |         ^
+  |
+```
+
+## non-upper-case-globals
+
+This lint detects static constants that don't have uppercase identifiers.
+Some example code that triggers this lint:
+
+```rust
+static x: i32 = 5;
+```
+
+This will produce:
+
+```text
+warning: static variable `x` should have an upper case name such as `X`
+ --> src/main.rs:1:1
+  |
+1 | static x: i32 = 5;
+  | ^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## no-mangle-generic-items
+
+This lint detects generic items must be mangled. Some
+example code that triggers this lint:
+
+```rust
+#[no_mangle]
+fn foo<T>(t: T) {
+
+}
+```
+
+This will produce:
+
+```text
+warning: functions generic over types must be mangled
+ --> src/main.rs:2:1
+  |
+1 |   #[no_mangle]
+  |   ------------ help: remove this attribute
+2 | / fn foo<T>(t: T) {
+3 | |     
+4 | | }
+  | |_^
+  |
+```
+
+## overflowing-literals
+
+This lint detects literal out of range for its type. Some
+example code that triggers this lint:
+
+```rust
+let x: u8 = 1000;
+```
+
+This will produce:
+
+```text
+warning: literal out of range for u8
+ --> src/main.rs:2:17
+  |
+2 |     let x: u8 = 1000;
+  |                 ^^^^
+  |
+```
+
+## path-statements
+
+This lint detects path statements with no effect. Some example code that
+triggers this lint:
+
+```rust
+let x = 42;
+
+x;
+```
+
+This will produce:
+
+```text
+warning: path statement with no effect
+ --> src/main.rs:3:5
+  |
+3 |     x;
+  |     ^^
+  |
+```
+
+## patterns-in-fns-without-body
+
+This lint detects patterns in functions without body were that were
+previously erroneously allowed. Some example code that triggers this lint:
+
+```rust
+trait Trait {
+    fn foo(mut arg: u8);
+}
+```
+
+This will produce:
+
+```text
+warning: patterns aren't allowed in methods without bodies
+ --> src/main.rs:2:12
+  |
+2 |     fn foo(mut arg: u8);
+  |            ^^^^^^^
+  |
+  = note: #[warn(patterns_in_fns_without_body)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
+```
+
+To fix this, remove the pattern; it can be used in the implementation without
+being used in the definition. That is:
+
+```rust
+trait Trait {
+    fn foo(arg: u8);
+}
+
+impl Trait for i32 {
+    fn foo(mut arg: u8) {
+
+    }
+}
+```
+
+## plugin-as-library
+
+This lint detects when compiler plugins are used as ordinary library in
+non-plugin crate. Some example code that triggers this lint:
+
+```rust
+#![feature(plugin)]
+#![plugin(macro_crate_test)]
+
+extern crate macro_crate_test;
+```
+
+## private-in-public
+
+This lint detects detect private items in public interfaces not caught by the old implementation. Some
+example code that triggers this lint:
+
+```rust
+pub trait Trait {
+    type A;
+}
+
+pub struct S;
+
+mod foo {
+    struct Z;
+
+    impl ::Trait for ::S {
+        type A = Z;
+    }
+}
+```
+
+This will produce:
+
+```text
+error[E0446]: private type `foo::Z` in public interface
+  --> src/main.rs:11:9
+   |
+11 |         type A = Z;
+   |         ^^^^^^^^^^^ can't leak private type
+```
+
+## private-no-mangle-fns
+
+This lint detects functions marked `#[no_mangle]` that are also private.
+Given that private functions aren't exposed publicly, and `#[no_mangle]`
+controls the public symbol, this combination is erroneous. Some example code
+that triggers this lint:
+
+```rust
+#[no_mangle]
+fn foo() {}
+```
+
+This will produce:
+
+```text
+warning: function is marked #[no_mangle], but not exported
+ --> src/main.rs:2:1
+  |
+2 | fn foo() {}
+  | -^^^^^^^^^^
+  | |
+  | help: try making it public: `pub`
+  |
+```
+
+To fix this, either make it public or remove the `#[no_mangle]`.
+
+## private-no-mangle-statics
+
+This lint detects any statics marked `#[no_mangle]` that are private.
+Given that private statics aren't exposed publicly, and `#[no_mangle]`
+controls the public symbol, this combination is erroneous. Some example code
+that triggers this lint:
+
+```rust
+#[no_mangle]
+static X: i32 = 4;
+```
+
+This will produce:
+
+```text
+warning: static is marked #[no_mangle], but not exported
+ --> src/main.rs:2:1
+  |
+2 | static X: i32 = 4;
+  | -^^^^^^^^^^^^^^^^^
+  | |
+  | help: try making it public: `pub`
+  |
+```
+
+To fix this, either make it public or remove the `#[no_mangle]`.
+
+## renamed-and-removed-lints
+
+This lint detects lints that have been renamed or removed. Some
+example code that triggers this lint:
+
+```rust
+#![deny(raw_pointer_derive)]
+```
+
+This will produce:
+
+```text
+warning: lint raw_pointer_derive has been removed: using derive with raw pointers is ok
+ --> src/main.rs:1:9
+  |
+1 | #![deny(raw_pointer_derive)]
+  |         ^^^^^^^^^^^^^^^^^^
+  |
+```
+
+To fix this, either remove the lint or use the new name.
+
+## safe-packed-borrows
+
+This lint detects borrowing a field in the interior of a packed structure
+with alignment other than 1. Some example code that triggers this lint:
+
+```rust
+#[repr(packed)]
+pub struct Unaligned<T>(pub T);
+
+pub struct Foo {
+    start: u8,
+    data: Unaligned<u32>,
+}
+
+fn main() {
+    let x = Foo { start: 0, data: Unaligned(1) };
+    let y = &x.data.0;
+}
+```
+
+This will produce:
+
+```text
+warning: borrow of packed field requires unsafe function or block (error E0133)
+  --> src/main.rs:11:13
+   |
+11 |     let y = &x.data.0; 
+   |             ^^^^^^^^^
+   |
+   = note: #[warn(safe_packed_borrows)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+```
+
+## stable-features
+
+This lint detects a `#[feature]` attribute that's since been made stable. Some
+example code that triggers this lint:
+
+```rust
+#![feature(test_accepted_feature)]
+```
+
+This will produce:
+
+```text
+warning: this feature has been stable since 1.0.0. Attribute no longer needed
+ --> src/main.rs:1:12
+  |
+1 | #![feature(test_accepted_feature)]
+  |            ^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+To fix, simply remove the `#![feature]` attribute, as it's no longer needed.
+
+## type-alias-bounds
+
+This lint detects bounds in type aliases. These are not currently enforced.
+Some example code that triggers this lint:
+
+```rust
+type SendVec<T: Send> = Vec<T>;
+```
+
+This will produce:
+
+```text
+warning: type alias is never used: `SendVec`
+ --> src/main.rs:1:1
+  |
+1 | type SendVec<T: Send> = Vec<T>;
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## tyvar-behind-raw-pointer
+
+This lint detects raw pointer to an inference variable. Some
+example code that triggers this lint:
+
+```rust
+let data = std::ptr::null();
+let _ = &data as *const *const ();
+
+if data.is_null() {}
+```
+
+This will produce:
+
+```text
+warning: type annotations needed
+ --> src/main.rs:4:13
+  |
+4 |     if data.is_null() {}
+  |             ^^^^^^^
+  |
+  = note: #[warn(tyvar_behind_raw_pointer)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+  = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+```
+
+## unconditional-recursion
+
+This lint detects functions that cannot return without calling themselves.
+Some example code that triggers this lint:
+
+```rust
+fn foo() {
+    foo();
+}
+```
+
+This will produce:
+
+```text
+warning: function cannot return without recurring
+ --> src/main.rs:1:1
+  |
+1 | fn foo() {
+  | ^^^^^^^^ cannot return without recurring
+2 |     foo();
+  |     ----- recursive call site
+  |
+```
+
+## unions-with-drop-fields
+
+This lint detects use of unions that contain fields with possibly non-trivial drop code. Some
+example code that triggers this lint:
+
+```rust
+#![feature(untagged_unions)]
+
+union U {
+    s: String,
+}
+```
+
+This will produce:
+
+```text
+warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
+ --> src/main.rs:4:5
+  |
+4 |     s: String,
+  |     ^^^^^^^^^
+  |
+```
+
+## unknown-lints
+
+This lint detects unrecognized lint attribute. Some
+example code that triggers this lint:
+
+```rust
+#[allow(not_a_real_lint)]
+```
+
+This will produce:
+
+```text
+warning: unknown lint: `not_a_real_lint`
+ --> src/main.rs:1:10
+  |
+1 | #![allow(not_a_real_lint)]
+  |          ^^^^^^^^^^^^^^^
+  |
+```
+
+## unreachable-code
+
+This lint detects detects unreachable code paths. Some example code that
+triggers this lint:
+
+```rust
+panic!("we never go past here!");
+
+let x = 5;
+```
+
+This will produce:
+
+```text
+warning: unreachable statement
+ --> src/main.rs:4:5
+  |
+4 |     let x = 5;
+  |     ^^^^^^^^^^
+  |
+```
+
+## unreachable-patterns
+
+This lint detects detects unreachable patterns. Some
+example code that triggers this lint:
+
+```rust
+let x = 5;
+match x {
+    y => (),
+    5 => (),
+}
+```
+
+This will produce:
+
+```text
+warning: unreachable pattern
+ --> src/main.rs:5:5
+  |
+5 |     5 => (),
+  |     ^
+  |
+```
+
+The `y` pattern will always match, so the five is impossible to reach.
+Remember, match arms match in order, you probably wanted to put the `5` case
+above the `y` case.
+
+## unstable-name-collision
+
+This lint detects that you've used a name that the standard library plans to
+add in the future, which means that your code may fail to compile without
+additional type annotations in the future. Either rename, or add those
+annotations now.
+
+## unused-allocation
+
+This lint detects detects unnecessary allocations that can be eliminated.
+
+## unused-assignments
+
+This lint detects detect assignments that will never be read. Some
+example code that triggers this lint:
+
+```rust
+let mut x = 5;
+x = 6;
+```
+
+This will produce:
+
+```text
+warning: value assigned to `x` is never read
+ --> src/main.rs:4:5
+  |
+4 |     x = 6;
+  |     ^
+  |
+```
+
+## unused-attributes
+
+This lint detects detects attributes that were not used by the compiler. Some
+example code that triggers this lint:
+
+```rust
+#![feature(custom_attribute)]
+
+#![mutable_doc]
+```
+
+This will produce:
+
+```text
+warning: unused attribute
+ --> src/main.rs:4:1
+  |
+4 | #![mutable_doc]
+  | ^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-comparisons
+
+This lint detects comparisons made useless by limits of the types involved. Some
+example code that triggers this lint:
+
+```rust
+fn foo(x: u8) {
+    x >= 0;
+}
+```
+
+This will produce:
+
+```text
+warning: comparison is useless due to type limits
+ --> src/main.rs:6:5
+  |
+6 |     x >= 0;
+  |     ^^^^^^
+  |
+```
+
+## unused-doc-comment
+
+This lint detects detects doc comments that aren't used by rustdoc. Some
+example code that triggers this lint:
+
+```rust
+/// docs for x
+let x = 12;
+```
+
+This will produce:
+
+```text
+warning: doc comment not used by rustdoc
+ --> src/main.rs:2:5
+  |
+2 |     /// docs for x
+  |     ^^^^^^^^^^^^^^
+  |
+```
+
+## unused-features
+
+This lint detects unused or unknown features found in crate-level #[feature] directives.
+To fix this, simply remove the feature flag.
+
+## unused-imports
+
+This lint detects imports that are never used. Some
+example code that triggers this lint:
+
+```rust
+use std::collections::HashMap;
+```
+
+This will produce:
+
+```text
+warning: unused import: `std::collections::HashMap`
+ --> src/main.rs:1:5
+  |
+1 | use std::collections::HashMap;
+  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-macros
+
+This lint detects detects macros that were not used. Some example code that
+triggers this lint:
+
+```rust
+macro_rules! unused {
+    () => {};
+}
+
+fn main() {
+}
+```
+
+This will produce:
+
+```text
+warning: unused macro definition
+ --> src/main.rs:1:1
+  |
+1 | / macro_rules! unused {
+2 | |     () => {};
+3 | | }
+  | |_^
+  |
+```
+
+## unused-must-use
+
+This lint detects unused result of a type flagged as #[must_use]. Some
+example code that triggers this lint:
+
+```rust
+fn returns_result() -> Result<(), ()> {
+    Ok(())
+}
+
+fn main() {
+    returns_result();
+}
+```
+
+This will produce:
+
+```text
+warning: unused `std::result::Result` which must be used
+ --> src/main.rs:6:5
+  |
+6 |     returns_result();
+  |     ^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-mut
+
+This lint detects detect mut variables which don't need to be mutable. Some
+example code that triggers this lint:
+
+```rust
+let mut x = 5;
+```
+
+This will produce:
+
+```text
+warning: variable does not need to be mutable
+ --> src/main.rs:2:9
+  |
+2 |     let mut x = 5;
+  |         ----^
+  |         |
+  |         help: remove this `mut`
+  |
+```
+
+## unused-parens
+
+This lint detects `if`, `match`, `while` and `return` with parentheses; they
+do not need them. Some example code that triggers this lint:
+
+```rust
+if(true) {}
+```
+
+This will produce:
+
+```text
+warning: unnecessary parentheses around `if` condition
+ --> src/main.rs:2:7
+  |
+2 |     if(true) {}
+  |       ^^^^^^ help: remove these parentheses
+  |
+```
+
+## unused-unsafe
+
+This lint detects unnecessary use of an `unsafe` block. Some
+example code that triggers this lint:
+
+```rust
+unsafe {}
+```
+
+This will produce:
+
+```text
+warning: unnecessary `unsafe` block
+ --> src/main.rs:2:5
+  |
+2 |     unsafe {}
+  |     ^^^^^^ unnecessary `unsafe` block
+  |
+```
+
+## unused-variables
+
+This lint detects detect variables which are not used in any way. Some
+example code that triggers this lint:
+
+```rust
+let x = 5;
+```
+
+This will produce:
+
+```text
+warning: unused variable: `x`
+ --> src/main.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^ help: consider using `_x` instead
+  |
+```
+
+## warnings
+
+This lint is a bit special; by changing its level, you change every other warning
+that would produce a warning to whatever value you'd like:
+
+```rust
+#![deny(warnings)]
+```
+
+As such, you won't ever trigger this lint in your code directly.
+
+## while-true
+
+This lint detects `while true { }`. Some example code that triggers this
+lint:
+
+```rust
+while true {
+
+}
+```
+
+This will produce:
+
+```text
+warning: denote infinite loops with `loop { ... }`
+ --> src/main.rs:2:5
+  |
+2 |     while true {
+  |     ^^^^^^^^^^ help: use `loop`
+  |
+```
\ No newline at end of file

From 142c52f4a3f7db42613239953d4615ab5a0ac3c6 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Fri, 6 Apr 2018 15:18:16 -0400
Subject: [PATCH 12/24] fix tests

---
 src/doc/rustc/src/lints/index.md               |  4 ++--
 src/doc/rustc/src/lints/levels.md              |  8 ++++----
 .../src/lints/listing/allowed-by-default.md    | 11 ++++++-----
 .../rustc/src/lints/listing/deny-by-default.md | 18 +++++++++---------
 .../rustc/src/lints/listing/warn-by-default.md | 15 ++++++++-------
 5 files changed, 29 insertions(+), 27 deletions(-)

diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md
index 4706a10c908ee..bf345a24389d2 100644
--- a/src/doc/rustc/src/lints/index.md
+++ b/src/doc/rustc/src/lints/index.md
@@ -7,7 +7,7 @@ depending on how you've configured things.
 
 Here's a small example:
 
-```rust
+```bash
 $ cat main.rs
 fn main() {
     let x = 5;
@@ -25,4 +25,4 @@ warning: unused variable: `x`
 
 This is the `unused_variables` lint, and it tells you that you've introduced
 a variable that you don't use in your code. That's not *wrong*, so it's not
-an error, but it might be a bug, so you get a warning.
\ No newline at end of file
+an error, but it might be a bug, so you get a warning.
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
index f2d7241e648a4..83b65cd648e0f 100644
--- a/src/doc/rustc/src/lints/levels.md
+++ b/src/doc/rustc/src/lints/levels.md
@@ -22,7 +22,7 @@ pub fn foo() {}
 
 Compiling this file produces no warnings:
 
-```rust
+```bash
 $ rustc lib.rs --crate-type=lib
 $
 ```
@@ -62,7 +62,7 @@ warning: unused variable: `x`
 A 'deny' lint produces an error if you violate it. For example, this code
 runs into the `exceeding_bitshifts` lint.
 
-```rust
+```rust,ignore
 fn main() {
     100u8 << 10;
 }
@@ -215,7 +215,7 @@ pub fn foo() {}
 This is the maximum level for all lints. So for example, if we take our
 code sample from the "deny" lint level above:
 
-```rust
+```rust,ignore
 fn main() {
     100u8 << 10;
 }
@@ -249,4 +249,4 @@ $
 
 This feature is used heavily by Cargo; it will pass `--cap-lints allow` when
 compiling your dependencies, so that if they have any warnings, they do not
-pollute the output of your build.
\ No newline at end of file
+pollute the output of your build.
diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md
index a432c00e0609a..e1a3f96a6fe6e 100644
--- a/src/doc/rustc/src/lints/listing/allowed-by-default.md
+++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md
@@ -336,7 +336,7 @@ This lint is deprecated and no longer used.
 This lint guards against `extern crate` items that are never used. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 extern crate semver;
 ```
 
@@ -359,9 +359,10 @@ code that triggers this lint:
 ```rust
 use test::{A};
 
-mod test {
-    struct A;
+pub mod test {
+    pub struct A;
 }
+# fn main() {}
 ```
 
 When set to 'deny', this will produce:
@@ -410,7 +411,7 @@ You can call `bar()` directly, without the `foo::`.
 This lint checks for the unused result of an expression in a statement. Some
 example code that triggers this lint:
 
-```rust
+```rust,no_run
 fn foo<T>() -> T { panic!() }
 
 fn main() {
@@ -449,4 +450,4 @@ error: enum variant is more than three times larger (1024 bytes) than the next l
 5 |     VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
   |     ^^^^^^^^^^^^^^^^
   |
-```
\ No newline at end of file
+```
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
index a361c117b10c9..0c49f2f7b36eb 100644
--- a/src/doc/rustc/src/lints/listing/deny-by-default.md
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -7,7 +7,7 @@ These lints are all set to the 'deny' level by default.
 This lint detects that a shift exceeds the type's number of bits. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 1_i32 << 32;
 ```
 
@@ -27,7 +27,7 @@ error: bitshift exceeds the type's number of bits
 This lint detects type parameter default erroneously allowed in invalid location. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 fn foo<T=i32>(t: T) {}
 ```
 
@@ -51,7 +51,7 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
 visibility rules, and changed the visibility of struct constructors. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 mod m {
     pub struct S(u8);
     
@@ -96,7 +96,7 @@ it into its own directory if appropriate.
 This lint detects names that resolve to ambiguous glob imports. Some example
 code that triggers this lint:
 
-```rust
+```rust,ignore
 pub struct Foo;
 
 mod bar {
@@ -143,7 +143,7 @@ This warning can always be fixed by removing the unused pattern in the
 This lint catches transmuting from `&T` to `&mut T` becuase it is undefined
 behavior. Some example code that triggers this lint:
 
-```rust
+```rust,ignore
 unsafe {
     let y = std::mem::transmute::<&i32, &mut i32>(&5);
 }
@@ -168,7 +168,7 @@ Constants do not have their symbols exported, and therefore, this probably
 means you meant to use a `static`, not a `const. Some example code that
 triggers this lint:
 
-```rust
+```rust,ignore
 #[no_mangle]
 const FOO: i32 = 5;
 ```
@@ -191,7 +191,7 @@ error: const items should never be #[no_mangle]
 This lint detects incorrect parentheses. Some example code that triggers this
 lint:
 
-```rust
+```rust,ignore
 let x = 5 as usize();
 ```
 
@@ -225,7 +225,7 @@ to be accessed in safe code. This lint now catches and denies this kind of code.
 This lint detects an unknown crate type found in a `#[crate_type]` directive. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 #![crate_type="lol"]
 ```
 
@@ -238,4 +238,4 @@ error: invalid `crate_type` value
 1 | #![crate_type="lol"]
   | ^^^^^^^^^^^^^^^^^^^^
   |
-```
\ No newline at end of file
+```
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
index a8f3400687c2a..1171f75caa1fd 100644
--- a/src/doc/rustc/src/lints/listing/warn-by-default.md
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -7,7 +7,7 @@ These lints are all set to the 'warn' level by default.
 This lint detects an erroneous expression while doing constant evaluation. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 let b = 200u8 + 200u8;
 ```
 
@@ -413,7 +413,7 @@ impl Trait for i32 {
 This lint detects when compiler plugins are used as ordinary library in
 non-plugin crate. Some example code that triggers this lint:
 
-```rust
+```rust,ignore
 #![feature(plugin)]
 #![plugin(macro_crate_test)]
 
@@ -425,7 +425,7 @@ extern crate macro_crate_test;
 This lint detects detect private items in public interfaces not caught by the old implementation. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 pub trait Trait {
     type A;
 }
@@ -439,6 +439,7 @@ mod foo {
         type A = Z;
     }
 }
+# fn main() {}
 ```
 
 This will produce:
@@ -682,7 +683,7 @@ warning: union contains a field with possibly non-trivial drop code, drop code o
 This lint detects unrecognized lint attribute. Some
 example code that triggers this lint:
 
-```rust
+```rust,ignore
 #[allow(not_a_real_lint)]
 ```
 
@@ -702,7 +703,7 @@ warning: unknown lint: `not_a_real_lint`
 This lint detects detects unreachable code paths. Some example code that
 triggers this lint:
 
-```rust
+```rust,no_run
 panic!("we never go past here!");
 
 let x = 5;
@@ -1020,7 +1021,7 @@ As such, you won't ever trigger this lint in your code directly.
 This lint detects `while true { }`. Some example code that triggers this
 lint:
 
-```rust
+```rust,no_run
 while true {
 
 }
@@ -1035,4 +1036,4 @@ warning: denote infinite loops with `loop { ... }`
 2 |     while true {
   |     ^^^^^^^^^^ help: use `loop`
   |
-```
\ No newline at end of file
+```

From cb6a19925a542dcf07c4318adb751d5aa4773465 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Tue, 10 Apr 2018 16:35:28 -0400
Subject: [PATCH 13/24] add codegen options section

---
 src/doc/rustc/src/codegen-options/index.md | 208 +++++++++++++++++++++
 1 file changed, 208 insertions(+)

diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 4350db56ef683..70dae9314c1f7 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -1 +1,209 @@
 # Codegen options
+
+All of these options are passed to `rustc` via the `-C` flag, short for "codegen." You can see
+a version of this list for your exact compiler by running `rustc -C help`.
+
+## ar
+
+This option is deprecated and does nothing.
+
+## linker
+
+This flag lets you control which linker `rustc` invokes to link your code.
+
+## link-arg=val
+
+This flag lets you append a single extra argument to the linker invocation.
+
+"Append" is significant; you can pass this flag multiple times to add multiple arguments.
+
+## link-args
+
+This flag lets you append multiple extra arguments to the linker invocation. The
+options should be separated by spaces.
+
+## link-dead-code
+
+Normally, the linker will remove dead code. This flag disables this behavior.
+
+An example of when this flag might be useful is when trying to construct code coverage
+metrics.
+
+## lto
+
+This flag instructs LLVM to use [link time
+optimizations](https://llvm.org/docs/LinkTimeOptimization.html).
+
+It takes one of two values, `thin` and `fat`. 'thin' LTO [is a new feature of
+LLVM](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html),
+'fat' referring to the classic version of LTO.
+
+## target-cpu
+
+This instructs `rustc` to generate code specifically for a particular processor.
+
+You can run `rustc --print target-cpus` to see the valid options to pass
+here. Additionally, `native` can be passed to use the processor of the host
+machine.
+
+## target-feature
+
+Individual targets will support different features; this flag lets you control
+enabling or disabling a feature.
+
+To see the valid options and an example of use, run `rustc --print
+target-features`.
+
+## passes
+
+This flag can be used to add extra LLVM passes to the compilation.
+
+The list must be separated by spaces.
+
+## llvm-args
+
+This flag can be used to pass a list of arguments directly to LLVM.
+
+The list must be separated by spaces.
+
+## save-temps
+
+`rustc` will generate temporary files during compilation; normally it will
+delete them after it's done with its work. This option will cause them to be
+preserved instead of removed.
+
+## rpath
+
+This option allows you to set the value of
+[`rpath`](https://en.wikipedia.org/wiki/Rpath).
+
+## overflow-checks
+
+This flag allows you to control the behavior of integer overflow. This flag
+can be passed many options:
+
+* To turn overflow checks on: `y`, `yes`, or `on`.
+* To turn overflow checks off: `n`, `no`, or `off`.
+
+## no-prepopulate-passes
+
+The pass manager comes pre-populated with a list of passes; this flag
+ensures that list is empty.
+
+## no-vectorize-loops
+
+By default, `rustc` will attempt to [vectorize
+loops](https://llvm.org/docs/Vectorizers.html#the-loop-vectorizer). This
+flag will turn that behavior off.
+
+## no-vectorize-slp
+
+By default, `rustc` will attempt to vectorize loops using [superword-level
+parallism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This
+flag will turn that behavior off.
+
+## soft-float
+
+This option will make `rustc` generate code using "soft floats." By default,
+a lot of hardware supports floating point instructions, and so the code generated
+will take advantage of this. "soft floats" emulate floating point instructions
+in software.
+
+## prefer-dynamic
+
+By default, `rustc` prefers to statically link dependencies. This option will
+make it use dynamic linking instead.
+
+## no-integrated-as
+
+LLVM comes with an internal assembler; this option will let you use an
+external assembler instead.
+
+## no-redzone
+
+This flag allows you to disable [the
+red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). This flag can
+be passed many options:
+
+* To enable the red zone: `y`, `yes`, or `on`.
+* To disable it: `n`, `no`, or `off`.
+
+## relocation-model
+
+This option lets you choose which relocation model to use.
+
+To find the valid options for this flag, run `rustc --print relocation-models`.
+
+## code-model=val
+
+This option lets you choose which code model to use.
+
+To find the valid options for this flag, run `rustc --print code-models`.
+
+## metadata
+
+This option allows you to control the metadata used for symbol mangling.
+
+## extra-filename
+
+This option allows you to put extra data in each output filename.
+
+## codegen-units
+
+This flag lets you control how many threads are used when doing
+code generation.
+
+Increasing paralellism may speed up compile times, but may also
+produce slower code.
+
+## remark
+
+This flag lets you print remarks for these optimization passes.
+
+The list of passes should be separated by spaces.
+
+`all` will remark on every pass.
+
+## no-stack-check
+
+This option is deprecated and does nothing.
+
+## debuginfo
+
+This flag lets you control debug information:
+
+* `0`: no debug info at all
+* `1`: line tables only
+* `2`: full debug info
+
+## opt-level
+
+This flag lets you control the optimization level.
+
+* `0`: no optimizations
+* `1`: basic optimizations
+* `2`: some optimizations
+* `3`: all optimizations
+* `s`: optimize for binary size
+* `z`: optimize for binary size, but also turn off loop vectorization.
+
+## debug-assertions
+
+This flag lets you turn `cfg(debug_assertions)` on or off.
+
+## inline-threshold
+
+This option lets you set the threshold for inlining a function.
+
+The default is 225.
+
+## panic
+
+This option lets you control what happens when the code panics.
+
+* `abort`: terminate the process upon panic
+* `unwind`: unwind the stack upon panic
+
+## incremental
+
+This flag allows you to enable incremental compilation.
\ No newline at end of file

From cd3f6cf3fef900c7461cc02d4bb4cd226d7c5b6e Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Mon, 16 Apr 2018 12:57:01 -0400
Subject: [PATCH 14/24] fill out command line arguments

---
 src/doc/rustc/src/command-line-arguments.md | 63 ++++++++++++++++++++-
 1 file changed, 61 insertions(+), 2 deletions(-)

diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 7ea3e806e4a58..488102f926a95 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -4,54 +4,113 @@ Here's a list of command-line arguments to `rustc` and what they do.
 
 ## `-h`/`--help`: get help
 
+This flag will print out help information for `rustc`.
+
 ## `--cfg`: configure the compilation environment
 
-## `-L`: add a directory to the library search path.
+This flag can turn on or off various `#[cfg]` settings.
+
+## `-L`: add a directory to the library search path
+
+When looking for external crates, a directory passed to this flag will be searched.
 
 ## `-l`: link the generated crate to a native library
 
+This flag allows you to specify linking to a specific native library when building
+a crate.
+
 ## `--crate-type`: a list of types of crates for the compiler to emit
 
+This instructs `rustc` on which crate type to build.
+
 ## `--crate-name`: specify the name of the crate being built
 
+This informs `rustc` of the name of your crate.
+
 ## `--emit`: emit output other than a crate
 
+Instead of producing a crate, this flag can print out things like the assembly or LLVM-IR.
+
 ## `--print`: print compiler information
 
+This flag prints out various information about the compiler.
+
 ## `-g`: include debug information
 
+A synonym for `-C debug-level=2`.
+
 ## `-O`: optimize your code
 
+A synonym for `-C opt-level=2`.
+
 ## `-o`: filename of the output
 
+This flag controls the output filename.
+
 ## `--out-dir`: directory to write the output in
 
+The outputted crate will be written to this directory.
+
 ## `--explain`: provide a detailed explanation of an error message
 
+Each error of `rustc`'s comes with an error code; this will print
+out a longer explanation of a given error.
+
 ## `--test`: build a test harness
 
+When compiling this crate, `rustc` will ignore your `main` function
+and instead produce a test harness.
+
 ## `--target`: select a target triple to build
 
+This controls which [target](targets/index.html) to produce.
+
 ## `-W`: set lint warnings
 
+This flag will set which lints should be set to the [warn level](lints/levels.html#warn).
+
 ## `-A`: set lint allowed
 
+This flag will set which lints should be set to the [allow level](lints/levels.html#allow).
+
 ## `-D`: set lint denied
 
+This flag will set which lints should be set to the [deny level](lints/levels.html#deny).
+
 ## `-F`: set lint forbidden
 
+This flag will set which lints should be set to the [forbid level](lints/levels.html#forbid).
+
 ## `--cap-lints`: set the most restrictive lint level
 
+This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-lints).
+
 ## `-C`/`--codegen`: code generation options
 
+This flag will allow you to set [codegen options](codegen-options/index.html).
+
 ## `-V`/`--verision`: print a version
 
+This flag will print out `rustc`'s version.
+
 ## `-v`/`--verbose`: use verbose output
 
+This flag, when combined with other flags, makes them produce extra output.
+
 ## `--extern`: specify where an external library is located
 
+This flag allows you to pass the name and location of an external crate that will
+be linked into the crate you're buildling.
+
 ## `--sysroot`: Override the system root
 
+The "sysroot" is where `rustc` looks for the crates that come with the Rust
+distribution; this flag allows that to be overridden.
+
 ## `--error-format`: control how errors are produced
 
-## `--color`: configur coloring of output
\ No newline at end of file
+This flag lets you control the format of errors.
+
+## `--color`: configur coloring of output
+
+This flag lets you control color settings of the output.
\ No newline at end of file

From b204968239188719b34929195e28b2cce25eb836 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Mon, 16 Apr 2018 12:57:09 -0400
Subject: [PATCH 15/24] fill out contributing

---
 src/doc/rustc/src/contributing.md | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
index e21b6fbd14aed..fcb8e6b27dbf0 100644
--- a/src/doc/rustc/src/contributing.md
+++ b/src/doc/rustc/src/contributing.md
@@ -1 +1,6 @@
 # Contributing to rustc
+
+We'd love to have your help improving `rustc`! To that end, we've written [a
+whole book](https://rust-lang-nursery.github.io/rustc-guide/) on its
+internals, how it works, and how to get started working on it. To learn
+more, you'll want to check that out.
\ No newline at end of file

From 00c860e8a908ae09eee0a3508a377fc6b7003d8c Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Mon, 16 Apr 2018 12:57:16 -0400
Subject: [PATCH 16/24] write docs for targets

---
 src/doc/rustc/src/targets/built-in.md |  9 +++++++++
 src/doc/rustc/src/targets/custom.md   | 16 ++++++++++++++++
 src/doc/rustc/src/targets/index.md    | 13 +++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
index 819d74457fe51..8620346e5b748 100644
--- a/src/doc/rustc/src/targets/built-in.md
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -1 +1,10 @@
 # Built-in Targets
+
+`rustc` ships with the ability to compile to many targets automatically, we
+call these "built-in" targets, and they generally correspond to targets that
+the team is supporting directly.
+
+To see the list of built-in targets, you can run `rustc --print target-list`,
+or look at [the API
+docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/#modules).
+Each module there defines a builder for a particular target.
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md
index 59039ce67bad9..0691afc60eae1 100644
--- a/src/doc/rustc/src/targets/custom.md
+++ b/src/doc/rustc/src/targets/custom.md
@@ -1 +1,17 @@
 # Custom Targets
+
+If you'd like to build for a target that is not yet supported by `rustc`, you can use a
+"custom target specification" to define a target. These target specification files
+are JSON. To see the JSON for the host target, you can run:
+
+```bash
+$ rustc +nightly -Z unstable-options --print target-spec-json
+```
+
+To see it for a different target, add the `--target` flag:
+
+```bash
+$ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json
+```
+
+To use a custom target, see [`xargo`](https://github.com/japaric/xargo).
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
index 01d0a4c8c0e3b..cea7ce4dea56a 100644
--- a/src/doc/rustc/src/targets/index.md
+++ b/src/doc/rustc/src/targets/index.md
@@ -1 +1,14 @@
 # Targets
+
+`rustc` is a cross-compiler by default. This means that you can use any compiler to build for any
+architecture. The list of *targets* are the possible architectures that you can build for.
+
+You can see the API docs for a given target
+[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html), all
+of these options can be set on a per-target basis.
+
+To compile to a particular target, use the `--target` flag:
+
+```bash
+$ rustc src/main.rs --target=wasm32-unknown-unknown
+```
\ No newline at end of file

From ac79c41edc2ed9d7125009dd5f21bdcc9fecb3c8 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Mon, 23 Apr 2018 11:58:11 -0400
Subject: [PATCH 17/24] review nits

---
 src/doc/rustc/src/codegen-options/index.md         | 4 ++--
 src/doc/rustc/src/lints/levels.md                  | 4 ++--
 src/doc/rustc/src/lints/listing/deny-by-default.md | 2 +-
 src/doc/rustc/src/targets/index.md                 | 7 +++----
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 70dae9314c1f7..eff09428902e8 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -99,7 +99,7 @@ flag will turn that behavior off.
 ## no-vectorize-slp
 
 By default, `rustc` will attempt to vectorize loops using [superword-level
-parallism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This
+parallelism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This
 flag will turn that behavior off.
 
 ## soft-float
@@ -206,4 +206,4 @@ This option lets you control what happens when the code panics.
 
 ## incremental
 
-This flag allows you to enable incremental compilation.
\ No newline at end of file
+This flag allows you to enable incremental compilation.
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
index 83b65cd648e0f..19bb6707d2285 100644
--- a/src/doc/rustc/src/lints/levels.md
+++ b/src/doc/rustc/src/lints/levels.md
@@ -45,8 +45,8 @@ pub fn foo() {
 
 This will produce this warning:
 
-```bash
-> rustc lib.rs --crate-type=lib
+```console
+$ rustc lib.rs --crate-type=lib
 warning: unused variable: `x`
  --> lib.rs:2:9
   |
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
index 0c49f2f7b36eb..e7ec6af8be1e3 100644
--- a/src/doc/rustc/src/lints/listing/deny-by-default.md
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -165,7 +165,7 @@ error: mutating transmuted &mut T from &T may cause undefined behavior, consider
 
 This lint detects any `const` items with the `#[no_mangle]` attribute.
 Constants do not have their symbols exported, and therefore, this probably
-means you meant to use a `static`, not a `const. Some example code that
+means you meant to use a `static`, not a `const`. Some example code that
 triggers this lint:
 
 ```rust,ignore
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
index cea7ce4dea56a..07e3a79471f5b 100644
--- a/src/doc/rustc/src/targets/index.md
+++ b/src/doc/rustc/src/targets/index.md
@@ -3,12 +3,11 @@
 `rustc` is a cross-compiler by default. This means that you can use any compiler to build for any
 architecture. The list of *targets* are the possible architectures that you can build for.
 
-You can see the API docs for a given target
-[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html), all
-of these options can be set on a per-target basis.
+To see all the options that you can set with a target, see the docs
+[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html).
 
 To compile to a particular target, use the `--target` flag:
 
 ```bash
 $ rustc src/main.rs --target=wasm32-unknown-unknown
-```
\ No newline at end of file
+```

From 36475d947b4c39ec9dcaad137d51019c8b861918 Mon Sep 17 00:00:00 2001
From: steveklabnik <steve@steveklabnik.com>
Date: Tue, 24 Apr 2018 12:21:08 -0400
Subject: [PATCH 18/24] more nits

---
 src/doc/rustc/src/command-line-arguments.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 488102f926a95..e2b001832fe31 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -89,7 +89,7 @@ This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-l
 
 This flag will allow you to set [codegen options](codegen-options/index.html).
 
-## `-V`/`--verision`: print a version
+## `-V`/`--version`: print a version
 
 This flag will print out `rustc`'s version.
 
@@ -111,6 +111,6 @@ distribution; this flag allows that to be overridden.
 
 This flag lets you control the format of errors.
 
-## `--color`: configur coloring of output
+## `--color`: configure coloring of output
 
-This flag lets you control color settings of the output.
\ No newline at end of file
+This flag lets you control color settings of the output.

From a95bff3ed40e46e89ca778b7674304bad92bc16e Mon Sep 17 00:00:00 2001
From: Michael Woerister <michaelwoerister@posteo>
Date: Wed, 25 Apr 2018 15:57:33 +0200
Subject: [PATCH 19/24] Bump bootstrap compiler to 2018-04-24

---
 src/stage0.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/stage0.txt b/src/stage0.txt
index e8db3358cf076..a5ad2b315a1dd 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-04-04
+date: 2018-04-24
 rustc: beta
 cargo: beta
 

From 2e4f66a86f7baa5644d18bb2adc07a8cd1c7409d Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Thu, 26 Apr 2018 15:35:24 +1000
Subject: [PATCH 20/24] Make dump_{alloc,allocs,local}() no-ops when tracing is
 disabled.

Because they traverse data structures and build up strings, which is
wasted effort if those strings aren't printed.

The patch also removes some now-unnecessary log_enabled! tests at call
sites.
---
 src/librustc_mir/interpret/eval_context.rs | 7 ++++---
 src/librustc_mir/interpret/memory.rs       | 6 ++++++
 src/librustc_mir/interpret/place.rs        | 4 +---
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b98ab218de5cb..90f1b5dda0162 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -749,9 +749,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             }
         }
 
-        if log_enabled!(::log::Level::Trace) {
-            self.dump_local(dest);
-        }
+        self.dump_local(dest);
 
         Ok(())
     }
@@ -1538,6 +1536,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
 
     pub fn dump_local(&self, place: Place) {
         // Debug output
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         match place {
             Place::Local { frame, local } => {
                 let mut allocs = Vec::new();
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 5e156e9271f57..7f8205b8327fa 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -334,11 +334,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
 
     /// For debugging, print an allocation and all allocations it points to, recursively.
     pub fn dump_alloc(&self, id: AllocId) {
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         self.dump_allocs(vec![id]);
     }
 
     /// For debugging, print a list of allocations and all allocations they point to, recursively.
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         use std::fmt::Write;
         allocs.sort();
         allocs.dedup();
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 456f5fd75db09..2d57ff44b4725 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -218,9 +218,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             }
         };
 
-        if log_enabled!(::log::Level::Trace) {
-            self.dump_local(place);
-        }
+        self.dump_local(place);
 
         Ok(place)
     }

From 30e3f1a620b06b6edd697c55858ea9f251a4332a Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Wed, 25 Apr 2018 20:10:58 +0200
Subject: [PATCH 21/24] Add more doc aliases

---
 src/libcore/cmp.rs       | 12 ++++++++++++
 src/libcore/fmt/mod.rs   |  2 ++
 src/libcore/ops/bit.rs   | 10 ++++++++++
 src/libcore/ops/deref.rs |  3 +++
 src/libcore/ops/range.rs |  6 ++++++
 5 files changed, 33 insertions(+)

diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index c91aa06609dd7..13e838773a587 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -106,6 +106,8 @@ use self::Ordering::*;
 /// ```
 #[lang = "eq"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
@@ -160,6 +162,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
 /// }
 /// impl Eq for Book {}
 /// ```
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Eq: PartialEq<Self> {
     // this method is used solely by #[deriving] to assert
@@ -428,6 +432,10 @@ impl<T: Ord> Ord for Reverse<T> {
 /// }
 /// ```
 #[lang = "ord"]
+#[doc(alias = "<")]
+#[doc(alias = ">")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an `Ordering` between `self` and `other`.
@@ -599,6 +607,10 @@ impl PartialOrd for Ordering {
 /// ```
 #[lang = "partial_ord"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = ">")]
+#[doc(alias = "<")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values if one exists.
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index a8430f14410e6..99e3012c9bf8c 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -547,6 +547,7 @@ impl<'a> Display for Arguments<'a> {
     message="`{Self}` doesn't implement `{Debug}`",
     label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`",
 )]
+#[doc(alias = "{:?}")]
 #[lang = "debug_trait"]
 pub trait Debug {
     /// Formats the value using the given formatter.
@@ -612,6 +613,7 @@ pub trait Debug {
     label="`{Self}` cannot be formatted with the default formatter; \
            try using `:?` instead if you are using a format string",
 )]
+#[doc(alias = "{}")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Display {
     /// Formats the value using the given formatter.
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
index 81c4455cef4d9..02b6f62db6eb1 100644
--- a/src/libcore/ops/bit.rs
+++ b/src/libcore/ops/bit.rs
@@ -119,6 +119,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 & bv2, expected);
 /// ```
 #[lang = "bitand"]
+#[doc(alias = "&")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
                          label="no implementation for `{Self} & {RHS}`")]
@@ -201,6 +202,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 | bv2, expected);
 /// ```
 #[lang = "bitor"]
+#[doc(alias = "|")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
                          label="no implementation for `{Self} | {RHS}`")]
@@ -286,6 +288,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 ^ bv2, expected);
 /// ```
 #[lang = "bitxor"]
+#[doc(alias = "^")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
                          label="no implementation for `{Self} ^ {RHS}`")]
@@ -372,6 +375,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
 /// ```
 #[lang = "shl"]
+#[doc(alias = "<<")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
                          label="no implementation for `{Self} << {RHS}`")]
@@ -479,6 +483,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 ///            SpinVector { vec: vec![3, 4, 0, 1, 2] });
 /// ```
 #[lang = "shr"]
+#[doc(alias = ">>")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
                          label="no implementation for `{Self} >> {RHS}`")]
@@ -593,6 +598,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// assert_eq!(bv, expected);
 /// ```
 #[lang = "bitand_assign"]
+#[doc(alias = "&=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
                          label="no implementation for `{Self} &= {Rhs}`")]
@@ -641,6 +647,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
 /// ```
 #[lang = "bitor_assign"]
+#[doc(alias = "|=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
                          label="no implementation for `{Self} |= {Rhs}`")]
@@ -689,6 +696,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
 /// ```
 #[lang = "bitxor_assign"]
+#[doc(alias = "^=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
                          label="no implementation for `{Self} ^= {Rhs}`")]
@@ -735,6 +743,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(scalar, Scalar(16));
 /// ```
 #[lang = "shl_assign"]
+#[doc(alias = "<<=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
                          label="no implementation for `{Self} <<= {Rhs}`")]
@@ -802,6 +811,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// assert_eq!(scalar, Scalar(4));
 /// ```
 #[lang = "shr_assign"]
+#[doc(alias = ">>=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
                          label="no implementation for `{Self} >>= {Rhs}`")]
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index 4ce0740130b98..332d154170f4d 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -68,6 +68,8 @@
 /// assert_eq!('a', *x);
 /// ```
 #[lang = "deref"]
+#[doc(alias = "*")]
+#[doc(alias = "&*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
     /// The resulting type after dereferencing.
@@ -162,6 +164,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
 /// assert_eq!('b', *x);
 /// ```
 #[lang = "deref_mut"]
+#[doc(alias = "*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait DerefMut: Deref {
     /// Mutably dereferences the value.
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 6f3e3b508853b..d70f7ae66f903 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -45,6 +45,7 @@ use fmt;
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFull;
@@ -74,6 +75,7 @@ impl fmt::Debug for RangeFull {
 /// assert_eq!(arr[1.. ], [     'b', 'c', 'd']);
 /// assert_eq!(arr[1..3], [     'b', 'c'     ]);  // Range
 /// ```
+#[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
@@ -175,6 +177,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
 /// ```
 ///
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
+#[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
@@ -256,6 +259,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeTo<Idx> {
@@ -323,6 +327,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// assert_eq!(arr[ ..=2], [0,1,2  ]);
 /// assert_eq!(arr[1..=2], [  1,2  ]);  // RangeInclusive
 /// ```
+#[doc(alias = "..=")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
@@ -449,6 +454,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..=")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeToInclusive<Idx> {

From 98c2e0976d6c4d0d3bd22e477b504f1a6f9b4ffa Mon Sep 17 00:00:00 2001
From: Shotaro Yamada <sinkuu@sinkuu.xyz>
Date: Mon, 23 Apr 2018 13:54:09 +0900
Subject: [PATCH 22/24] Do not ICE on generics mismatch with non-local traits

Fixes #49841
---
 src/librustc_typeck/check/compare_method.rs           |  3 +--
 .../compile-fail/impl-trait/impl-generic-mismatch.rs  | 11 +++++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index e1e3dea9a2a11..2003e0cc3d28f 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -730,8 +730,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if impl_ty.synthetic != trait_ty.synthetic {
             let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
             let impl_span = tcx.hir.span(impl_node_id);
-            let trait_node_id = tcx.hir.as_local_node_id(trait_ty.def_id).unwrap();
-            let trait_span = tcx.hir.span(trait_node_id);
+            let trait_span = tcx.def_span(trait_ty.def_id);
             let mut err = struct_span_err!(tcx.sess,
                                            impl_span,
                                            E0643,
diff --git a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
index eea7ca2095780..d6707f590113c 100644
--- a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
+++ b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
@@ -28,4 +28,15 @@ impl Bar for () {
     //~^ Error method `bar` has incompatible signature for trait
 }
 
+// With non-local trait (#49841):
+
+use std::hash::{Hash, Hasher};
+
+struct X;
+
+impl Hash for X {
+    fn hash(&self, hasher: &mut impl Hasher) {}
+    //~^ Error method `hash` has incompatible signature for trait
+}
+
 fn main() {}

From acf0adf7984d7bfc9bf5f81465471976c0f6b626 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Wed, 25 Apr 2018 19:50:32 +0200
Subject: [PATCH 23/24] Add setting to go to item if there is only one result

---
 src/librustdoc/html/render.rs      |  2 +
 src/librustdoc/html/static/main.js | 88 +++++++++++++++++++-----------
 2 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 0ae946c418286..0784c7b10e8c6 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1594,6 +1594,8 @@ impl<'a> Settings<'a> {
             settings: vec![
                 ("item-declarations", "Auto-hide item declarations.", true),
                 ("item-attributes", "Auto-hide item attributes.", true),
+                ("go-to-only-result", "Directly go to item in search if there is only one result",
+                 false),
             ],
             root_path,
             suffix,
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 58a57f43d3745..bcad2eb19f574 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1013,7 +1013,8 @@
                 'returned': sortResults(results_returned, true),
                 'others': sortResults(results),
             };
-            if (ALIASES[window.currentCrate][query.raw]) {
+            if (ALIASES && ALIASES[window.currentCrate] &&
+                    ALIASES[window.currentCrate][query.raw]) {
                 var aliases = ALIASES[window.currentCrate][query.raw];
                 for (var i = 0; i < aliases.length; ++i) {
                     ret['others'].unshift(aliases[i]);
@@ -1188,6 +1189,44 @@
             return '<span>' + path.replace(/::/g, '::</span><span>');
         }
 
+        function buildHrefAndPath(item) {
+            var displayPath;
+            var href;
+            var type = itemTypes[item.ty];
+            var name = item.name;
+
+            if (type === 'mod') {
+                displayPath = item.path + '::';
+                href = rootPath + item.path.replace(/::/g, '/') + '/' +
+                       name + '/index.html';
+            } else if (type === "primitive") {
+                displayPath = "";
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + type + '.' + name + '.html';
+            } else if (type === "externcrate") {
+                displayPath = "";
+                href = rootPath + name + '/index.html';
+            } else if (item.parent !== undefined) {
+                var myparent = item.parent;
+                var anchor = '#' + type + '.' + name;
+                var parentType = itemTypes[myparent.ty];
+                if (parentType === "primitive") {
+                    displayPath = myparent.name + '::';
+                } else {
+                    displayPath = item.path + '::' + myparent.name + '::';
+                }
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + parentType +
+                       '.' + myparent.name +
+                       '.html' + anchor;
+            } else {
+                displayPath = item.path + '::';
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + type + '.' + name + '.html';
+            }
+            return [displayPath, href];
+        }
+
         function addTab(array, query, display) {
             var extraStyle = '';
             if (display === false) {
@@ -1211,35 +1250,9 @@
                     name = item.name;
                     type = itemTypes[item.ty];
 
-                    if (type === 'mod') {
-                        displayPath = item.path + '::';
-                        href = rootPath + item.path.replace(/::/g, '/') + '/' +
-                               name + '/index.html';
-                    } else if (type === "primitive") {
-                        displayPath = "";
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + type + '.' + name + '.html';
-                    } else if (type === "externcrate") {
-                        displayPath = "";
-                        href = rootPath + name + '/index.html';
-                    } else if (item.parent !== undefined) {
-                        var myparent = item.parent;
-                        var anchor = '#' + type + '.' + name;
-                        var parentType = itemTypes[myparent.ty];
-                        if (parentType === "primitive") {
-                            displayPath = myparent.name + '::';
-                        } else {
-                            displayPath = item.path + '::' + myparent.name + '::';
-                        }
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + parentType +
-                               '.' + myparent.name +
-                               '.html' + anchor;
-                    } else {
-                        displayPath = item.path + '::';
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + type + '.' + name + '.html';
-                    }
+                    var res = buildHrefAndPath(item);
+                    var href = res[1];
+                    var displayPath = res[0];
 
                     output += '<tr class="' + type + ' result"><td>' +
                               '<a href="' + href + '">' +
@@ -1268,6 +1281,16 @@
         }
 
         function showResults(results) {
+            if (results['others'].length === 1 &&
+                getCurrentValue('rustdoc-go-to-only-result') === "true") {
+                var elem = document.createElement('a');
+                var res = buildHrefAndPath(results['others'][0]);
+                elem.href = res[1];
+                elem.style.display = 'none';
+                // For firefox, we need the element to be in the DOM so it can be clicked.
+                document.body.appendChild(elem);
+                elem.click();
+            }
             var output, query = getQuery(search_input.value);
 
             currentResults = query.id;
@@ -1721,6 +1744,9 @@
 
     function toggleAllDocs(pageId) {
         var toggle = document.getElementById("toggle-all-docs");
+        if (!toggle) {
+            return;
+        }
         if (hasClass(toggle, "will-expand")) {
             updateLocalStorage("rustdoc-collapse", "false");
             removeClass(toggle, "will-expand");
@@ -1977,7 +2003,7 @@
                 collapseDocs(e.previousSibling.childNodes[0], "toggle");
             }
         }
-    })
+    });
 
     autoCollapseAllImpls(getPageId());
 

From 4d52751d12429f4508f9a3c537521ba1113fabf5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Wed, 11 Apr 2018 23:02:41 +0200
Subject: [PATCH 24/24] Rename InternedString to LocalInternedString and
 introduce a new thread-safe InternedString

---
 src/librustc/hir/lowering.rs                  |   4 +-
 src/librustc/hir/map/def_collector.rs         |  33 +--
 src/librustc/hir/map/definitions.rs           |   6 +-
 src/librustc/ich/impls_syntax.rs              |  28 ++-
 src/librustc/lib.rs                           |   1 +
 src/librustc/traits/on_unimplemented.rs       |   6 +-
 src/librustc/ty/context.rs                    |   2 +-
 src/librustc/ty/item_path.rs                  |  11 +-
 src/librustc/ty/maps/values.rs                |   2 +-
 src/librustc/ty/mod.rs                        |  14 +-
 src/librustc/ty/sty.rs                        |   2 +-
 src/librustc/util/ppaux.rs                    |   2 +-
 src/librustc_driver/test.rs                   |   4 +-
 .../assert_module_sources.rs                  |   2 +-
 src/librustc_metadata/cstore_impl.rs          |   2 +-
 src/librustc_metadata/decoder.rs              |  16 +-
 src/librustc_mir/build/expr/into.rs           |   2 +-
 src/librustc_mir/interpret/const_eval.rs      |   2 +-
 src/librustc_mir/monomorphize/item.rs         |   2 +-
 src/librustc_mir/monomorphize/partitioning.rs |  14 +-
 src/librustc_mir/transform/check_unsafety.rs  |  12 +-
 src/librustc_mir/transform/qualify_consts.rs  |   2 +-
 src/librustc_resolve/build_reduced_graph.rs   |   5 +-
 src/librustc_trans/back/symbol_export.rs      |   2 +-
 src/librustc_trans/base.rs                    |   2 +-
 src/librustc_trans/callee.rs                  |   2 +-
 src/librustc_trans/common.rs                  |   6 +-
 src/librustc_trans/consts.rs                  |   2 +-
 src/librustc_trans/context.rs                 |   6 +-
 src/librustc_trans/debuginfo/metadata.rs      |   2 +-
 src/librustc_trans/debuginfo/mod.rs           |   2 +-
 src/librustc_trans/debuginfo/namespace.rs     |   2 +-
 src/librustc_trans/debuginfo/type_names.rs    |   4 +-
 src/librustc_trans/intrinsic.rs               |   2 +-
 src/librustc_trans/mir/block.rs               |   2 +-
 src/librustc_trans/trans_item.rs              |   2 +-
 src/librustc_trans_utils/symbol_names.rs      |   6 +-
 src/librustc_typeck/astconv.rs                |   4 +-
 src/librustc_typeck/check/intrinsic.rs        |   4 +-
 src/librustc_typeck/check/mod.rs              |   4 +-
 src/librustc_typeck/check/wfcheck.rs          |   2 +-
 src/librustc_typeck/collect.rs                |  18 +-
 src/librustdoc/clean/auto_trait.rs            |   4 +-
 src/librustdoc/clean/mod.rs                   |  12 +-
 src/libsyntax_pos/symbol.rs                   | 192 +++++++++++++++---
 45 files changed, 307 insertions(+), 149 deletions(-)

diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 4023521147e78..f5d590f25c80f 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -655,7 +655,7 @@ impl<'a> LoweringContext<'a> {
                 self.resolver.definitions().create_def_with_parent(
                     parent_id.index,
                     def_node_id,
-                    DefPathData::LifetimeDef(str_name),
+                    DefPathData::LifetimeDef(str_name.as_interned_str()),
                     DefIndexAddressSpace::High,
                     Mark::root(),
                     span,
@@ -1302,7 +1302,7 @@ impl<'a> LoweringContext<'a> {
                     self.context.resolver.definitions().create_def_with_parent(
                         self.parent,
                         def_node_id,
-                        DefPathData::LifetimeDef(name.name().as_str()),
+                        DefPathData::LifetimeDef(name.name().as_interned_str()),
                         DefIndexAddressSpace::High,
                         Mark::root(),
                         lifetime.span,
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bfe21549e453d..ebd8e6235825c 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -107,18 +107,18 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         // information we encapsulate into
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
-            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()),
+            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
             ItemKind::TraitAlias(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.name.as_str()),
+                DefPathData::TypeNs(i.ident.name.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
-            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.name.as_str()),
-            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
+                DefPathData::ValueNs(i.ident.name.as_interned_str()),
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
@@ -133,7 +133,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.ident.name.as_str()),
+                                            DefPathData::EnumVariant(v.node.ident
+                                                                      .name.as_interned_str()),
                                             REGULAR_SPACE,
                                             v.span);
                         this.with_parent(variant_def_index, |this| {
@@ -141,7 +142,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                                 let name = field.ident.map(|ident| ident.name)
                                     .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                                 this.create_def(field.id,
-                                                DefPathData::Field(name.as_str()),
+                                                DefPathData::Field(name.as_interned_str()),
                                                 REGULAR_SPACE,
                                                 field.span);
                             }
@@ -165,7 +166,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                         let name = field.ident.map(|ident| ident.name)
                             .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                         this.create_def(field.id,
-                                        DefPathData::Field(name.as_str()),
+                                        DefPathData::Field(name.as_interned_str()),
                                         REGULAR_SPACE,
                                         field.span);
                     }
@@ -187,7 +188,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         }
 
         let def = self.create_def(foreign_item.id,
-                                  DefPathData::ValueNs(foreign_item.ident.name.as_str()),
+                                  DefPathData::ValueNs(foreign_item.ident.name.as_interned_str()),
                                   REGULAR_SPACE,
                                   foreign_item.span);
 
@@ -201,7 +202,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             GenericParam::Lifetime(ref lifetime_def) => {
                 self.create_def(
                     lifetime_def.lifetime.id,
-                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_str()),
+                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()),
                     REGULAR_SPACE,
                     lifetime_def.lifetime.ident.span
                 );
@@ -209,7 +210,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             GenericParam::Type(ref ty_param) => {
                 self.create_def(
                     ty_param.id,
-                    DefPathData::TypeParam(ty_param.ident.name.as_str()),
+                    DefPathData::TypeParam(ty_param.ident.name.as_interned_str()),
                     REGULAR_SPACE,
                     ty_param.ident.span
                 );
@@ -222,8 +223,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name.as_str()),
-            TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()),
+                DefPathData::ValueNs(ti.ident.name.as_interned_str()),
+            TraitItemKind::Type(..) => {
+                DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str())
+            },
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
         };
 
@@ -240,8 +243,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.name.as_str()),
-            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()),
+                DefPathData::ValueNs(ii.ident.name.as_interned_str()),
+            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
         };
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 12f146ef49115..616dc22486d92 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -701,7 +701,7 @@ impl DefPathData {
             Typeof => "{{typeof}}",
         };
 
-        Symbol::intern(s).as_str()
+        Symbol::intern(s).as_interned_str()
     }
 
     pub fn to_string(&self) -> String {
@@ -731,7 +731,7 @@ macro_rules! define_global_metadata_kind {
                     definitions.create_def_with_parent(
                         CRATE_DEF_INDEX,
                         ast::DUMMY_NODE_ID,
-                        DefPathData::GlobalMetaData(instance.name().as_str()),
+                        DefPathData::GlobalMetaData(instance.name().as_interned_str()),
                         GLOBAL_MD_ADDRESS_SPACE,
                         Mark::root(),
                         DUMMY_SP
@@ -746,7 +746,7 @@ macro_rules! define_global_metadata_kind {
                 let def_key = DefKey {
                     parent: Some(CRATE_DEF_INDEX),
                     disambiguated_data: DisambiguatedDefPathData {
-                        data: DefPathData::GlobalMetaData(self.name().as_str()),
+                        data: DefPathData::GlobalMetaData(self.name().as_interned_str()),
                         disambiguator: 0,
                     }
                 };
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index d7e16ab36205e..c1e86473996d0 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -19,7 +19,7 @@ use std::mem;
 use syntax::ast;
 use syntax::feature_gate;
 use syntax::parse::token;
-use syntax::symbol::InternedString;
+use syntax::symbol::{InternedString, LocalInternedString};
 use syntax::tokenstream;
 use syntax_pos::FileMap;
 
@@ -34,8 +34,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        let s: &str = &**self;
-        s.hash_stable(hcx, hasher);
+        self.with(|s| s.hash_stable(hcx, hasher))
     }
 }
 
@@ -50,6 +49,27 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
     }
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let s: &str = &**self;
+        s.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
+    type KeyType = LocalInternedString;
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          _: &StableHashingContext<'a>)
+                          -> LocalInternedString {
+        self.clone()
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -66,7 +86,7 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
     fn to_stable_hash_key(&self,
                           _: &StableHashingContext<'a>)
                           -> InternedString {
-        self.as_str()
+        self.as_interned_str()
     }
 }
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index f85d0a9bf0c2e..c2b1d7f09149e 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -58,6 +58,7 @@
 #![feature(nonzero)]
 #![feature(proc_macro_internals)]
 #![feature(quote)]
+#![feature(optin_builtin_traits)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 405dafdff2b34..d1fd70ae02d69 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -18,10 +18,10 @@ use util::nodemap::FxHashMap;
 use syntax::ast::{MetaItem, NestedMetaItem};
 use syntax::attr;
 use syntax_pos::Span;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::LocalInternedString;
 
 #[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(InternedString);
+pub struct OnUnimplementedFormatString(LocalInternedString);
 
 #[derive(Debug)]
 pub struct OnUnimplementedDirective {
@@ -225,7 +225,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
 impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
     pub fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                      trait_def_id: DefId,
-                     from: InternedString,
+                     from: LocalInternedString,
                      err_sp: Span)
                      -> Result<Self, ErrorReported>
     {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 4f49b159ad387..d38c003ef8aeb 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2471,7 +2471,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(0, keywords::SelfType.name().as_str())
+        self.mk_param(0, keywords::SelfType.name().as_interned_str())
     }
 
     pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 2819141c81be2..752b7f69a6a7f 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -14,7 +14,7 @@ use ty::{self, Ty, TyCtxt};
 use middle::cstore::{ExternCrate, ExternCrateSource};
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 
 use std::cell::Cell;
 
@@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         let visible_parent_map = self.visible_parent_map(LOCAL_CRATE);
 
-        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<InternedString>::new());
+        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<LocalInternedString>::new());
         loop {
             // If `cur_def` is a direct or injected extern crate, push the path to the crate
             // followed by the path to the item within the crate and return.
@@ -168,8 +168,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
 
             let data = cur_def_key.disambiguated_data.data;
-            let symbol =
-                data.get_opt_name().unwrap_or_else(|| Symbol::intern("<unnamed>").as_str());
+            let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
+                Symbol::intern("<unnamed>").as_str()
+            });
             cur_path.push(symbol);
 
             match visible_parent_map.get(&cur_def) {
@@ -221,7 +222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::GlobalMetaData(..) => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
-                buffer.push(&data.as_interned_str());
+                buffer.push(&data.as_interned_str().as_symbol().as_str());
             }
             DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
diff --git a/src/librustc/ty/maps/values.rs b/src/librustc/ty/maps/values.rs
index 8d38d7dbbbbff..d3d0624879240 100644
--- a/src/librustc/ty/maps/values.rs
+++ b/src/librustc/ty/maps/values.rs
@@ -37,7 +37,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> {
 
 impl<'tcx> Value<'tcx> for ty::SymbolName {
     fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
-        ty::SymbolName { name: Symbol::intern("<error>").as_str() }
+        ty::SymbolName { name: Symbol::intern("<error>").as_interned_str() }
     }
 }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index de04366841076..19532bc80aa0d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -51,7 +51,7 @@ use std::mem;
 use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::{Symbol, LocalInternedString, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
@@ -2463,7 +2463,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn item_name(self, id: DefId) -> InternedString {
         if id.index == CRATE_DEF_INDEX {
-            self.original_crate_name(id.krate).as_str()
+            self.original_crate_name(id.krate).as_interned_str()
         } else {
             let def_key = self.def_key(id);
             // The name of a StructCtor is that of its struct parent.
@@ -2820,15 +2820,13 @@ impl_stable_hash_for!(struct self::SymbolName {
 impl SymbolName {
     pub fn new(name: &str) -> SymbolName {
         SymbolName {
-            name: Symbol::intern(name).as_str()
+            name: Symbol::intern(name).as_interned_str()
         }
     }
-}
-
-impl Deref for SymbolName {
-    type Target = str;
 
-    fn deref(&self) -> &str { &self.name }
+    pub fn as_str(&self) -> LocalInternedString {
+        self.name.as_str()
+    }
 }
 
 impl fmt::Display for SymbolName {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 0dfae13cc753a..2220f2b0aaf3a 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -864,7 +864,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, keywords::SelfType.name().as_str())
+        ParamTy::new(0, keywords::SelfType.name().as_interned_str())
     }
 
     pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 905776373bd37..b777f513e6df0 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -462,7 +462,7 @@ impl PrintContext {
                 0 => Symbol::intern("'r"),
                 1 => Symbol::intern("'s"),
                 i => Symbol::intern(&format!("'t{}", i-2)),
-            }.as_str()
+            }.as_interned_str()
         }
 
         // Replace any anonymous late-bound regions with named
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 47c49fbe9ef47..d2ee3d8743c2c 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -303,11 +303,11 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_str())
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_interned_str())
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
-        let name = Symbol::intern(name).as_str();
+        let name = Symbol::intern(name).as_interned_str();
         self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
             index,
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 46ba94f206151..6906dacfc5ef6 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -74,7 +74,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
 
         let mname = self.field(attr, MODULE);
         let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
-        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
+        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str();
 
         let dep_node = DepNode::new(self.tcx,
                                     DepConstructor::CompileCodegenUnit(mangled_cgu_name));
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index a11b95cb5b6c1..91f8beeaafb00 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -535,7 +535,7 @@ impl CrateStore for cstore::CStore {
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::from_str(&name),
+            ident: ast::Ident::from_str(&name.as_str()),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 0147e8dc60759..388bf1fb99a34 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -40,7 +40,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
-use syntax::symbol::{InternedString, Symbol};
+use syntax::symbol::InternedString;
 use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
 
@@ -537,12 +537,12 @@ impl<'a, 'tcx> CrateMetadata {
 
         ty::VariantDef {
             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-            name: Symbol::intern(&self.item_name(index)),
+            name: self.item_name(index).as_symbol(),
             fields: item.children.decode(self).map(|index| {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    name: Symbol::intern(&self.item_name(index)),
+                    name: self.item_name(index).as_symbol(),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -730,7 +730,7 @@ impl<'a, 'tcx> CrateMetadata {
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
                                     def,
-                                    ident: Ident::from_str(&self.item_name(child_index)),
+                                    ident: Ident::from_interned_str(self.item_name(child_index)),
                                     vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                     is_import: false,
@@ -748,7 +748,7 @@ impl<'a, 'tcx> CrateMetadata {
                 let span = child.span.decode((self, sess));
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::from_str(&name);
+                    let ident = Ident::from_interned_str(name);
                     let vis = self.get_visibility(child_index);
                     let is_import = false;
                     callback(def::Export { def, ident, vis, span, is_import });
@@ -847,7 +847,7 @@ impl<'a, 'tcx> CrateMetadata {
         };
 
         ty::AssociatedItem {
-            name: Symbol::intern(&name),
+            name: name.as_symbol(),
             kind,
             vis: item.visibility.decode(self),
             defaultness: container.defaultness(),
@@ -914,7 +914,7 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(id)
             .children
             .decode(self)
-            .map(|index| Symbol::intern(&self.item_name(index)))
+            .map(|index| self.item_name(index).as_symbol())
             .collect()
     }
 
@@ -1106,7 +1106,7 @@ impl<'a, 'tcx> CrateMetadata {
             DefKey {
                 parent: Some(CRATE_DEF_INDEX),
                 disambiguated_data: DisambiguatedDefPathData {
-                    data: DefPathData::MacroDef(name.as_str()),
+                    data: DefPathData::MacroDef(name.as_interned_str()),
                     disambiguator: 0,
                 }
             }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index c130b4f550fd4..562f890b4c0fb 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -220,7 +220,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         let f = ty.fn_sig(this.hir.tcx());
                         if f.abi() == Abi::RustIntrinsic ||
                            f.abi() == Abi::PlatformIntrinsic {
-                            Some(this.hir.tcx().item_name(def_id))
+                            Some(this.hir.tcx().item_name(def_id).as_str())
                         } else {
                             None
                         }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index a25331f7279fb..dff9fa271aba5 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -263,7 +263,7 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
     ) -> EvalResult<'tcx> {
         let substs = instance.substs;
 
-        let intrinsic_name = &ecx.tcx.item_name(instance.def_id())[..];
+        let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..];
         match intrinsic_name {
             "min_align_of" => {
                 let elem_ty = substs.type_at(0);
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 9e0c977a3f062..9e43bed1b63af 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
             MonoItem::GlobalAsm(node_id) => {
                 let def_id = tcx.hir.local_def_id(node_id);
                 ty::SymbolName {
-                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_str()
+                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str()
                 }
             }
         }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index f29f86af4aba7..3a65cd4ea770b 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -146,7 +146,7 @@ pub trait CodegenUnitExt<'tcx> {
     }
 
     fn work_product_id(&self) -> WorkProductId {
-        WorkProductId::from_cgu_name(self.name())
+        WorkProductId::from_cgu_name(&self.name().as_str())
     }
 
     fn items_in_deterministic_order<'a>(&self,
@@ -206,9 +206,9 @@ fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
     const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
 
     if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
-        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str()
+        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str()
     } else {
-        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str()
+        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str()
     }
 }
 
@@ -740,7 +740,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         }
                     }) {
         cgu_name.push_str("-");
-        cgu_name.push_str(&part.data.as_interned_str());
+        cgu_name.push_str(&part.data.as_interned_str().as_str());
     }
 
     if volatile {
@@ -753,11 +753,11 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         CodegenUnit::mangle_name(&cgu_name)
     };
 
-    Symbol::intern(&cgu_name[..]).as_str()
+    Symbol::intern(&cgu_name[..]).as_interned_str()
 }
 
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
-    Symbol::intern(&format!("{}{}", crate_name, index)).as_str()
+    Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str()
 }
 
 fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -772,7 +772,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             debug!("CodegenUnit {}:", cgu.name());
 
             for (trans_item, linkage) in cgu.items() {
-                let symbol_name = trans_item.symbol_name(tcx);
+                let symbol_name = trans_item.symbol_name(tcx).name.as_str();
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
                                                    .unwrap_or("<no hash>");
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 31af7c2185794..2bf5a49c97e8f 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     self.visibility_scope_info[source_info.scope].lint_root;
                 self.register_violations(&[UnsafetyViolation {
                     source_info,
-                    description: Symbol::intern("borrow of packed field").as_str(),
+                    description: Symbol::intern("borrow of packed field").as_interned_str(),
                     kind: UnsafetyViolationKind::BorrowPacked(lint_root)
                 }], &[]);
             }
@@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.visibility_scope_info[source_info.scope].lint_root;
                     self.register_violations(&[UnsafetyViolation {
                         source_info,
-                        description: Symbol::intern("use of extern static").as_str(),
+                        description: Symbol::intern("use of extern static").as_interned_str(),
                         kind: UnsafetyViolationKind::ExternStatic(lint_root)
                     }], &[]);
                 }
@@ -231,7 +231,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info,
-            description: Symbol::intern(description).as_str(),
+            description: Symbol::intern(description).as_interned_str(),
             kind: UnsafetyViolationKind::General,
         }], &[]);
     }
@@ -444,7 +444,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                 struct_span_err!(
                     tcx.sess, source_info.span, E0133,
                     "{} requires unsafe function or block", description)
-                    .span_label(source_info.span, &description[..])
+                    .span_label(source_info.span, &description.as_str()[..])
                     .emit();
             }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
@@ -452,7 +452,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                               lint_node_id,
                               source_info.span,
                               &format!("{} requires unsafe function or \
-                                        block (error E0133)", &description[..]));
+                                        block (error E0133)", &description.as_str()[..]));
             }
             UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
                 if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) {
@@ -462,7 +462,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                                   lint_node_id,
                                   source_info.span,
                                   &format!("{} requires unsafe function or \
-                                            block (error E0133)", &description[..]));
+                                            block (error E0133)", &description.as_str()[..]));
                 }
             }
         }
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index ff7551ed6f4f8..4762c6aaa27cc 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -868,7 +868,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
                         assert!(!self.tcx.is_const_fn(def_id));
-                        match &self.tcx.item_name(def_id)[..] {
+                        match &self.tcx.item_name(def_id).as_str()[..] {
                             "size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id),
 
                             name if name.starts_with("simd_shuffle") => {
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index f4e2136a5a115..14ceb5f59a3ec 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -41,7 +41,6 @@ use syntax::ext::tt::macro_rules;
 use syntax::parse::token::{self, Token};
 use syntax::std_inject::injected_crate_name;
 use syntax::symbol::keywords;
-use syntax::symbol::Symbol;
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -544,14 +543,14 @@ impl<'a> Resolver<'a> {
         }
 
         let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
-            (self.cstore.crate_name_untracked(def_id.krate).as_str(), None)
+            (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
         } else {
             let def_key = self.cstore.def_key(def_id);
             (def_key.disambiguated_data.data.get_opt_name().unwrap(),
              Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
         };
 
-        let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name));
+        let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol());
         let module =
             self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
         self.extern_module_map.insert((def_id, macros_only), module);
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 965a34eccb862..d8520b61d9157 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -132,7 +132,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         })
         .map(|def_id| {
             let export_level = if special_runtime_crate {
-                let name = tcx.symbol_name(Instance::mono(tcx, def_id));
+                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str();
                 // We can probably do better here by just ensuring that
                 // it has hidden visibility rather than public
                 // visibility, as this is primarily here to ensure it's
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 2323ec3ef1108..b756a6695f941 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1037,7 +1037,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
                 cgus.dedup();
                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
                     output.push_str(" ");
-                    output.push_str(&cgu_name);
+                    output.push_str(&cgu_name.as_str());
 
                     let linkage_abbrev = match linkage {
                         Linkage::External => "External",
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 5849437758af6..9263d9a5f5dc2 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -52,7 +52,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return llfn;
     }
 
-    let sym = tcx.symbol_name(instance);
+    let sym = tcx.symbol_name(instance).as_str();
     debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
 
     // Create a fn pointer with the substituted signature.
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 25ca2152b2768..4a0619b23360d 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -33,7 +33,7 @@ use libc::{c_uint, c_char};
 use std::iter;
 
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use syntax_pos::{Span, DUMMY_SP};
 
 pub use context::CodegenCx;
@@ -183,7 +183,7 @@ pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
 
 // This is a 'c-like' raw string, which differs from
 // our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef {
     unsafe {
         if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
             return llval;
@@ -208,7 +208,7 @@ pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> Value
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CodegenCx, s: InternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
         cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 122b51dbbb778..405cb83ad4d75 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -118,7 +118,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
              def_id);
 
     let ty = instance.ty(cx.tcx);
-    let sym = cx.tcx.symbol_name(instance);
+    let sym = cx.tcx.symbol_name(instance).as_str();
 
     let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
 
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 76f8be9ee98a6..90b2fb4b59a70 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -39,7 +39,7 @@ use std::ptr;
 use std::iter;
 use std::str;
 use std::sync::Arc;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use abi::Abi;
 
 /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
@@ -62,7 +62,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
                                 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
+    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, ValueRef>>,
 
     /// Reverse-direction for const ptrs cast from globals.
     /// Key is a ValueRef holding a *T,
@@ -273,7 +273,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
             let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
                 let dctx = debuginfo::CrateDebugContext::new(llmod);
                 debuginfo::metadata::compile_unit_metadata(tcx,
-                                                           codegen_unit.name(),
+                                                           &codegen_unit.name().as_str(),
                                                            &dctx);
                 Some(dctx)
             } else {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 5359e0e0405a1..123b9cf7931a5 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -1399,7 +1399,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     (discr.size(cx), discr.align(cx));
                 let discriminant_base_type_metadata =
                     type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
-                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
+                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str();
 
                 let name = CString::new(discriminant_name.as_bytes()).unwrap();
                 let discriminant_type_metadata = unsafe {
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 706dc3dca8a61..193db15303f97 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -394,7 +394,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             substs.types().zip(names).map(|(ty, name)| {
                 let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                 let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
-                let name = CString::new(name.as_bytes()).unwrap();
+                let name = CString::new(name.as_str().as_bytes()).unwrap();
                 unsafe {
                     llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index 891bf649c388a..51c45de9dc22a 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -47,7 +47,7 @@ pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
 
     let namespace_name = match def_key.disambiguated_data.data {
         DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(),
-        data => data.as_interned_str()
+        data => data.as_interned_str().as_str()
     };
 
     let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 96ed4e8847115..825fac36c93d7 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -190,10 +190,10 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
             for path_element in cx.tcx.def_path(def_id).data {
                 output.push_str("::");
-                output.push_str(&path_element.data.as_interned_str());
+                output.push_str(&path_element.data.as_interned_str().as_str());
             }
         } else {
-            output.push_str(&cx.tcx.item_name(def_id));
+            output.push_str(&cx.tcx.item_name(def_id).as_str());
         }
     }
 
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 103b04e6f135b..49a207a2d8ab5 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -103,7 +103,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
     let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
     let arg_tys = sig.inputs();
     let ret_ty = sig.output();
-    let name = &*tcx.item_name(def_id);
+    let name = &*tcx.item_name(def_id).as_str();
 
     let llret_ty = cx.layout_of(ret_ty).llvm_type(cx);
     let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align);
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 36f03605feabd..fb6a17a1c75b4 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -442,7 +442,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 // Handle intrinsics old trans wants Expr's for, ourselves.
                 let intrinsic = match def {
                     Some(ty::InstanceDef::Intrinsic(def_id))
-                        => Some(bx.tcx().item_name(def_id)),
+                        => Some(bx.tcx().item_name(def_id).as_str()),
                     _ => None
                 };
                 let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 06d94e8d15569..d19b5af25273d 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -88,7 +88,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
                self.to_raw_string(),
                cx.codegen_unit.name());
 
-        let symbol_name = self.symbol_name(cx.tcx);
+        let symbol_name = self.symbol_name(cx.tcx).as_str();
 
         debug!("symbol {}", &symbol_name);
 
diff --git a/src/librustc_trans_utils/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs
index f3b7326b21071..be5bff60805c3 100644
--- a/src/librustc_trans_utils/symbol_names.rs
+++ b/src/librustc_trans_utils/symbol_names.rs
@@ -229,7 +229,7 @@ fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
                          -> ty::SymbolName
 {
-    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() }
+    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_interned_str() }
 }
 
 fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
@@ -355,12 +355,12 @@ impl SymbolPathBuffer {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16)
         };
-        result.result.push_str(&symbol.name);
+        result.result.push_str(&symbol.name.as_str());
         result
     }
 
     fn into_interned(self) -> ty::SymbolName {
-        ty::SymbolName { name: Symbol::intern(&self.result).as_str() }
+        ty::SymbolName { name: Symbol::intern(&self.result).as_interned_str() }
     }
 
     fn finish(mut self, hash: u64) -> String {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 6cdce127308f6..93dbba6e873a9 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -101,7 +101,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     {
         let tcx = self.tcx();
         let lifetime_name = |def_id| {
-            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_str()
+            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_interned_str()
         };
 
         let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
@@ -981,7 +981,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 let item_def_id = tcx.hir.local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)];
-                tcx.mk_param(index, tcx.hir.name(node_id).as_str())
+                tcx.mk_param(index, tcx.hir.name(node_id).as_interned_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 283fbf8fecc42..fcf7541a159b0 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_str());
+    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
     let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
@@ -341,7 +341,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                it: &hir::ForeignItem) {
     let param = |n| {
-        let name = Symbol::intern(&format!("P{}", n)).as_str();
+        let name = Symbol::intern(&format!("P{}", n)).as_interned_str();
         tcx.mk_param(n, name)
     };
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 787df7c647969..db859e42057e9 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -124,7 +124,7 @@ use syntax::attr;
 use syntax::codemap::{original_sp, Spanned};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, InternedString, keywords};
+use syntax::symbol::{Symbol, LocalInternedString, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{self, BytePos, Span, MultiSpan};
 
@@ -3172,7 +3172,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // Return an hint about the closest match in field names
     fn suggest_field_name(variant: &'tcx ty::VariantDef,
                           field: &Spanned<ast::Name>,
-                          skip: Vec<InternedString>)
+                          skip: Vec<LocalInternedString>)
                           -> Option<Symbol> {
         let name = field.node.as_str();
         let names = variant.fields.iter().filter_map(|field| {
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 9c4807bec2f08..d0ff44c8e7e10 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -655,7 +655,7 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
             // local so it should be okay to just unwrap everything.
             let trait_def_id = impl_params[&method_param.name];
             let trait_decl_span = tcx.def_span(trait_def_id);
-            error_194(tcx, type_span, trait_decl_span, &method_param.name[..]);
+            error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
         }
     }
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 2ebbd64cab90e..1b8f2e661c30d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -244,7 +244,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_owner_def_id = tcx.hir.local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
     let index = generics.type_param_to_index[&def_id];
-    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_str());
+    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -842,7 +842,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     opt_self = Some(ty::TypeParameterDef {
                         index: 0,
-                        name: keywords::SelfType.name().as_str(),
+                        name: keywords::SelfType.name().as_interned_str(),
                         def_id: tcx.hir.local_def_id(param_id),
                         has_default: false,
                         object_lifetime_default: rl::Set1::Empty,
@@ -888,7 +888,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
     let regions = early_lifetimes.enumerate().map(|(i, l)| {
         ty::RegionParameterDef {
-            name: l.lifetime.name.name().as_str(),
+            name: l.lifetime.name.name().as_interned_str(),
             index: own_start + i as u32,
             def_id: tcx.hir.local_def_id(l.lifetime.id),
             pure_wrt_drop: l.pure_wrt_drop,
@@ -918,7 +918,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         ty::TypeParameterDef {
             index: type_start + i as u32,
-            name: p.name.as_str(),
+            name: p.name.as_interned_str(),
             def_id: tcx.hir.local_def_id(p.id),
             has_default: p.default.is_some(),
             object_lifetime_default:
@@ -937,7 +937,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure kind
         types.push(ty::TypeParameterDef {
             index: type_start,
-            name: Symbol::intern("<closure_kind>").as_str(),
+            name: Symbol::intern("<closure_kind>").as_interned_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -948,7 +948,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure signature
         types.push(ty::TypeParameterDef {
             index: type_start + 1,
-            name: Symbol::intern("<closure_signature>").as_str(),
+            name: Symbol::intern("<closure_signature>").as_interned_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -959,7 +959,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.with_freevars(node_id, |fv| {
             types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
                 index: type_start + i,
-                name: Symbol::intern("<upvar>").as_str(),
+                name: Symbol::intern("<upvar>").as_interned_str(),
                 def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
@@ -1429,7 +1429,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: tcx.hir.local_def_id(param.lifetime.id),
             index,
-            name: param.lifetime.name.name().as_str(),
+            name: param.lifetime.name.name().as_interned_str(),
         }));
         index += 1;
 
@@ -1443,7 +1443,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Collect the predicates that were written inline by the user on each
     // type parameter (e.g., `<T:Foo>`).
     for param in ast_generics.ty_params() {
-        let param_ty = ty::ParamTy::new(index, param.name.as_str()).to_ty(tcx);
+        let param_ty = ty::ParamTy::new(index, param.name.as_interned_str()).to_ty(tcx);
         index += 1;
 
         let bounds = compute_bounds(&icx,
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 477b576ad217e..221fc4dab7232 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -224,7 +224,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                     let name = if p.name == "" {
                         hir::LifetimeName::Static
                     } else {
-                        hir::LifetimeName::Name(Symbol::intern(&p.name))
+                        hir::LifetimeName::Name(p.name.as_symbol())
                     };
 
                     hir::Lifetime {
@@ -261,7 +261,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                     span: DUMMY_SP,
                     def: Def::TyParam(param.def_id),
                     segments: HirVec::from_vec(vec![
-                        hir::PathSegment::from_name(Symbol::intern(&param.name))
+                        hir::PathSegment::from_name(param.name.as_symbol())
                     ]),
                 }),
             )),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fb05cbfe32c70..6623d5ab3c2c2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1367,7 +1367,7 @@ impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
         let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, &cx.tcx.item_name(did),
+        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
             Some(did), false, vec![], empty);
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
         TraitBound(PolyTrait {
@@ -1474,7 +1474,7 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         let (trait_ref, ref bounds) = *self;
         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
-        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id),
+        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
                                  Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
@@ -2801,7 +2801,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     AdtKind::Enum => TypeKind::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, &cx.tcx.item_name(did),
+                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], substs);
                 ResolvedPath {
                     path,
@@ -2812,7 +2812,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             }
             ty::TyForeign(did) => {
                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
-                let path = external_path(cx, &cx.tcx.item_name(did),
+                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], Substs::empty());
                 ResolvedPath {
                     path: path,
@@ -2830,7 +2830,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
                     for did in obj.auto_traits() {
                         let empty = cx.tcx.intern_substs(&[]);
-                        let path = external_path(cx, &cx.tcx.item_name(did),
+                        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                             Some(did), false, vec![], empty);
                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
                         let bound = TraitBound(PolyTrait {
@@ -2853,7 +2853,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                         });
                     }
 
-                    let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
+                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
                         false, bindings, principal.skip_binder().substs);
                     ResolvedPath {
                         path,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 556ee162c6ef2..4a8b1e8b1c1e4 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -18,6 +18,7 @@ use {Span, DUMMY_SP, GLOBALS};
 use rustc_data_structures::fx::FxHashMap;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
+use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::hash::{Hash, Hasher};
 
 #[derive(Copy, Clone, Eq)]
@@ -36,6 +37,11 @@ impl Ident {
         Ident::new(name, DUMMY_SP)
     }
 
+    /// Maps an interned string to an identifier with an empty syntax context.
+    pub fn from_interned_str(string: InternedString) -> Ident {
+        Ident::with_empty_ctxt(string.as_symbol())
+    }
+
     /// Maps a string to an identifier with an empty syntax context.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_empty_ctxt(Symbol::intern(string))
@@ -138,14 +144,20 @@ impl Symbol {
         with_interner(|interner| interner.gensymed(self))
     }
 
-    pub fn as_str(self) -> InternedString {
+    pub fn as_str(self) -> LocalInternedString {
         with_interner(|interner| unsafe {
-            InternedString {
+            LocalInternedString {
                 string: ::std::mem::transmute::<&str, &str>(interner.get(self))
             }
         })
     }
 
+    pub fn as_interned_str(self) -> InternedString {
+        with_interner(|interner| InternedString {
+            symbol: interner.interned(self)
+        })
+    }
+
     pub fn as_u32(self) -> u32 {
         self.0
     }
@@ -365,84 +377,208 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
     GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
 }
 
-/// Represents a string stored in the thread-local interner. Because the
-/// interner lives for the life of the thread, this can be safely treated as an
-/// immortal string, as long as it never crosses between threads.
-///
-/// FIXME(pcwalton): You must be careful about what you do in the destructors
-/// of objects stored in TLS, because they may run after the interner is
-/// destroyed. In particular, they must not access string contents. This can
-/// be fixed in the future by just leaking all strings until thread death
-/// somehow.
+/// Represents a string stored in the interner. Because the interner outlives any thread
+/// which uses this type, we can safely treat `string` which points to interner data,
+/// as an immortal string, as long as this type never crosses between threads.
+// FIXME: Ensure that the interner outlives any thread which uses LocalInternedString,
+//        by creating a new thread right after constructing the interner
 #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
-pub struct InternedString {
+pub struct LocalInternedString {
     string: &'static str,
 }
 
-impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
+impl LocalInternedString {
+    pub fn as_interned_str(self) -> InternedString {
+        InternedString {
+            symbol: Symbol::intern(self.string)
+        }
+    }
+}
+
+impl<U: ?Sized> ::std::convert::AsRef<U> for LocalInternedString
+where
+    str: ::std::convert::AsRef<U>
+{
     fn as_ref(&self) -> &U {
         self.string.as_ref()
     }
 }
 
-impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
+impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for LocalInternedString {
     fn eq(&self, other: &T) -> bool {
         self.string == other.deref()
     }
 }
 
-impl ::std::cmp::PartialEq<InternedString> for str {
-    fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for str {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         self == other.string
     }
 }
 
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
-    fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a str {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         *self == other.string
     }
 }
 
-impl ::std::cmp::PartialEq<InternedString> for String {
-    fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for String {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         self == other.string
     }
 }
 
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
-    fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a String {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         *self == other.string
     }
 }
 
-impl !Send for InternedString { }
+impl !Send for LocalInternedString {}
+impl !Sync for LocalInternedString {}
 
-impl ::std::ops::Deref for InternedString {
+impl ::std::ops::Deref for LocalInternedString {
     type Target = str;
     fn deref(&self) -> &str { self.string }
 }
 
-impl fmt::Debug for InternedString {
+impl fmt::Debug for LocalInternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(self.string, f)
     }
 }
 
-impl fmt::Display for InternedString {
+impl fmt::Display for LocalInternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(self.string, f)
     }
 }
 
+impl Decodable for LocalInternedString {
+    fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
+        Ok(Symbol::intern(&d.read_str()?).as_str())
+    }
+}
+
+impl Encodable for LocalInternedString {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(self.string)
+    }
+}
+
+/// Represents a string stored in the string interner
+#[derive(Clone, Copy, Eq)]
+pub struct InternedString {
+    symbol: Symbol,
+}
+
+impl InternedString {
+    pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
+        let str = with_interner(|interner| {
+            interner.get(self.symbol) as *const str
+        });
+        // This is safe because the interner keeps string alive until it is dropped.
+        // We can access it because we know the interner is still alive since we use a
+        // scoped thread local to access it, and it was alive at the begining of this scope
+        unsafe { f(&*str) }
+    }
+
+    pub fn as_symbol(self) -> Symbol {
+        self.symbol
+    }
+
+    pub fn as_str(self) -> LocalInternedString {
+        self.symbol.as_str()
+    }
+}
+
+impl Hash for InternedString {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.with(|str| str.hash(state))
+    }
+}
+
+impl PartialOrd<InternedString> for InternedString {
+    fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
+        if self.symbol == other.symbol {
+            return Some(Ordering::Equal);
+        }
+        self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str)))
+    }
+}
+
+impl Ord for InternedString {
+    fn cmp(&self, other: &InternedString) -> Ordering {
+        if self.symbol == other.symbol {
+            return Ordering::Equal;
+        }
+        self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str)))
+    }
+}
+
+impl<T: ::std::ops::Deref<Target = str>> PartialEq<T> for InternedString {
+    fn eq(&self, other: &T) -> bool {
+        self.with(|string| string == other.deref())
+    }
+}
+
+impl PartialEq<InternedString> for InternedString {
+    fn eq(&self, other: &InternedString) -> bool {
+        self.symbol == other.symbol
+    }
+}
+
+impl PartialEq<InternedString> for str {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| self == string)
+    }
+}
+
+impl<'a> PartialEq<InternedString> for &'a str {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| *self == string)
+    }
+}
+
+impl PartialEq<InternedString> for String {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| self == string)
+    }
+}
+
+impl<'a> PartialEq<InternedString> for &'a String {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| *self == string)
+    }
+}
+
+impl ::std::convert::From<InternedString> for String {
+    fn from(val: InternedString) -> String {
+        val.as_symbol().to_string()
+    }
+}
+
+impl fmt::Debug for InternedString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.with(|str| fmt::Debug::fmt(&str, f))
+    }
+}
+
+impl fmt::Display for InternedString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.with(|str| fmt::Display::fmt(&str, f))
+    }
+}
+
 impl Decodable for InternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
-        Ok(Symbol::intern(&d.read_str()?).as_str())
+        Ok(Symbol::intern(&d.read_str()?).as_interned_str())
     }
 }
 
 impl Encodable for InternedString {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self.string)
+        self.with(|string| s.emit_str(string))
     }
 }