about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-05-03 03:24:35 +0000
committerbors <bors@rust-lang.org>2017-05-03 03:24:35 +0000
commit146dc670cfec54a02bc1eddef62f6a595c6b3726 (patch)
tree763b7680341f8413be81b4facaf9f84eb75229e5
parent0634f0a30f94116ee13c16fb1a35c4c92253ab13 (diff)
parent2b51384a2d6973b307ca126551fbe838cf7384d0 (diff)
downloadrust-146dc670cfec54a02bc1eddef62f6a595c6b3726.tar.gz
rust-146dc670cfec54a02bc1eddef62f6a595c6b3726.zip
Auto merge of #41717 - frewsxcv:rollup, r=frewsxcv
Rollup of 7 pull requests

- Successful merges: #41217, #41625, #41640, #41653, #41656, #41657, #41705
- Failed merges:
-rw-r--r--src/grammar/.gitignore4
-rw-r--r--src/grammar/README.md33
-rw-r--r--src/grammar/RustLexer.g4197
-rwxr-xr-xsrc/grammar/check.sh52
-rw-r--r--src/grammar/lexer.l343
-rw-r--r--src/grammar/parser-lalr-main.c203
-rw-r--r--src/grammar/parser-lalr.y1945
-rw-r--r--src/grammar/raw-string-literal-ambiguity.md64
-rwxr-xr-xsrc/grammar/testparser.py76
-rw-r--r--src/grammar/tokens.h91
-rw-r--r--src/grammar/verify.rs361
-rw-r--r--src/grammar/xidcontinue.g4473
-rw-r--r--src/grammar/xidstart.g4379
-rw-r--r--src/libcore/sync/atomic.rs55
-rw-r--r--src/librustc/dep_graph/dep_node.rs6
-rw-r--r--src/librustc/dep_graph/mod.rs1
-rw-r--r--src/librustc/dep_graph/safe.rs6
-rw-r--r--src/librustc/dep_graph/visit.rs12
-rw-r--r--src/librustc/hir/map/mod.rs2
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/middle/cstore.rs5
-rw-r--r--src/librustc/middle/stability.rs4
-rw-r--r--src/librustc/mir/README.md90
-rw-r--r--src/librustc/mir/mod.rs2
-rw-r--r--src/librustc/mir/transform.rs187
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/session/mod.rs3
-rw-r--r--src/librustc/ty/context.rs22
-rw-r--r--src/librustc/ty/maps.rs233
-rw-r--r--src/librustc/ty/mod.rs57
-rw-r--r--src/librustc/ty/steal.rs57
-rw-r--r--src/librustc_back/target/arm_linux_androideabi.rs3
-rw-r--r--src/librustc_back/target/armv7_linux_androideabi.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs9
-rw-r--r--src/librustc_borrowck/borrowck/mir/elaborate_drops.rs12
-rw-r--r--src/librustc_borrowck/borrowck/mir/mod.rs5
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs27
-rw-r--r--src/librustc_driver/driver.rs100
-rw-r--r--src/librustc_driver/pretty.rs17
-rw-r--r--src/librustc_driver/test.rs2
-rw-r--r--src/librustc_metadata/cstore_impl.rs24
-rw-r--r--src/librustc_metadata/decoder.rs8
-rw-r--r--src/librustc_metadata/encoder.rs27
-rw-r--r--src/librustc_mir/build/into.rs2
-rw-r--r--src/librustc_mir/build/mod.rs229
-rw-r--r--src/librustc_mir/callgraph.rs252
-rw-r--r--src/librustc_mir/hair/cx/mod.rs6
-rw-r--r--src/librustc_mir/lib.rs7
-rw-r--r--src/librustc_mir/mir_map.rs273
-rw-r--r--src/librustc_mir/shim.rs9
-rw-r--r--src/librustc_mir/transform/add_call_guards.rs11
-rw-r--r--src/librustc_mir/transform/copy_prop.rs14
-rw-r--r--src/librustc_mir/transform/deaggregator.rs12
-rw-r--r--src/librustc_mir/transform/dump_mir.rs74
-rw-r--r--src/librustc_mir/transform/erase_regions.rs12
-rw-r--r--src/librustc_mir/transform/inline.rs264
-rw-r--r--src/librustc_mir/transform/instcombine.rs40
-rw-r--r--src/librustc_mir/transform/mod.rs127
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs32
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs65
-rw-r--r--src/librustc_mir/transform/simplify.rs43
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs31
-rw-r--r--src/librustc_mir/transform/type_check.rs13
-rw-r--r--src/librustc_mir/util/graphviz.rs16
-rw-r--r--src/librustc_mir/util/mod.rs2
-rw-r--r--src/librustc_mir/util/pretty.rs95
-rw-r--r--src/librustc_passes/mir_stats.rs8
-rw-r--r--src/librustc_trans/collector.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/test/mir-opt/basic_assignment.rs4
-rw-r--r--src/test/mir-opt/issue-38669.rs4
-rw-r--r--src/test/mir-opt/simplify_if.rs8
-rw-r--r--src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr5
-rw-r--r--src/tools/compiletest/src/runtest.rs10
74 files changed, 1355 insertions, 5523 deletions
diff --git a/src/grammar/.gitignore b/src/grammar/.gitignore
deleted file mode 100644
index e77db28967e..00000000000
--- a/src/grammar/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-verify
-*.class
-*.java
-*.tokens
diff --git a/src/grammar/README.md b/src/grammar/README.md
deleted file mode 100644
index 83808108ff8..00000000000
--- a/src/grammar/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Reference grammar.
-
-Uses [antlr4](http://www.antlr.org/) and a custom Rust tool to compare
-ASTs/token streams generated. You can use the `make check-lexer` target to
-run all of the available tests.
-
-The build of the rust part is included with `make tidy` and can be run with `make check-build-lexer-verifier`.
-
-# Manual build
-
-To use manually, assuming antlr4 is installed at `/usr/share/java/antlr-complete.jar`:
-
-```
-antlr4 RustLexer.g4
-javac -classpath /usr/share/java/antlr-complete.jar *.java
-rustc -O verify.rs
-for file in ../*/**.rs; do
-    echo $file;
-    grun RustLexer tokens -tokens < "$file" | ./verify "$file" RustLexer.tokens || break
-done
-```
-
-Note that the `../*/**.rs` glob will match every `*.rs` file in the above
-directory and all of its recursive children. This is a Zsh extension.
-
-
-## Cleanup
-
-To cleanup you can use a command like this:
-
-```bash
-rm -f verify *.class *.java *.tokens
-```
diff --git a/src/grammar/RustLexer.g4 b/src/grammar/RustLexer.g4
deleted file mode 100644
index a63fc59e50b..00000000000
--- a/src/grammar/RustLexer.g4
+++ /dev/null
@@ -1,197 +0,0 @@
-lexer grammar RustLexer;
-
-@lexer::members {
-  public boolean is_at(int pos) {
-    return _input.index() == pos;
-  }
-}
-
-
-tokens {
-    EQ, LT, LE, EQEQ, NE, GE, GT, ANDAND, OROR, NOT, TILDE, PLUS,
-    MINUS, STAR, SLASH, PERCENT, CARET, AND, OR, SHL, SHR, BINOP,
-    BINOPEQ, LARROW, AT, DOT, DOTDOT, DOTDOTDOT, COMMA, SEMI, COLON,
-    MOD_SEP, RARROW, FAT_ARROW, LPAREN, RPAREN, LBRACKET, RBRACKET,
-    LBRACE, RBRACE, POUND, DOLLAR, UNDERSCORE, LIT_CHAR, LIT_BYTE,
-    LIT_INTEGER, LIT_FLOAT, LIT_STR, LIT_STR_RAW, LIT_BYTE_STR,
-    LIT_BYTE_STR_RAW, QUESTION, IDENT, LIFETIME, WHITESPACE, DOC_COMMENT,
-    COMMENT, SHEBANG, UTF8_BOM
-}
-
-import xidstart , xidcontinue;
-
-
-/* Expression-operator symbols */
-
-EQ      : '=' ;
-LT      : '<' ;
-LE      : '<=' ;
-EQEQ    : '==' ;
-NE      : '!=' ;
-GE      : '>=' ;
-GT      : '>' ;
-ANDAND  : '&&' ;
-OROR    : '||' ;
-NOT     : '!' ;
-TILDE   : '~' ;
-PLUS    : '+' ;
-MINUS   : '-' ;
-STAR    : '*' ;
-SLASH   : '/' ;
-PERCENT : '%' ;
-CARET   : '^' ;
-AND     : '&' ;
-OR      : '|' ;
-SHL     : '<<' ;
-SHR     : '>>' ;
-LARROW  : '<-' ;
-
-BINOP
-    : PLUS
-    | SLASH
-    | MINUS
-    | STAR
-    | PERCENT
-    | CARET
-    | AND
-    | OR
-    | SHL
-    | SHR
-    | LARROW
-    ;
-
-BINOPEQ : BINOP EQ ;
-
-/* "Structural symbols" */
-
-AT         : '@' ;
-DOT        : '.' ;
-DOTDOT     : '..' ;
-DOTDOTDOT  : '...' ;
-COMMA      : ',' ;
-SEMI       : ';' ;
-COLON      : ':' ;
-MOD_SEP    : '::' ;
-RARROW     : '->' ;
-FAT_ARROW  : '=>' ;
-LPAREN     : '(' ;
-RPAREN     : ')' ;
-LBRACKET   : '[' ;
-RBRACKET   : ']' ;
-LBRACE     : '{' ;
-RBRACE     : '}' ;
-POUND      : '#';
-DOLLAR     : '$' ;
-UNDERSCORE : '_' ;
-
-// Literals
-
-fragment HEXIT
-  : [0-9a-fA-F]
-  ;
-
-fragment CHAR_ESCAPE
-  : [nrt\\'"0]
-  | [xX] HEXIT HEXIT
-  | 'u' HEXIT HEXIT HEXIT HEXIT
-  | 'U' HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT
-  | 'u{' HEXIT '}'
-  | 'u{' HEXIT HEXIT '}'
-  | 'u{' HEXIT HEXIT HEXIT '}'
-  | 'u{' HEXIT HEXIT HEXIT HEXIT '}'
-  | 'u{' HEXIT HEXIT HEXIT HEXIT HEXIT '}'
-  | 'u{' HEXIT HEXIT HEXIT HEXIT HEXIT HEXIT '}'
-  ;
-
-fragment SUFFIX
-  : IDENT
-  ;
-
-fragment INTEGER_SUFFIX
-  : { _input.LA(1) != 'e' && _input.LA(1) != 'E' }? SUFFIX
-  ;
-
-LIT_CHAR
-  : '\'' ( '\\' CHAR_ESCAPE
-         | ~[\\'\n\t\r]
-         | '\ud800' .. '\udbff' '\udc00' .. '\udfff'
-         )
-    '\'' SUFFIX?
-  ;
-
-LIT_BYTE
-  : 'b\'' ( '\\' ( [xX] HEXIT HEXIT
-                 | [nrt\\'"0] )
-          | ~[\\'\n\t\r] '\udc00'..'\udfff'?
-          )
-    '\'' SUFFIX?
-  ;
-
-LIT_INTEGER
-
-  : [0-9][0-9_]* INTEGER_SUFFIX?
-  | '0b' [01_]+ INTEGER_SUFFIX?
-  | '0o' [0-7_]+ INTEGER_SUFFIX?
-  | '0x' [0-9a-fA-F_]+ INTEGER_SUFFIX?
-  ;
-
-LIT_FLOAT
-  : [0-9][0-9_]* ('.' {
-        /* dot followed by another dot is a range, not a float */
-        _input.LA(1) != '.' &&
-        /* dot followed by an identifier is an integer with a function call, not a float */
-        _input.LA(1) != '_' &&
-        !(_input.LA(1) >= 'a' && _input.LA(1) <= 'z') &&
-        !(_input.LA(1) >= 'A' && _input.LA(1) <= 'Z')
-  }? | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
-  ;
-
-LIT_STR
-  : '"' ('\\\n' | '\\\r\n' | '\\' CHAR_ESCAPE | .)*? '"' SUFFIX?
-  ;
-
-LIT_BYTE_STR : 'b' LIT_STR ;
-LIT_BYTE_STR_RAW : 'b' LIT_STR_RAW ;
-
-/* this is a bit messy */
-
-fragment LIT_STR_RAW_INNER
-  : '"' .*? '"'
-  | LIT_STR_RAW_INNER2
-  ;
-
-fragment LIT_STR_RAW_INNER2
-  : POUND LIT_STR_RAW_INNER POUND
-  ;
-
-LIT_STR_RAW
-  : 'r' LIT_STR_RAW_INNER SUFFIX?
-  ;
-
-
-QUESTION : '?';
-
-IDENT : XID_Start XID_Continue* ;
-
-fragment QUESTION_IDENTIFIER : QUESTION? IDENT;
-
-LIFETIME : '\'' IDENT ;
-
-WHITESPACE : [ \r\n\t]+ ;
-
-UNDOC_COMMENT     : '////' ~[\n]* -> type(COMMENT) ;
-YESDOC_COMMENT    : '///' ~[\r\n]* -> type(DOC_COMMENT) ;
-OUTER_DOC_COMMENT : '//!' ~[\r\n]* -> type(DOC_COMMENT) ;
-LINE_COMMENT      : '//' ( ~[/\n] ~[\n]* )? -> type(COMMENT) ;
-
-DOC_BLOCK_COMMENT
-  : ('/**' ~[*] | '/*!') (DOC_BLOCK_COMMENT | .)*? '*/' -> type(DOC_COMMENT)
-  ;
-
-BLOCK_COMMENT : '/*' (BLOCK_COMMENT | .)*? '*/' -> type(COMMENT) ;
-
-/* these appear at the beginning of a file */
-
-SHEBANG : '#!' { is_at(2) && _input.LA(1) != '[' }? ~[\r\n]* -> type(SHEBANG) ;
-
-UTF8_BOM : '\ufeff' { is_at(1) }? -> skip ;
diff --git a/src/grammar/check.sh b/src/grammar/check.sh
deleted file mode 100755
index 70a8f6fca2e..00000000000
--- a/src/grammar/check.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-
-# ignore-license
-
-# Run the reference lexer against libsyntax and compare the tokens and spans.
-# If "// ignore-lexer-test" is present in the file, it will be ignored.
-
-
-# Argument $1 is the file to check, $2 is the classpath to use, $3 is the path
-# to the grun binary, $4 is the path to the verify binary, $5 is the path to
-# RustLexer.tokens
-if [ "${VERBOSE}" == "1" ]; then
-    set -x
-fi
-
-passed=0
-failed=0
-skipped=0
-
-check() {
-    grep --silent "// ignore-lexer-test" "$1";
-
-    # if it is *not* found...
-    if [ $? -eq 1 ]; then
-        cd $2 # This `cd` is so java will pick up RustLexer.class. I could not
-        # figure out how to wrangle the CLASSPATH, just adding build/grammar
-        # did not seem to have any effect.
-        if $3 RustLexer tokens -tokens < $1 | $4 $1 $5; then
-            echo "pass: $1"
-            passed=`expr $passed + 1`
-        else
-            echo "fail: $1"
-            failed=`expr $failed + 1`
-        fi
-    else
-        echo "skip: $1"
-        skipped=`expr $skipped + 1`
-    fi
-}
-
-for file in $(find $1 -iname '*.rs' ! -path '*/test/compile-fail*'); do
-    check "$file" $2 $3 $4 $5
-done
-
-printf "\ntest result: "
-
-if [ $failed -eq 0 ]; then
-    printf "ok. $passed passed; $failed failed; $skipped skipped\n\n"
-else
-    printf "failed. $passed passed; $failed failed; $skipped skipped\n\n"
-    exit 1
-fi
diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l
deleted file mode 100644
index 77737c99496..00000000000
--- a/src/grammar/lexer.l
+++ /dev/null
@@ -1,343 +0,0 @@
-%{
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#include <stdio.h>
-#include <ctype.h>
-
-static int num_hashes;
-static int end_hashes;
-static int saw_non_hash;
-
-%}
-
-%option stack
-%option yylineno
-
-%x str
-%x rawstr
-%x rawstr_esc_begin
-%x rawstr_esc_body
-%x rawstr_esc_end
-%x byte
-%x bytestr
-%x rawbytestr
-%x rawbytestr_nohash
-%x pound
-%x shebang_or_attr
-%x ltorchar
-%x linecomment
-%x doc_line
-%x blockcomment
-%x doc_block
-%x suffix
-
-ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]*
-
-%%
-
-<suffix>{ident}            { BEGIN(INITIAL); }
-<suffix>(.|\n)  { yyless(0); BEGIN(INITIAL); }
-
-[ \n\t\r]             { }
-
-\xef\xbb\xbf {
-  // UTF-8 byte order mark (BOM), ignore if in line 1, error otherwise
-  if (yyget_lineno() != 1) {
-    return -1;
-  }
-}
-
-\/\/(\/|\!)           { BEGIN(doc_line); yymore(); }
-<doc_line>\n          { BEGIN(INITIAL);
-                        yyleng--;
-                        yytext[yyleng] = 0;
-                        return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
-                      }
-<doc_line>[^\n]*      { yymore(); }
-
-\/\/|\/\/\/\/         { BEGIN(linecomment); }
-<linecomment>\n       { BEGIN(INITIAL); }
-<linecomment>[^\n]*   { }
-
-\/\*(\*|\!)[^*]       { yy_push_state(INITIAL); yy_push_state(doc_block); yymore(); }
-<doc_block>\/\*       { yy_push_state(doc_block); yymore(); }
-<doc_block>\*\/       {
-    yy_pop_state();
-    if (yy_top_state() == doc_block) {
-        yymore();
-    } else {
-        return ((yytext[2] == '!') ? INNER_DOC_COMMENT : OUTER_DOC_COMMENT);
-    }
-}
-<doc_block>(.|\n)     { yymore(); }
-
-\/\*                  { yy_push_state(blockcomment); }
-<blockcomment>\/\*    { yy_push_state(blockcomment); }
-<blockcomment>\*\/    { yy_pop_state(); }
-<blockcomment>(.|\n)   { }
-
-_        { return UNDERSCORE; }
-as       { return AS; }
-box      { return BOX; }
-break    { return BREAK; }
-const    { return CONST; }
-continue { return CONTINUE; }
-crate    { return CRATE; }
-else     { return ELSE; }
-enum     { return ENUM; }
-extern   { return EXTERN; }
-false    { return FALSE; }
-fn       { return FN; }
-for      { return FOR; }
-if       { return IF; }
-impl     { return IMPL; }
-in       { return IN; }
-let      { return LET; }
-loop     { return LOOP; }
-match    { return MATCH; }
-mod      { return MOD; }
-move     { return MOVE; }
-mut      { return MUT; }
-priv     { return PRIV; }
-proc     { return PROC; }
-pub      { return PUB; }
-ref      { return REF; }
-return   { return RETURN; }
-self     { return SELF; }
-static   { return STATIC; }
-struct   { return STRUCT; }
-trait    { return TRAIT; }
-true     { return TRUE; }
-type     { return TYPE; }
-typeof   { return TYPEOF; }
-unsafe   { return UNSAFE; }
-use      { return USE; }
-where    { return WHERE; }
-while    { return WHILE; }
-
-{ident}  { return IDENT; }
-
-0x[0-9a-fA-F_]+                                    { BEGIN(suffix); return LIT_INTEGER; }
-0o[0-8_]+                                          { BEGIN(suffix); return LIT_INTEGER; }
-0b[01_]+                                           { BEGIN(suffix); return LIT_INTEGER; }
-[0-9][0-9_]*                                       { BEGIN(suffix); return LIT_INTEGER; }
-[0-9][0-9_]*\.(\.|[a-zA-Z])    { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; }
-
-[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)?          { BEGIN(suffix); return LIT_FLOAT; }
-[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+          { BEGIN(suffix); return LIT_FLOAT; }
-
-;      { return ';'; }
-,      { return ','; }
-\.\.\. { return DOTDOTDOT; }
-\.\.   { return DOTDOT; }
-\.     { return '.'; }
-\(     { return '('; }
-\)     { return ')'; }
-\{     { return '{'; }
-\}     { return '}'; }
-\[     { return '['; }
-\]     { return ']'; }
-@      { return '@'; }
-#      { BEGIN(pound); yymore(); }
-<pound>\! { BEGIN(shebang_or_attr); yymore(); }
-<shebang_or_attr>\[ {
-  BEGIN(INITIAL);
-  yyless(2);
-  return SHEBANG;
-}
-<shebang_or_attr>[^\[\n]*\n {
-  // Since the \n was eaten as part of the token, yylineno will have
-  // been incremented to the value 2 if the shebang was on the first
-  // line. This yyless undoes that, setting yylineno back to 1.
-  yyless(yyleng - 1);
-  if (yyget_lineno() == 1) {
-    BEGIN(INITIAL);
-    return SHEBANG_LINE;
-  } else {
-    BEGIN(INITIAL);
-    yyless(2);
-    return SHEBANG;
-  }
-}
-<pound>. { BEGIN(INITIAL); yyless(1); return '#'; }
-
-\~     { return '~'; }
-::     { return MOD_SEP; }
-:      { return ':'; }
-\$     { return '$'; }
-\?     { return '?'; }
-
-==    { return EQEQ; }
-=>    { return FAT_ARROW; }
-=     { return '='; }
-\!=   { return NE; }
-\!    { return '!'; }
-\<=   { return LE; }
-\<\<  { return SHL; }
-\<\<= { return SHLEQ; }
-\<    { return '<'; }
-\>=   { return GE; }
-\>\>  { return SHR; }
-\>\>= { return SHREQ; }
-\>    { return '>'; }
-
-\x27                                  { BEGIN(ltorchar); yymore(); }
-<ltorchar>static                      { BEGIN(INITIAL); return STATIC_LIFETIME; }
-<ltorchar>{ident}                     { BEGIN(INITIAL); return LIFETIME; }
-<ltorchar>\\[nrt\\\x27\x220]\x27      { BEGIN(suffix); return LIT_CHAR; }
-<ltorchar>\\x[0-9a-fA-F]{2}\x27       { BEGIN(suffix); return LIT_CHAR; }
-<ltorchar>\\u\{[0-9a-fA-F]?{6}\}\x27  { BEGIN(suffix); return LIT_CHAR; }
-<ltorchar>.\x27                       { BEGIN(suffix); return LIT_CHAR; }
-<ltorchar>[\x80-\xff]{2,4}\x27        { BEGIN(suffix); return LIT_CHAR; }
-<ltorchar><<EOF>>                     { BEGIN(INITIAL); return -1; }
-
-b\x22              { BEGIN(bytestr); yymore(); }
-<bytestr>\x22      { BEGIN(suffix); return LIT_BYTE_STR; }
-
-<bytestr><<EOF>>                { return -1; }
-<bytestr>\\[n\nrt\\\x27\x220]   { yymore(); }
-<bytestr>\\x[0-9a-fA-F]{2}      { yymore(); }
-<bytestr>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
-<bytestr>\\[^n\nrt\\\x27\x220]  { return -1; }
-<bytestr>(.|\n)                 { yymore(); }
-
-br\x22                      { BEGIN(rawbytestr_nohash); yymore(); }
-<rawbytestr_nohash>\x22     { BEGIN(suffix); return LIT_BYTE_STR_RAW; }
-<rawbytestr_nohash>(.|\n)   { yymore(); }
-<rawbytestr_nohash><<EOF>>  { return -1; }
-
-br/# {
-    BEGIN(rawbytestr);
-    yymore();
-    num_hashes = 0;
-    saw_non_hash = 0;
-    end_hashes = 0;
-}
-<rawbytestr># {
-    if (!saw_non_hash) {
-        num_hashes++;
-    } else if (end_hashes != 0) {
-        end_hashes++;
-        if (end_hashes == num_hashes) {
-            BEGIN(INITIAL);
-            return LIT_BYTE_STR_RAW;
-        }
-    }
-    yymore();
-}
-<rawbytestr>\x22# {
-    end_hashes = 1;
-    if (end_hashes == num_hashes) {
-        BEGIN(INITIAL);
-        return LIT_BYTE_STR_RAW;
-    }
-    yymore();
-}
-<rawbytestr>(.|\n) {
-    if (!saw_non_hash) {
-        saw_non_hash = 1;
-    }
-    if (end_hashes != 0) {
-        end_hashes = 0;
-    }
-    yymore();
-}
-<rawbytestr><<EOF>> { return -1; }
-
-b\x27                        { BEGIN(byte); yymore(); }
-<byte>\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; }
-<byte>\\x[0-9a-fA-F]{2}\x27  { BEGIN(INITIAL); return LIT_BYTE; }
-<byte>\\u[0-9a-fA-F]{4}\x27  { BEGIN(INITIAL); return LIT_BYTE; }
-<byte>\\U[0-9a-fA-F]{8}\x27  { BEGIN(INITIAL); return LIT_BYTE; }
-<byte>.\x27                  { BEGIN(INITIAL); return LIT_BYTE; }
-<byte><<EOF>>                { BEGIN(INITIAL); return -1; }
-
-r\x22           { BEGIN(rawstr); yymore(); }
-<rawstr>\x22    { BEGIN(suffix); return LIT_STR_RAW; }
-<rawstr>(.|\n)  { yymore(); }
-<rawstr><<EOF>> { return -1; }
-
-r/#             {
-    BEGIN(rawstr_esc_begin);
-    yymore();
-    num_hashes = 0;
-    saw_non_hash = 0;
-    end_hashes = 0;
-}
-
-<rawstr_esc_begin># {
-    num_hashes++;
-    yymore();
-}
-<rawstr_esc_begin>\x22 {
-    BEGIN(rawstr_esc_body);
-    yymore();
-}
-<rawstr_esc_begin>(.|\n) { return -1; }
-
-<rawstr_esc_body>\x22/# {
-  BEGIN(rawstr_esc_end);
-  yymore();
- }
-<rawstr_esc_body>(.|\n) {
-  yymore();
- }
-
-<rawstr_esc_end># {
-  end_hashes++;
-  if (end_hashes == num_hashes) {
-    BEGIN(INITIAL);
-    return LIT_STR_RAW;
-  }
-  yymore();
- }
-<rawstr_esc_end>[^#] {
-  end_hashes = 0;
-  BEGIN(rawstr_esc_body);
-  yymore();
- }
-
-<rawstr_esc_begin,rawstr_esc_body,rawstr_esc_end><<EOF>> { return -1; }
-
-\x22                     { BEGIN(str); yymore(); }
-<str>\x22                { BEGIN(suffix); return LIT_STR; }
-
-<str><<EOF>>                { return -1; }
-<str>\\[n\nr\rt\\\x27\x220] { yymore(); }
-<str>\\x[0-9a-fA-F]{2}      { yymore(); }
-<str>\\u\{[0-9a-fA-F]?{6}\} { yymore(); }
-<str>\\[^n\nrt\\\x27\x220]  { return -1; }
-<str>(.|\n)                 { yymore(); }
-
-\<-  { return LARROW; }
--\>  { return RARROW; }
--    { return '-'; }
--=   { return MINUSEQ; }
-&&   { return ANDAND; }
-&    { return '&'; }
-&=   { return ANDEQ; }
-\|\| { return OROR; }
-\|   { return '|'; }
-\|=  { return OREQ; }
-\+   { return '+'; }
-\+=  { return PLUSEQ; }
-\*   { return '*'; }
-\*=  { return STAREQ; }
-\/   { return '/'; }
-\/=  { return SLASHEQ; }
-\^   { return '^'; }
-\^=  { return CARETEQ; }
-%    { return '%'; }
-%=   { return PERCENTEQ; }
-
-<<EOF>> { return 0; }
-
-%%
diff --git a/src/grammar/parser-lalr-main.c b/src/grammar/parser-lalr-main.c
deleted file mode 100644
index db88a1f2999..00000000000
--- a/src/grammar/parser-lalr-main.c
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern int yylex();
-extern int rsparse();
-
-#define PUSHBACK_LEN 4
-
-static char pushback[PUSHBACK_LEN];
-static int verbose;
-
-void print(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  if (verbose) {
-    vprintf(format, args);
-  }
-  va_end(args);
-}
-
-// If there is a non-null char at the head of the pushback queue,
-// dequeue it and shift the rest of the queue forwards. Otherwise,
-// return the token from calling yylex.
-int rslex() {
-  if (pushback[0] == '\0') {
-    return yylex();
-  } else {
-    char c = pushback[0];
-    memmove(pushback, pushback + 1, PUSHBACK_LEN - 1);
-    pushback[PUSHBACK_LEN - 1] = '\0';
-    return c;
-  }
-}
-
-// Note: this does nothing if the pushback queue is full. As long as
-// there aren't more than PUSHBACK_LEN consecutive calls to push_back
-// in an action, this shouldn't be a problem.
-void push_back(char c) {
-  for (int i = 0; i < PUSHBACK_LEN; ++i) {
-    if (pushback[i] == '\0') {
-      pushback[i] = c;
-      break;
-    }
-  }
-}
-
-extern int rsdebug;
-
-struct node {
-  struct node *next;
-  struct node *prev;
-  int own_string;
-  char const *name;
-  int n_elems;
-  struct node *elems[];
-};
-
-struct node *nodes = NULL;
-int n_nodes;
-
-struct node *mk_node(char const *name, int n, ...) {
-  va_list ap;
-  int i = 0;
-  unsigned sz = sizeof(struct node) + (n * sizeof(struct node *));
-  struct node *nn, *nd = (struct node *)malloc(sz);
-
-  print("# New %d-ary node: %s = %p\n", n, name, nd);
-
-  nd->own_string = 0;
-  nd->prev = NULL;
-  nd->next = nodes;
-  if (nodes) {
-    nodes->prev = nd;
-  }
-  nodes = nd;
-
-  nd->name = name;
-  nd->n_elems = n;
-
-  va_start(ap, n);
-  while (i < n) {
-    nn = va_arg(ap, struct node *);
-    print("#   arg[%d]: %p\n", i, nn);
-    print("#            (%s ...)\n", nn->name);
-    nd->elems[i++] = nn;
-  }
-  va_end(ap);
-  n_nodes++;
-  return nd;
-}
-
-struct node *mk_atom(char *name) {
-  struct node *nd = mk_node((char const *)strdup(name), 0);
-  nd->own_string = 1;
-  return nd;
-}
-
-struct node *mk_none() {
-  return mk_atom("<none>");
-}
-
-struct node *ext_node(struct node *nd, int n, ...) {
-  va_list ap;
-  int i = 0, c = nd->n_elems + n;
-  unsigned sz = sizeof(struct node) + (c * sizeof(struct node *));
-  struct node *nn;
-
-  print("# Extending %d-ary node by %d nodes: %s = %p",
-        nd->n_elems, c, nd->name, nd);
-
-  if (nd->next) {
-    nd->next->prev = nd->prev;
-  }
-  if (nd->prev) {
-    nd->prev->next = nd->next;
-  }
-  nd = realloc(nd, sz);
-  nd->prev = NULL;
-  nd->next = nodes;
-  nodes->prev = nd;
-  nodes = nd;
-
-  print(" ==> %p\n", nd);
-
-  va_start(ap, n);
-  while (i < n) {
-    nn = va_arg(ap, struct node *);
-    print("#   arg[%d]: %p\n", i, nn);
-    print("#            (%s ...)\n", nn->name);
-    nd->elems[nd->n_elems++] = nn;
-    ++i;
-  }
-  va_end(ap);
-  return nd;
-}
-
-int const indent_step = 4;
-
-void print_indent(int depth) {
-  while (depth) {
-    if (depth-- % indent_step == 0) {
-      print("|");
-    } else {
-      print(" ");
-    }
-  }
-}
-
-void print_node(struct node *n, int depth) {
-  int i = 0;
-  print_indent(depth);
-  if (n->n_elems == 0) {
-    print("%s\n", n->name);
-  } else {
-    print("(%s\n", n->name);
-    for (i = 0; i < n->n_elems; ++i) {
-      print_node(n->elems[i], depth + indent_step);
-    }
-    print_indent(depth);
-    print(")\n");
-  }
-}
-
-int main(int argc, char **argv) {
-  if (argc == 2 && strcmp(argv[1], "-v") == 0) {
-    verbose = 1;
-  } else {
-    verbose = 0;
-  }
-  int ret = 0;
-  struct node *tmp;
-  memset(pushback, '\0', PUSHBACK_LEN);
-  ret = rsparse();
-  print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes);
-  if (nodes) {
-    print_node(nodes, 0);
-  }
-  while (nodes) {
-    tmp = nodes;
-    nodes = tmp->next;
-    if (tmp->own_string) {
-      free((void*)tmp->name);
-    }
-    free(tmp);
-  }
-  return ret;
-}
-
-void rserror(char const *s) {
-  fprintf(stderr, "%s\n", s);
-}
diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y
deleted file mode 100644
index c9fcdf7647b..00000000000
--- a/src/grammar/parser-lalr.y
+++ /dev/null
@@ -1,1945 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-%{
-#define YYERROR_VERBOSE
-#define YYSTYPE struct node *
-struct node;
-extern int yylex();
-extern void yyerror(char const *s);
-extern struct node *mk_node(char const *name, int n, ...);
-extern struct node *mk_atom(char *text);
-extern struct node *mk_none();
-extern struct node *ext_node(struct node *nd, int n, ...);
-extern void push_back(char c);
-extern char *yytext;
-%}
-%debug
-
-%token SHL
-%token SHR
-%token LE
-%token EQEQ
-%token NE
-%token GE
-%token ANDAND
-%token OROR
-%token SHLEQ
-%token SHREQ
-%token MINUSEQ
-%token ANDEQ
-%token OREQ
-%token PLUSEQ
-%token STAREQ
-%token SLASHEQ
-%token CARETEQ
-%token PERCENTEQ
-%token DOTDOT
-%token DOTDOTDOT
-%token MOD_SEP
-%token RARROW
-%token LARROW
-%token FAT_ARROW
-%token LIT_BYTE
-%token LIT_CHAR
-%token LIT_INTEGER
-%token LIT_FLOAT
-%token LIT_STR
-%token LIT_STR_RAW
-%token LIT_BYTE_STR
-%token LIT_BYTE_STR_RAW
-%token IDENT
-%token UNDERSCORE
-%token LIFETIME
-
-// keywords
-%token SELF
-%token STATIC
-%token AS
-%token BREAK
-%token CRATE
-%token ELSE
-%token ENUM
-%token EXTERN
-%token FALSE
-%token FN
-%token FOR
-%token IF
-%token IMPL
-%token IN
-%token LET
-%token LOOP
-%token MATCH
-%token MOD
-%token MOVE
-%token MUT
-%token PRIV
-%token PUB
-%token REF
-%token RETURN
-%token STRUCT
-%token TRUE
-%token TRAIT
-%token TYPE
-%token UNSAFE
-%token DEFAULT
-%token USE
-%token WHILE
-%token CONTINUE
-%token PROC
-%token BOX
-%token CONST
-%token WHERE
-%token TYPEOF
-%token INNER_DOC_COMMENT
-%token OUTER_DOC_COMMENT
-
-%token SHEBANG
-%token SHEBANG_LINE
-%token STATIC_LIFETIME
-
- /*
-   Quoting from the Bison manual:
-
-   "Finally, the resolution of conflicts works by comparing the precedence
-   of the rule being considered with that of the lookahead token. If the
-   token's precedence is higher, the choice is to shift. If the rule's
-   precedence is higher, the choice is to reduce. If they have equal
-   precedence, the choice is made based on the associativity of that
-   precedence level. The verbose output file made by ‘-v’ (see Invoking
-   Bison) says how each conflict was resolved"
- */
-
-// We expect no shift/reduce or reduce/reduce conflicts in this grammar;
-// all potential ambiguities are scrutinized and eliminated manually.
-%expect 0
-
-// fake-precedence symbol to cause '|' bars in lambda context to parse
-// at low precedence, permit things like |x| foo = bar, where '=' is
-// otherwise lower-precedence than '|'. Also used for proc() to cause
-// things like proc() a + b to parse as proc() { a + b }.
-%precedence LAMBDA
-
-%precedence SELF
-
-// MUT should be lower precedence than IDENT so that in the pat rule,
-// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]"
-%precedence MUT
-
-// IDENT needs to be lower than '{' so that 'foo {' is shifted when
-// trying to decide if we've got a struct-construction expr (esp. in
-// contexts like 'if foo { .')
-//
-// IDENT also needs to be lower precedence than '<' so that '<' in
-// 'foo:bar . <' is shifted (in a trait reference occurring in a
-// bounds list), parsing as foo:(bar<baz>) rather than (foo:bar)<baz>.
-%precedence IDENT
-
-// A couple fake-precedence symbols to use in rules associated with +
-// and < in trailing type contexts. These come up when you have a type
-// in the RHS of operator-AS, such as "foo as bar<baz>". The "<" there
-// has to be shifted so the parser keeps trying to parse a type, even
-// though it might well consider reducing the type "bar" and then
-// going on to "<" as a subsequent binop. The "+" case is with
-// trailing type-bounds ("foo as bar:A+B"), for the same reason.
-%precedence SHIFTPLUS
-
-%precedence MOD_SEP
-%precedence RARROW ':'
-
-// In where clauses, "for" should have greater precedence when used as
-// a higher ranked constraint than when used as the beginning of a
-// for_in_type (which is a ty)
-%precedence FORTYPE
-%precedence FOR
-
-// Binops & unops, and their precedences
-%precedence BOX
-%precedence BOXPLACE
-%nonassoc DOTDOT
-
-// RETURN needs to be lower-precedence than tokens that start
-// prefix_exprs
-%precedence RETURN
-
-%right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ
-%right LARROW
-%left OROR
-%left ANDAND
-%left EQEQ NE
-%left '<' '>' LE GE
-%left '|'
-%left '^'
-%left '&'
-%left SHL SHR
-%left '+' '-'
-%precedence AS
-%left '*' '/' '%'
-%precedence '!'
-
-%precedence '{' '[' '(' '.'
-
-%precedence RANGE
-
-%start crate
-
-%%
-
-////////////////////////////////////////////////////////////////////////
-// Part 1: Items and attributes
-////////////////////////////////////////////////////////////////////////
-
-crate
-: maybe_shebang inner_attrs maybe_mod_items  { mk_node("crate", 2, $2, $3); }
-| maybe_shebang maybe_mod_items  { mk_node("crate", 1, $2); }
-;
-
-maybe_shebang
-: SHEBANG_LINE
-| %empty
-;
-
-maybe_inner_attrs
-: inner_attrs
-| %empty                   { $$ = mk_none(); }
-;
-
-inner_attrs
-: inner_attr               { $$ = mk_node("InnerAttrs", 1, $1); }
-| inner_attrs inner_attr   { $$ = ext_node($1, 1, $2); }
-;
-
-inner_attr
-: SHEBANG '[' meta_item ']'   { $$ = mk_node("InnerAttr", 1, $3); }
-| INNER_DOC_COMMENT           { $$ = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); }
-;
-
-maybe_outer_attrs
-: outer_attrs
-| %empty                   { $$ = mk_none(); }
-;
-
-outer_attrs
-: outer_attr               { $$ = mk_node("OuterAttrs", 1, $1); }
-| outer_attrs outer_attr   { $$ = ext_node($1, 1, $2); }
-;
-
-outer_attr
-: '#' '[' meta_item ']'    { $$ = $3; }
-| OUTER_DOC_COMMENT        { $$ = mk_node("doc-comment", 1, mk_atom(yytext)); }
-;
-
-meta_item
-: ident                      { $$ = mk_node("MetaWord", 1, $1); }
-| ident '=' lit              { $$ = mk_node("MetaNameValue", 2, $1, $3); }
-| ident '(' meta_seq ')'     { $$ = mk_node("MetaList", 2, $1, $3); }
-| ident '(' meta_seq ',' ')' { $$ = mk_node("MetaList", 2, $1, $3); }
-;
-
-meta_seq
-: %empty                   { $$ = mk_none(); }
-| meta_item                { $$ = mk_node("MetaItems", 1, $1); }
-| meta_seq ',' meta_item   { $$ = ext_node($1, 1, $3); }
-;
-
-maybe_mod_items
-: mod_items
-| %empty             { $$ = mk_none(); }
-;
-
-mod_items
-: mod_item                               { $$ = mk_node("Items", 1, $1); }
-| mod_items mod_item                     { $$ = ext_node($1, 1, $2); }
-;
-
-attrs_and_vis
-: maybe_outer_attrs visibility           { $$ = mk_node("AttrsAndVis", 2, $1, $2); }
-;
-
-mod_item
-: attrs_and_vis item    { $$ = mk_node("Item", 2, $1, $2); }
-;
-
-// items that can appear outside of a fn block
-item
-: stmt_item
-| item_macro
-;
-
-// items that can appear in "stmts"
-stmt_item
-: item_static
-| item_const
-| item_type
-| block_item
-| view_item
-;
-
-item_static
-: STATIC ident ':' ty '=' expr ';'  { $$ = mk_node("ItemStatic", 3, $2, $4, $6); }
-| STATIC MUT ident ':' ty '=' expr ';'  { $$ = mk_node("ItemStatic", 3, $3, $5, $7); }
-;
-
-item_const
-: CONST ident ':' ty '=' expr ';'  { $$ = mk_node("ItemConst", 3, $2, $4, $6); }
-;
-
-item_macro
-: path_expr '!' maybe_ident parens_delimited_token_trees ';'  { $$ = mk_node("ItemMacro", 3, $1, $3, $4); }
-| path_expr '!' maybe_ident braces_delimited_token_trees      { $$ = mk_node("ItemMacro", 3, $1, $3, $4); }
-| path_expr '!' maybe_ident brackets_delimited_token_trees ';'{ $$ = mk_node("ItemMacro", 3, $1, $3, $4); }
-;
-
-view_item
-: use_item
-| extern_fn_item
-| EXTERN CRATE ident ';'                      { $$ = mk_node("ViewItemExternCrate", 1, $3); }
-| EXTERN CRATE ident AS ident ';'             { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); }
-;
-
-extern_fn_item
-: EXTERN maybe_abi item_fn                    { $$ = mk_node("ViewItemExternFn", 2, $2, $3); }
-;
-
-use_item
-: USE view_path ';'                           { $$ = mk_node("ViewItemUse", 1, $2); }
-;
-
-view_path
-: path_no_types_allowed                                    { $$ = mk_node("ViewPathSimple", 1, $1); }
-| path_no_types_allowed MOD_SEP '{'                '}'     { $$ = mk_node("ViewPathList", 2, $1, mk_atom("ViewPathListEmpty")); }
-|                       MOD_SEP '{'                '}'     { $$ = mk_node("ViewPathList", 1, mk_atom("ViewPathListEmpty")); }
-| path_no_types_allowed MOD_SEP '{' idents_or_self '}'     { $$ = mk_node("ViewPathList", 2, $1, $4); }
-|                       MOD_SEP '{' idents_or_self '}'     { $$ = mk_node("ViewPathList", 1, $3); }
-| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); }
-|                       MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $3); }
-| path_no_types_allowed MOD_SEP '*'                        { $$ = mk_node("ViewPathGlob", 1, $1); }
-|                               '{'                '}'     { $$ = mk_atom("ViewPathListEmpty"); }
-|                               '{' idents_or_self '}'     { $$ = mk_node("ViewPathList", 1, $2); }
-|                               '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); }
-| path_no_types_allowed AS ident                           { $$ = mk_node("ViewPathSimple", 2, $1, $3); }
-;
-
-block_item
-: item_fn
-| item_unsafe_fn
-| item_mod
-| item_foreign_mod          { $$ = mk_node("ItemForeignMod", 1, $1); }
-| item_struct
-| item_enum
-| item_trait
-| item_impl
-;
-
-maybe_ty_ascription
-: ':' ty_sum { $$ = $2; }
-| %empty { $$ = mk_none(); }
-;
-
-maybe_init_expr
-: '=' expr { $$ = $2; }
-| %empty   { $$ = mk_none(); }
-;
-
-// structs
-item_struct
-: STRUCT ident generic_params maybe_where_clause struct_decl_args
-{
-  $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5);
-}
-| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';'
-{
-  $$ = mk_node("ItemStruct", 4, $2, $3, $4, $5);
-}
-| STRUCT ident generic_params maybe_where_clause ';'
-{
-  $$ = mk_node("ItemStruct", 3, $2, $3, $4);
-}
-;
-
-struct_decl_args
-: '{' struct_decl_fields '}'                  { $$ = $2; }
-| '{' struct_decl_fields ',' '}'              { $$ = $2; }
-;
-
-struct_tuple_args
-: '(' struct_tuple_fields ')'                 { $$ = $2; }
-| '(' struct_tuple_fields ',' ')'             { $$ = $2; }
-;
-
-struct_decl_fields
-: struct_decl_field                           { $$ = mk_node("StructFields", 1, $1); }
-| struct_decl_fields ',' struct_decl_field    { $$ = ext_node($1, 1, $3); }
-| %empty                                      { $$ = mk_none(); }
-;
-
-struct_decl_field
-: attrs_and_vis ident ':' ty_sum              { $$ = mk_node("StructField", 3, $1, $2, $4); }
-;
-
-struct_tuple_fields
-: struct_tuple_field                          { $$ = mk_node("StructFields", 1, $1); }
-| struct_tuple_fields ',' struct_tuple_field  { $$ = ext_node($1, 1, $3); }
-;
-
-struct_tuple_field
-: attrs_and_vis ty_sum                    { $$ = mk_node("StructField", 2, $1, $2); }
-;
-
-// enums
-item_enum
-: ENUM ident generic_params maybe_where_clause '{' enum_defs '}'     { $$ = mk_node("ItemEnum", 0); }
-| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node("ItemEnum", 0); }
-;
-
-enum_defs
-: enum_def               { $$ = mk_node("EnumDefs", 1, $1); }
-| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); }
-| %empty                 { $$ = mk_none(); }
-;
-
-enum_def
-: attrs_and_vis ident enum_args { $$ = mk_node("EnumDef", 3, $1, $2, $3); }
-;
-
-enum_args
-: '{' struct_decl_fields '}'     { $$ = mk_node("EnumArgs", 1, $2); }
-| '{' struct_decl_fields ',' '}' { $$ = mk_node("EnumArgs", 1, $2); }
-| '(' maybe_ty_sums ')'          { $$ = mk_node("EnumArgs", 1, $2); }
-| '=' expr                       { $$ = mk_node("EnumArgs", 1, $2); }
-| %empty                         { $$ = mk_none(); }
-;
-
-item_mod
-: MOD ident ';'                                 { $$ = mk_node("ItemMod", 1, $2); }
-| MOD ident '{' maybe_mod_items '}'             { $$ = mk_node("ItemMod", 2, $2, $4); }
-| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node("ItemMod", 3, $2, $4, $5); }
-;
-
-item_foreign_mod
-: EXTERN maybe_abi '{' maybe_foreign_items '}'             { $$ = mk_node("ItemForeignMod", 1, $4); }
-| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 2, $4, $5); }
-;
-
-maybe_abi
-: str
-| %empty { $$ = mk_none(); }
-;
-
-maybe_foreign_items
-: foreign_items
-| %empty { $$ = mk_none(); }
-;
-
-foreign_items
-: foreign_item               { $$ = mk_node("ForeignItems", 1, $1); }
-| foreign_items foreign_item { $$ = ext_node($1, 1, $2); }
-;
-
-foreign_item
-: attrs_and_vis STATIC item_foreign_static { $$ = mk_node("ForeignItem", 2, $1, $3); }
-| attrs_and_vis item_foreign_fn            { $$ = mk_node("ForeignItem", 2, $1, $2); }
-| attrs_and_vis UNSAFE item_foreign_fn     { $$ = mk_node("ForeignItem", 2, $1, $3); }
-;
-
-item_foreign_static
-: maybe_mut ident ':' ty ';'               { $$ = mk_node("StaticItem", 3, $1, $2, $4); }
-;
-
-item_foreign_fn
-: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node("ForeignFn", 4, $2, $3, $4, $5); }
-;
-
-fn_decl_allow_variadic
-: fn_params_allow_variadic ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); }
-;
-
-fn_params_allow_variadic
-: '(' ')'                      { $$ = mk_none(); }
-| '(' params ')'               { $$ = $2; }
-| '(' params ',' ')'           { $$ = $2; }
-| '(' params ',' DOTDOTDOT ')' { $$ = $2; }
-;
-
-visibility
-: PUB      { $$ = mk_atom("Public"); }
-| %empty   { $$ = mk_atom("Inherited"); }
-;
-
-idents_or_self
-: ident_or_self                    { $$ = mk_node("IdentsOrSelf", 1, $1); }
-| ident_or_self AS ident           { $$ = mk_node("IdentsOrSelf", 2, $1, $3); }
-| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); }
-;
-
-ident_or_self
-: ident
-| SELF  { $$ = mk_atom(yytext); }
-;
-
-item_type
-: TYPE ident generic_params maybe_where_clause '=' ty_sum ';'  { $$ = mk_node("ItemTy", 4, $2, $3, $4, $6); }
-;
-
-for_sized
-: FOR '?' ident { $$ = mk_node("ForSized", 1, $3); }
-| FOR ident '?' { $$ = mk_node("ForSized", 1, $2); }
-| %empty        { $$ = mk_none(); }
-;
-
-item_trait
-: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}'
-{
-  $$ = mk_node("ItemTrait", 7, $1, $3, $4, $5, $6, $7, $9);
-}
-;
-
-maybe_trait_items
-: trait_items
-| %empty { $$ = mk_none(); }
-;
-
-trait_items
-: trait_item               { $$ = mk_node("TraitItems", 1, $1); }
-| trait_items trait_item   { $$ = ext_node($1, 1, $2); }
-;
-
-trait_item
-: trait_const
-| trait_type
-| trait_method
-;
-
-trait_const
-: maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 4, $1, $3, $4, $5); }
-;
-
-maybe_const_default
-: '=' expr { $$ = mk_node("ConstDefault", 1, $2); }
-| %empty   { $$ = mk_none(); }
-;
-
-trait_type
-: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); }
-;
-
-maybe_unsafe
-: UNSAFE { $$ = mk_atom("Unsafe"); }
-| %empty { $$ = mk_none(); }
-;
-
-maybe_default_maybe_unsafe
-: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
-| DEFAULT        { $$ = mk_atom("Default"); }
-|         UNSAFE { $$ = mk_atom("Unsafe"); }
-| %empty { $$ = mk_none(); }
-
-trait_method
-: type_method { $$ = mk_node("Required", 1, $1); }
-| method      { $$ = mk_node("Provided", 1, $1); }
-;
-
-type_method
-: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';'
-{
-  $$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7);
-}
-| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';'
-{
-  $$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9);
-}
-;
-
-method
-: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8);
-}
-| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10);
-}
-;
-
-impl_method
-: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8);
-}
-| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10);
-}
-;
-
-// There are two forms of impl:
-//
-// impl (<...>)? TY { ... }
-// impl (<...>)? TRAIT for TY { ... }
-//
-// Unfortunately since TY can begin with '<' itself -- as part of a
-// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL:
-// should we reduce one of the early rules of TY (such as maybe_once)
-// or shall we continue shifting into the generic_params list for the
-// impl?
-//
-// The production parser disambiguates a different case here by
-// permitting / requiring the user to provide parens around types when
-// they are ambiguous with traits. We do the same here, regrettably,
-// by splitting ty into ty and ty_prim.
-item_impl
-: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
-{
-  $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
-}
-| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
-{
-  $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
-}
-| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
-{
-  $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
-}
-| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
-{
-  $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
-}
-| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
-{
-  $$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
-}
-| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
-{
-  $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
-}
-;
-
-maybe_impl_items
-: impl_items
-| %empty { $$ = mk_none(); }
-;
-
-impl_items
-: impl_item               { $$ = mk_node("ImplItems", 1, $1); }
-| impl_item impl_items    { $$ = ext_node($1, 1, $2); }
-;
-
-impl_item
-: impl_method
-| attrs_and_vis item_macro { $$ = mk_node("ImplMacroItem", 2, $1, $2); }
-| impl_const
-| impl_type
-;
-
-impl_const
-: attrs_and_vis item_const { $$ = mk_node("ImplConst", 1, $1, $2); }
-;
-
-impl_type
-: attrs_and_vis TYPE ident generic_params '=' ty_sum ';'  { $$ = mk_node("ImplType", 4, $1, $3, $4, $6); }
-;
-
-item_fn
-: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6);
-}
-;
-
-item_unsafe_fn
-: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7);
-}
-| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
-{
-  $$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9);
-}
-;
-
-fn_decl
-: fn_params ret_ty   { $$ = mk_node("FnDecl", 2, $1, $2); }
-;
-
-fn_decl_with_self
-: fn_params_with_self ret_ty   { $$ = mk_node("FnDecl", 2, $1, $2); }
-;
-
-fn_decl_with_self_allow_anon_params
-: fn_anon_params_with_self ret_ty   { $$ = mk_node("FnDecl", 2, $1, $2); }
-;
-
-fn_params
-: '(' maybe_params ')'  { $$ = $2; }
-;
-
-fn_anon_params
-: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); }
-| '(' ')'                                            { $$ = mk_none(); }
-;
-
-fn_params_with_self
-: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')'              { $$ = mk_node("SelfValue", 3, $2, $4, $5); }
-| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')'          { $$ = mk_node("SelfRegion", 3, $3, $5, $6); }
-| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); }
-| '(' maybe_params ')'                                                       { $$ = mk_node("SelfStatic", 1, $2); }
-;
-
-fn_anon_params_with_self
-: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')'              { $$ = mk_node("SelfValue", 3, $2, $4, $5); }
-| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')'          { $$ = mk_node("SelfRegion", 3, $3, $5, $6); }
-| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); }
-| '(' maybe_anon_params ')'                                                       { $$ = mk_node("SelfStatic", 1, $2); }
-;
-
-maybe_params
-: params
-| params ','
-| %empty  { $$ = mk_none(); }
-;
-
-params
-: param                { $$ = mk_node("Args", 1, $1); }
-| params ',' param     { $$ = ext_node($1, 1, $3); }
-;
-
-param
-: pat ':' ty_sum   { $$ = mk_node("Arg", 2, $1, $3); }
-;
-
-inferrable_params
-: inferrable_param                       { $$ = mk_node("InferrableParams", 1, $1); }
-| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); }
-;
-
-inferrable_param
-: pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); }
-;
-
-maybe_unboxed_closure_kind
-: %empty
-| ':'
-| '&' maybe_mut ':'
-;
-
-maybe_comma_params
-: ','            { $$ = mk_none(); }
-| ',' params     { $$ = $2; }
-| ',' params ',' { $$ = $2; }
-| %empty         { $$ = mk_none(); }
-;
-
-maybe_comma_anon_params
-: ','                 { $$ = mk_none(); }
-| ',' anon_params     { $$ = $2; }
-| ',' anon_params ',' { $$ = $2; }
-| %empty              { $$ = mk_none(); }
-;
-
-maybe_anon_params
-: anon_params
-| anon_params ','
-| %empty      { $$ = mk_none(); }
-;
-
-anon_params
-: anon_param                 { $$ = mk_node("Args", 1, $1); }
-| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); }
-;
-
-// anon means it's allowed to be anonymous (type-only), but it can
-// still have a name
-anon_param
-: named_arg ':' ty   { $$ = mk_node("Arg", 2, $1, $3); }
-| ty
-;
-
-anon_params_allow_variadic_tail
-: ',' DOTDOTDOT                                  { $$ = mk_none(); }
-| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node("Args", 2, $2, $3); }
-| %empty                                         { $$ = mk_none(); }
-;
-
-named_arg
-: ident
-| UNDERSCORE        { $$ = mk_atom("PatWild"); }
-| '&' ident         { $$ = $2; }
-| '&' UNDERSCORE    { $$ = mk_atom("PatWild"); }
-| ANDAND ident      { $$ = $2; }
-| ANDAND UNDERSCORE { $$ = mk_atom("PatWild"); }
-| MUT ident         { $$ = $2; }
-;
-
-ret_ty
-: RARROW '!'         { $$ = mk_none(); }
-| RARROW ty          { $$ = mk_node("ret-ty", 1, $2); }
-| %prec IDENT %empty { $$ = mk_none(); }
-;
-
-generic_params
-: '<' lifetimes '>'                   { $$ = mk_node("Generics", 2, $2, mk_none()); }
-| '<' lifetimes ',' '>'               { $$ = mk_node("Generics", 2, $2, mk_none()); }
-| '<' lifetimes SHR                   { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); }
-| '<' lifetimes ',' SHR               { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); }
-| '<' lifetimes ',' ty_params '>'     { $$ = mk_node("Generics", 2, $2, $4); }
-| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node("Generics", 2, $2, $4); }
-| '<' lifetimes ',' ty_params SHR     { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); }
-| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); }
-| '<' ty_params '>'                   { $$ = mk_node("Generics", 2, mk_none(), $2); }
-| '<' ty_params ',' '>'               { $$ = mk_node("Generics", 2, mk_none(), $2); }
-| '<' ty_params SHR                   { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); }
-| '<' ty_params ',' SHR               { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); }
-| %empty                              { $$ = mk_none(); }
-;
-
-maybe_where_clause
-: %empty                              { $$ = mk_none(); }
-| where_clause
-;
-
-where_clause
-: WHERE where_predicates              { $$ = mk_node("WhereClause", 1, $2); }
-| WHERE where_predicates ','          { $$ = mk_node("WhereClause", 1, $2); }
-;
-
-where_predicates
-: where_predicate                      { $$ = mk_node("WherePredicates", 1, $1); }
-| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); }
-;
-
-where_predicate
-: maybe_for_lifetimes lifetime ':' bounds    { $$ = mk_node("WherePredicate", 3, $1, $2, $4); }
-| maybe_for_lifetimes ty ':' ty_param_bounds { $$ = mk_node("WherePredicate", 3, $1, $2, $4); }
-;
-
-maybe_for_lifetimes
-: FOR '<' lifetimes '>' { $$ = mk_none(); }
-| %prec FORTYPE %empty  { $$ = mk_none(); }
-
-ty_params
-: ty_param               { $$ = mk_node("TyParams", 1, $1); }
-| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); }
-;
-
-// A path with no type parameters; e.g. `foo::bar::Baz`
-//
-// These show up in 'use' view-items, because these are processed
-// without respect to types.
-path_no_types_allowed
-: ident                               { $$ = mk_node("ViewPath", 1, $1); }
-| MOD_SEP ident                       { $$ = mk_node("ViewPath", 1, $2); }
-| SELF                                { $$ = mk_node("ViewPath", 1, mk_atom("Self")); }
-| MOD_SEP SELF                        { $$ = mk_node("ViewPath", 1, mk_atom("Self")); }
-| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); }
-;
-
-// A path with a lifetime and type parameters, with no double colons
-// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
-//
-// These show up in "trait references", the components of
-// type-parameter bounds lists, as well as in the prefix of the
-// path_generic_args_and_bounds rule, which is the full form of a
-// named typed expression.
-//
-// They do not have (nor need) an extra '::' before '<' because
-// unlike in expr context, there are no "less-than" type exprs to
-// be ambiguous with.
-path_generic_args_without_colons
-: %prec IDENT
-  ident                                                                       { $$ = mk_node("components", 1, $1); }
-| %prec IDENT
-  ident generic_args                                                          { $$ = mk_node("components", 2, $1, $2); }
-| %prec IDENT
-  ident '(' maybe_ty_sums ')' ret_ty                                          { $$ = mk_node("components", 2, $1, $3); }
-| %prec IDENT
-  path_generic_args_without_colons MOD_SEP ident                              { $$ = ext_node($1, 1, $3); }
-| %prec IDENT
-  path_generic_args_without_colons MOD_SEP ident generic_args                 { $$ = ext_node($1, 2, $3, $4); }
-| %prec IDENT
-  path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); }
-;
-
-generic_args
-: '<' generic_values '>'   { $$ = $2; }
-| '<' generic_values SHR   { push_back('>'); $$ = $2; }
-| '<' generic_values GE    { push_back('='); $$ = $2; }
-| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; }
-// If generic_args starts with "<<", the first arg must be a
-// TyQualifiedPath because that's the only type that can start with a
-// '<'. This rule parses that as the first ty_sum and then continues
-// with the rest of generic_values.
-| SHL ty_qualified_path_and_generic_values '>'   { $$ = $2; }
-| SHL ty_qualified_path_and_generic_values SHR   { push_back('>'); $$ = $2; }
-| SHL ty_qualified_path_and_generic_values GE    { push_back('='); $$ = $2; }
-| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; }
-;
-
-generic_values
-: maybe_lifetimes maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 2, $1, $2); }
-;
-
-maybe_ty_sums_and_or_bindings
-: ty_sums
-| ty_sums ','
-| ty_sums ',' bindings { $$ = mk_node("TySumsAndBindings", 2, $1, $3); }
-| bindings
-| bindings ','
-| %empty               { $$ = mk_none(); }
-;
-
-maybe_bindings
-: ',' bindings { $$ = $2; }
-| %empty       { $$ = mk_none(); }
-;
-
-////////////////////////////////////////////////////////////////////////
-// Part 2: Patterns
-////////////////////////////////////////////////////////////////////////
-
-pat
-: UNDERSCORE                                      { $$ = mk_atom("PatWild"); }
-| '&' pat                                         { $$ = mk_node("PatRegion", 1, $2); }
-| '&' MUT pat                                     { $$ = mk_node("PatRegion", 1, $3); }
-| ANDAND pat                                      { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); }
-| '(' ')'                                         { $$ = mk_atom("PatUnit"); }
-| '(' pat_tup ')'                                 { $$ = mk_node("PatTup", 1, $2); }
-| '(' pat_tup ',' ')'                             { $$ = mk_node("PatTup", 1, $2); }
-| '[' pat_vec ']'                                 { $$ = mk_node("PatVec", 1, $2); }
-| lit_or_path
-| lit_or_path DOTDOTDOT lit_or_path               { $$ = mk_node("PatRange", 2, $1, $3); }
-| path_expr '{' pat_struct '}'                    { $$ = mk_node("PatStruct", 2, $1, $3); }
-| path_expr '(' DOTDOT ')'                        { $$ = mk_node("PatEnum", 1, $1); }
-| path_expr '(' pat_tup ')'                       { $$ = mk_node("PatEnum", 2, $1, $3); }
-| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); }
-| binding_mode ident                              { $$ = mk_node("PatIdent", 2, $1, $2); }
-|              ident '@' pat                      { $$ = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), $1, $3); }
-| binding_mode ident '@' pat                      { $$ = mk_node("PatIdent", 3, $1, $2, $4); }
-| BOX pat                                         { $$ = mk_node("PatUniq", 1, $2); }
-| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("PatQualifiedPath", 3, $2, $3, $6); }
-| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident
-{
-  $$ = mk_node("PatQualifiedPath", 3, mk_node("PatQualifiedPath", 3, $2, $3, $6), $7, $10);
-}
-;
-
-pats_or
-: pat              { $$ = mk_node("Pats", 1, $1); }
-| pats_or '|' pat  { $$ = ext_node($1, 1, $3); }
-;
-
-binding_mode
-: REF         { $$ = mk_node("BindByRef", 1, mk_atom("MutImmutable")); }
-| REF MUT     { $$ = mk_node("BindByRef", 1, mk_atom("MutMutable")); }
-| MUT         { $$ = mk_node("BindByValue", 1, mk_atom("MutMutable")); }
-;
-
-lit_or_path
-: path_expr    { $$ = mk_node("PatLit", 1, $1); }
-| lit          { $$ = mk_node("PatLit", 1, $1); }
-| '-' lit      { $$ = mk_node("PatLit", 1, $2); }
-;
-
-pat_field
-:                  ident        { $$ = mk_node("PatField", 1, $1); }
-|     binding_mode ident        { $$ = mk_node("PatField", 2, $1, $2); }
-| BOX              ident        { $$ = mk_node("PatField", 2, mk_atom("box"), $2); }
-| BOX binding_mode ident        { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); }
-|              ident ':' pat    { $$ = mk_node("PatField", 2, $1, $3); }
-| binding_mode ident ':' pat    { $$ = mk_node("PatField", 3, $1, $2, $4); }
-;
-
-pat_fields
-: pat_field                  { $$ = mk_node("PatFields", 1, $1); }
-| pat_fields ',' pat_field   { $$ = ext_node($1, 1, $3); }
-;
-
-pat_struct
-: pat_fields                 { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); }
-| pat_fields ','             { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); }
-| pat_fields ',' DOTDOT      { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); }
-| DOTDOT                     { $$ = mk_node("PatStruct", 1, mk_atom("true")); }
-;
-
-pat_tup
-: pat               { $$ = mk_node("pat_tup", 1, $1); }
-| pat_tup ',' pat   { $$ = ext_node($1, 1, $3); }
-;
-
-pat_vec
-: pat_vec_elts                                  { $$ = mk_node("PatVec", 2, $1, mk_none()); }
-| pat_vec_elts                             ','  { $$ = mk_node("PatVec", 2, $1, mk_none()); }
-| pat_vec_elts     DOTDOT                       { $$ = mk_node("PatVec", 2, $1, mk_none()); }
-| pat_vec_elts ',' DOTDOT                       { $$ = mk_node("PatVec", 2, $1, mk_none()); }
-| pat_vec_elts     DOTDOT ',' pat_vec_elts      { $$ = mk_node("PatVec", 2, $1, $4); }
-| pat_vec_elts     DOTDOT ',' pat_vec_elts ','  { $$ = mk_node("PatVec", 2, $1, $4); }
-| pat_vec_elts ',' DOTDOT ',' pat_vec_elts      { $$ = mk_node("PatVec", 2, $1, $5); }
-| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ','  { $$ = mk_node("PatVec", 2, $1, $5); }
-|                  DOTDOT ',' pat_vec_elts      { $$ = mk_node("PatVec", 2, mk_none(), $3); }
-|                  DOTDOT ',' pat_vec_elts ','  { $$ = mk_node("PatVec", 2, mk_none(), $3); }
-|                  DOTDOT                       { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); }
-| %empty                                        { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); }
-;
-
-pat_vec_elts
-: pat                    { $$ = mk_node("PatVecElts", 1, $1); }
-| pat_vec_elts ',' pat   { $$ = ext_node($1, 1, $3); }
-;
-
-////////////////////////////////////////////////////////////////////////
-// Part 3: Types
-////////////////////////////////////////////////////////////////////////
-
-ty
-: ty_prim
-| ty_closure
-| '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident                                      { $$ = mk_node("TyQualifiedPath", 3, $2, $3, $6); }
-| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, $2, $3, $6), $7, $10); }
-| '(' ty_sums ')'                                                                      { $$ = mk_node("TyTup", 1, $2); }
-| '(' ty_sums ',' ')'                                                                  { $$ = mk_node("TyTup", 1, $2); }
-| '(' ')'                                                                              { $$ = mk_atom("TyNil"); }
-;
-
-ty_prim
-: %prec IDENT path_generic_args_without_colons              { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); }
-| %prec IDENT MOD_SEP path_generic_args_without_colons      { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); }
-| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); }
-| BOX ty                                                    { $$ = mk_node("TyBox", 1, $2); }
-| '*' maybe_mut_or_const ty                                 { $$ = mk_node("TyPtr", 2, $2, $3); }
-| '&' ty                                                    { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); }
-| '&' MUT ty                                                { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); }
-| ANDAND ty                                                 { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); }
-| ANDAND MUT ty                                             { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); }
-| '&' lifetime maybe_mut ty                                 { $$ = mk_node("TyRptr", 3, $2, $3, $4); }
-| ANDAND lifetime maybe_mut ty                              { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); }
-| '[' ty ']'                                                { $$ = mk_node("TyVec", 1, $2); }
-| '[' ty ',' DOTDOT expr ']'                                { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); }
-| '[' ty ';' expr ']'                                       { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); }
-| TYPEOF '(' expr ')'                                       { $$ = mk_node("TyTypeof", 1, $3); }
-| UNDERSCORE                                                { $$ = mk_atom("TyInfer"); }
-| ty_bare_fn
-| ty_proc
-| for_in_type
-;
-
-ty_bare_fn
-:                         FN ty_fn_decl { $$ = $2; }
-| UNSAFE                  FN ty_fn_decl { $$ = $3; }
-|        EXTERN maybe_abi FN ty_fn_decl { $$ = $4; }
-| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; }
-;
-
-ty_fn_decl
-: generic_params fn_anon_params ret_ty { $$ = mk_node("TyFnDecl", 3, $1, $2, $3); }
-;
-
-ty_closure
-: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $3, $5, $6); }
-|        '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $2, $4, $5); }
-| UNSAFE OROR maybe_bounds ret_ty                { $$ = mk_node("TyClosure", 2, $3, $4); }
-|        OROR maybe_bounds ret_ty                { $$ = mk_node("TyClosure", 2, $2, $3); }
-;
-
-ty_proc
-: PROC generic_params fn_params maybe_bounds ret_ty { $$ = mk_node("TyProc", 4, $2, $3, $4, $5); }
-;
-
-for_in_type
-: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); }
-;
-
-for_in_type_suffix
-: ty_proc
-| ty_bare_fn
-| trait_ref
-| ty_closure
-;
-
-maybe_mut
-: MUT              { $$ = mk_atom("MutMutable"); }
-| %prec MUT %empty { $$ = mk_atom("MutImmutable"); }
-;
-
-maybe_mut_or_const
-: MUT    { $$ = mk_atom("MutMutable"); }
-| CONST  { $$ = mk_atom("MutImmutable"); }
-| %empty { $$ = mk_atom("MutImmutable"); }
-;
-
-ty_qualified_path_and_generic_values
-: ty_qualified_path maybe_bindings
-{
-  $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, $1)), $2);
-}
-| ty_qualified_path ',' ty_sums maybe_bindings
-{
-  $$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 2, $1, $3), $4);
-}
-;
-
-ty_qualified_path
-: ty_sum AS trait_ref '>' MOD_SEP ident                     { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); }
-| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); }
-;
-
-maybe_ty_sums
-: ty_sums
-| ty_sums ','
-| %empty { $$ = mk_none(); }
-;
-
-ty_sums
-: ty_sum             { $$ = mk_node("TySums", 1, $1); }
-| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); }
-;
-
-ty_sum
-: ty                     { $$ = mk_node("TySum", 1, $1); }
-| ty '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); }
-;
-
-ty_prim_sum
-: ty_prim                     { $$ = mk_node("TySum", 1, $1); }
-| ty_prim '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); }
-;
-
-maybe_ty_param_bounds
-: ':' ty_param_bounds { $$ = $2; }
-| %empty              { $$ = mk_none(); }
-;
-
-ty_param_bounds
-: boundseq
-| %empty { $$ = mk_none(); }
-;
-
-boundseq
-: polybound
-| boundseq '+' polybound { $$ = ext_node($1, 1, $3); }
-;
-
-polybound
-: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); }
-| bound
-| '?' bound { $$ = $2; }
-;
-
-bindings
-: binding              { $$ = mk_node("Bindings", 1, $1); }
-| bindings ',' binding { $$ = ext_node($1, 1, $3); }
-;
-
-binding
-: ident '=' ty { mk_node("Binding", 2, $1, $3); }
-;
-
-ty_param
-: ident maybe_ty_param_bounds maybe_ty_default           { $$ = mk_node("TyParam", 3, $1, $2, $3); }
-| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 4, $1, $3, $4, $5); }
-;
-
-maybe_bounds
-: %prec SHIFTPLUS
-  ':' bounds             { $$ = $2; }
-| %prec SHIFTPLUS %empty { $$ = mk_none(); }
-;
-
-bounds
-: bound            { $$ = mk_node("bounds", 1, $1); }
-| bounds '+' bound { $$ = ext_node($1, 1, $3); }
-;
-
-bound
-: lifetime
-| trait_ref
-;
-
-maybe_ltbounds
-: %prec SHIFTPLUS
-  ':' ltbounds       { $$ = $2; }
-| %empty             { $$ = mk_none(); }
-;
-
-ltbounds
-: lifetime              { $$ = mk_node("ltbounds", 1, $1); }
-| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); }
-;
-
-maybe_ty_default
-: '=' ty_sum { $$ = mk_node("TyDefault", 1, $2); }
-| %empty     { $$ = mk_none(); }
-;
-
-maybe_lifetimes
-: lifetimes
-| lifetimes ','
-| %empty { $$ = mk_none(); }
-;
-
-lifetimes
-: lifetime_and_bounds               { $$ = mk_node("Lifetimes", 1, $1); }
-| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); }
-;
-
-lifetime_and_bounds
-: LIFETIME maybe_ltbounds         { $$ = mk_node("lifetime", 2, mk_atom(yytext), $2); }
-| STATIC_LIFETIME                 { $$ = mk_atom("static_lifetime"); }
-;
-
-lifetime
-: LIFETIME         { $$ = mk_node("lifetime", 1, mk_atom(yytext)); }
-| STATIC_LIFETIME  { $$ = mk_atom("static_lifetime"); }
-;
-
-trait_ref
-: %prec IDENT path_generic_args_without_colons
-| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; }
-;
-
-////////////////////////////////////////////////////////////////////////
-// Part 4: Blocks, statements, and expressions
-////////////////////////////////////////////////////////////////////////
-
-inner_attrs_and_block
-: '{' maybe_inner_attrs maybe_stmts '}'        { $$ = mk_node("ExprBlock", 2, $2, $3); }
-;
-
-block
-: '{' maybe_stmts '}'                          { $$ = mk_node("ExprBlock", 1, $2); }
-;
-
-maybe_stmts
-: stmts
-| stmts nonblock_expr { $$ = ext_node($1, 1, $2); }
-| nonblock_expr
-| %empty              { $$ = mk_none(); }
-;
-
-// There are two sub-grammars within a "stmts: exprs" derivation
-// depending on whether each stmt-expr is a block-expr form; this is to
-// handle the "semicolon rule" for stmt sequencing that permits
-// writing
-//
-//     if foo { bar } 10
-//
-// as a sequence of two stmts (one if-expr stmt, one lit-10-expr
-// stmt). Unfortunately by permitting juxtaposition of exprs in
-// sequence like that, the non-block expr grammar has to have a
-// second limited sub-grammar that excludes the prefix exprs that
-// are ambiguous with binops. That is to say:
-//
-//     {10} - 1
-//
-// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that
-// is to say, two statements rather than one, at least according to
-// the mainline rust parser.
-//
-// So we wind up with a 3-way split in exprs that occur in stmt lists:
-// block, nonblock-prefix, and nonblock-nonprefix.
-//
-// In non-stmts contexts, expr can relax this trichotomy.
-//
-// There is also one other expr subtype: nonparen_expr disallows exprs
-// surrounded by parens (including tuple expressions), this is
-// necessary for BOX (place) expressions, so a parens expr following
-// the BOX is always parsed as the place.
-
-stmts
-: stmt           { $$ = mk_node("stmts", 1, $1); }
-| stmts stmt     { $$ = ext_node($1, 1, $2); }
-;
-
-stmt
-: let
-|                 stmt_item
-|             PUB stmt_item { $$ = $2; }
-| outer_attrs     stmt_item { $$ = $2; }
-| outer_attrs PUB stmt_item { $$ = $3; }
-| full_block_expr
-| block
-| nonblock_expr ';'
-| ';'                   { $$ = mk_none(); }
-;
-
-maybe_exprs
-: exprs
-| exprs ','
-| %empty { $$ = mk_none(); }
-;
-
-maybe_expr
-: expr
-| %empty { $$ = mk_none(); }
-;
-
-exprs
-: expr                                                        { $$ = mk_node("exprs", 1, $1); }
-| exprs ',' expr                                              { $$ = ext_node($1, 1, $3); }
-;
-
-path_expr
-: path_generic_args_with_colons
-| MOD_SEP path_generic_args_with_colons      { $$ = $2; }
-| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node("SelfPath", 1, $3); }
-;
-
-// A path with a lifetime and type parameters with double colons before
-// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
-//
-// These show up in expr context, in order to disambiguate from "less-than"
-// expressions.
-path_generic_args_with_colons
-: ident                                              { $$ = mk_node("components", 1, $1); }
-| path_generic_args_with_colons MOD_SEP ident        { $$ = ext_node($1, 1, $3); }
-| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); }
-;
-
-// the braces-delimited macro is a block_expr so it doesn't appear here
-macro_expr
-: path_expr '!' maybe_ident parens_delimited_token_trees   { $$ = mk_node("MacroExpr", 3, $1, $3, $4); }
-| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); }
-;
-
-nonblock_expr
-: lit                                                           { $$ = mk_node("ExprLit", 1, $1); }
-| %prec IDENT
-  path_expr                                                     { $$ = mk_node("ExprPath", 1, $1); }
-| SELF                                                          { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
-| macro_expr                                                    { $$ = mk_node("ExprMac", 1, $1); }
-| path_expr '{' struct_expr_fields '}'                          { $$ = mk_node("ExprStruct", 2, $1, $3); }
-| nonblock_expr '.' path_generic_args_with_colons               { $$ = mk_node("ExprField", 2, $1, $3); }
-| nonblock_expr '.' LIT_INTEGER                                 { $$ = mk_node("ExprTupleIndex", 1, $1); }
-| nonblock_expr '[' maybe_expr ']'                              { $$ = mk_node("ExprIndex", 2, $1, $3); }
-| nonblock_expr '(' maybe_exprs ')'                             { $$ = mk_node("ExprCall", 2, $1, $3); }
-| '[' vec_expr ']'                                              { $$ = mk_node("ExprVec", 1, $2); }
-| '(' maybe_exprs ')'                                           { $$ = mk_node("ExprParen", 1, $2); }
-| CONTINUE                                                      { $$ = mk_node("ExprAgain", 0); }
-| CONTINUE lifetime                                             { $$ = mk_node("ExprAgain", 1, $2); }
-| RETURN                                                        { $$ = mk_node("ExprRet", 0); }
-| RETURN expr                                                   { $$ = mk_node("ExprRet", 1, $2); }
-| BREAK                                                         { $$ = mk_node("ExprBreak", 0); }
-| BREAK lifetime                                                { $$ = mk_node("ExprBreak", 1, $2); }
-| nonblock_expr LARROW expr                                     { $$ = mk_node("ExprInPlace", 2, $1, $3); }
-| nonblock_expr '=' expr                                        { $$ = mk_node("ExprAssign", 2, $1, $3); }
-| nonblock_expr SHLEQ expr                                      { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
-| nonblock_expr SHREQ expr                                      { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
-| nonblock_expr MINUSEQ expr                                    { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
-| nonblock_expr ANDEQ expr                                      { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
-| nonblock_expr OREQ expr                                       { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
-| nonblock_expr PLUSEQ expr                                     { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
-| nonblock_expr STAREQ expr                                     { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
-| nonblock_expr SLASHEQ expr                                    { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
-| nonblock_expr CARETEQ expr                                    { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
-| nonblock_expr PERCENTEQ expr                                  { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
-| nonblock_expr OROR expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
-| nonblock_expr ANDAND expr                                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
-| nonblock_expr EQEQ expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
-| nonblock_expr NE expr                                         { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
-| nonblock_expr '<' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
-| nonblock_expr '>' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
-| nonblock_expr LE expr                                         { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
-| nonblock_expr GE expr                                         { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
-| nonblock_expr '|' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
-| nonblock_expr '^' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
-| nonblock_expr '&' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
-| nonblock_expr SHL expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
-| nonblock_expr SHR expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
-| nonblock_expr '+' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
-| nonblock_expr '-' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
-| nonblock_expr '*' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
-| nonblock_expr '/' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
-| nonblock_expr '%' expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
-| nonblock_expr DOTDOT                                          { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
-| nonblock_expr DOTDOT expr                                     { $$ = mk_node("ExprRange", 2, $1, $3); }
-|               DOTDOT expr                                     { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
-|               DOTDOT                                          { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
-| nonblock_expr AS ty                                           { $$ = mk_node("ExprCast", 2, $1, $3); }
-| BOX nonparen_expr                                             { $$ = mk_node("ExprBox", 1, $2); }
-| %prec BOXPLACE BOX '(' maybe_expr ')' nonblock_expr           { $$ = mk_node("ExprBox", 2, $3, $5); }
-| expr_qualified_path
-| nonblock_prefix_expr
-;
-
-expr
-: lit                                                 { $$ = mk_node("ExprLit", 1, $1); }
-| %prec IDENT
-  path_expr                                           { $$ = mk_node("ExprPath", 1, $1); }
-| SELF                                                { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
-| macro_expr                                          { $$ = mk_node("ExprMac", 1, $1); }
-| path_expr '{' struct_expr_fields '}'                { $$ = mk_node("ExprStruct", 2, $1, $3); }
-| expr '.' path_generic_args_with_colons              { $$ = mk_node("ExprField", 2, $1, $3); }
-| expr '.' LIT_INTEGER                                { $$ = mk_node("ExprTupleIndex", 1, $1); }
-| expr '[' maybe_expr ']'                             { $$ = mk_node("ExprIndex", 2, $1, $3); }
-| expr '(' maybe_exprs ')'                            { $$ = mk_node("ExprCall", 2, $1, $3); }
-| '(' maybe_exprs ')'                                 { $$ = mk_node("ExprParen", 1, $2); }
-| '[' vec_expr ']'                                    { $$ = mk_node("ExprVec", 1, $2); }
-| CONTINUE                                            { $$ = mk_node("ExprAgain", 0); }
-| CONTINUE ident                                      { $$ = mk_node("ExprAgain", 1, $2); }
-| RETURN                                              { $$ = mk_node("ExprRet", 0); }
-| RETURN expr                                         { $$ = mk_node("ExprRet", 1, $2); }
-| BREAK                                               { $$ = mk_node("ExprBreak", 0); }
-| BREAK ident                                         { $$ = mk_node("ExprBreak", 1, $2); }
-| expr LARROW expr                                    { $$ = mk_node("ExprInPlace", 2, $1, $3); }
-| expr '=' expr                                       { $$ = mk_node("ExprAssign", 2, $1, $3); }
-| expr SHLEQ expr                                     { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
-| expr SHREQ expr                                     { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
-| expr MINUSEQ expr                                   { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
-| expr ANDEQ expr                                     { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
-| expr OREQ expr                                      { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
-| expr PLUSEQ expr                                    { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
-| expr STAREQ expr                                    { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
-| expr SLASHEQ expr                                   { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
-| expr CARETEQ expr                                   { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
-| expr PERCENTEQ expr                                 { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
-| expr OROR expr                                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
-| expr ANDAND expr                                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
-| expr EQEQ expr                                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
-| expr NE expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
-| expr '<' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
-| expr '>' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
-| expr LE expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
-| expr GE expr                                        { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
-| expr '|' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
-| expr '^' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
-| expr '&' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
-| expr SHL expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
-| expr SHR expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
-| expr '+' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
-| expr '-' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
-| expr '*' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
-| expr '/' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
-| expr '%' expr                                       { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
-| expr DOTDOT                                         { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
-| expr DOTDOT expr                                    { $$ = mk_node("ExprRange", 2, $1, $3); }
-|      DOTDOT expr                                    { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
-|      DOTDOT                                         { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
-| expr AS ty                                          { $$ = mk_node("ExprCast", 2, $1, $3); }
-| BOX nonparen_expr                                   { $$ = mk_node("ExprBox", 1, $2); }
-| %prec BOXPLACE BOX '(' maybe_expr ')' expr          { $$ = mk_node("ExprBox", 2, $3, $5); }
-| expr_qualified_path
-| block_expr
-| block
-| nonblock_prefix_expr
-;
-
-nonparen_expr
-: lit                                                 { $$ = mk_node("ExprLit", 1, $1); }
-| %prec IDENT
-  path_expr                                           { $$ = mk_node("ExprPath", 1, $1); }
-| SELF                                                { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
-| macro_expr                                          { $$ = mk_node("ExprMac", 1, $1); }
-| path_expr '{' struct_expr_fields '}'                { $$ = mk_node("ExprStruct", 2, $1, $3); }
-| nonparen_expr '.' path_generic_args_with_colons     { $$ = mk_node("ExprField", 2, $1, $3); }
-| nonparen_expr '.' LIT_INTEGER                       { $$ = mk_node("ExprTupleIndex", 1, $1); }
-| nonparen_expr '[' maybe_expr ']'                    { $$ = mk_node("ExprIndex", 2, $1, $3); }
-| nonparen_expr '(' maybe_exprs ')'                   { $$ = mk_node("ExprCall", 2, $1, $3); }
-| '[' vec_expr ']'                                    { $$ = mk_node("ExprVec", 1, $2); }
-| CONTINUE                                            { $$ = mk_node("ExprAgain", 0); }
-| CONTINUE ident                                      { $$ = mk_node("ExprAgain", 1, $2); }
-| RETURN                                              { $$ = mk_node("ExprRet", 0); }
-| RETURN expr                                         { $$ = mk_node("ExprRet", 1, $2); }
-| BREAK                                               { $$ = mk_node("ExprBreak", 0); }
-| BREAK ident                                         { $$ = mk_node("ExprBreak", 1, $2); }
-| nonparen_expr LARROW nonparen_expr                  { $$ = mk_node("ExprInPlace", 2, $1, $3); }
-| nonparen_expr '=' nonparen_expr                     { $$ = mk_node("ExprAssign", 2, $1, $3); }
-| nonparen_expr SHLEQ nonparen_expr                   { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
-| nonparen_expr SHREQ nonparen_expr                   { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
-| nonparen_expr MINUSEQ nonparen_expr                 { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
-| nonparen_expr ANDEQ nonparen_expr                   { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
-| nonparen_expr OREQ nonparen_expr                    { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
-| nonparen_expr PLUSEQ nonparen_expr                  { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
-| nonparen_expr STAREQ nonparen_expr                  { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
-| nonparen_expr SLASHEQ nonparen_expr                 { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
-| nonparen_expr CARETEQ nonparen_expr                 { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
-| nonparen_expr PERCENTEQ nonparen_expr               { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
-| nonparen_expr OROR nonparen_expr                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
-| nonparen_expr ANDAND nonparen_expr                  { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
-| nonparen_expr EQEQ nonparen_expr                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
-| nonparen_expr NE nonparen_expr                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
-| nonparen_expr '<' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
-| nonparen_expr '>' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
-| nonparen_expr LE nonparen_expr                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
-| nonparen_expr GE nonparen_expr                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
-| nonparen_expr '|' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
-| nonparen_expr '^' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
-| nonparen_expr '&' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
-| nonparen_expr SHL nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
-| nonparen_expr SHR nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
-| nonparen_expr '+' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
-| nonparen_expr '-' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
-| nonparen_expr '*' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
-| nonparen_expr '/' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
-| nonparen_expr '%' nonparen_expr                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
-| nonparen_expr DOTDOT                                { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
-| nonparen_expr DOTDOT nonparen_expr                  { $$ = mk_node("ExprRange", 2, $1, $3); }
-|               DOTDOT nonparen_expr                  { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
-|               DOTDOT                                { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
-| nonparen_expr AS ty                                 { $$ = mk_node("ExprCast", 2, $1, $3); }
-| BOX nonparen_expr                                   { $$ = mk_node("ExprBox", 1, $2); }
-| %prec BOXPLACE BOX '(' maybe_expr ')' expr          { $$ = mk_node("ExprBox", 1, $3, $5); }
-| expr_qualified_path
-| block_expr
-| block
-| nonblock_prefix_expr
-;
-
-expr_nostruct
-: lit                                                 { $$ = mk_node("ExprLit", 1, $1); }
-| %prec IDENT
-  path_expr                                           { $$ = mk_node("ExprPath", 1, $1); }
-| SELF                                                { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
-| macro_expr                                          { $$ = mk_node("ExprMac", 1, $1); }
-| expr_nostruct '.' path_generic_args_with_colons     { $$ = mk_node("ExprField", 2, $1, $3); }
-| expr_nostruct '.' LIT_INTEGER                       { $$ = mk_node("ExprTupleIndex", 1, $1); }
-| expr_nostruct '[' maybe_expr ']'                    { $$ = mk_node("ExprIndex", 2, $1, $3); }
-| expr_nostruct '(' maybe_exprs ')'                   { $$ = mk_node("ExprCall", 2, $1, $3); }
-| '[' vec_expr ']'                                    { $$ = mk_node("ExprVec", 1, $2); }
-| '(' maybe_exprs ')'                                 { $$ = mk_node("ExprParen", 1, $2); }
-| CONTINUE                                            { $$ = mk_node("ExprAgain", 0); }
-| CONTINUE ident                                      { $$ = mk_node("ExprAgain", 1, $2); }
-| RETURN                                              { $$ = mk_node("ExprRet", 0); }
-| RETURN expr                                         { $$ = mk_node("ExprRet", 1, $2); }
-| BREAK                                               { $$ = mk_node("ExprBreak", 0); }
-| BREAK ident                                         { $$ = mk_node("ExprBreak", 1, $2); }
-| expr_nostruct LARROW expr_nostruct                  { $$ = mk_node("ExprInPlace", 2, $1, $3); }
-| expr_nostruct '=' expr_nostruct                     { $$ = mk_node("ExprAssign", 2, $1, $3); }
-| expr_nostruct SHLEQ expr_nostruct                   { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
-| expr_nostruct SHREQ expr_nostruct                   { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
-| expr_nostruct MINUSEQ expr_nostruct                 { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
-| expr_nostruct ANDEQ expr_nostruct                   { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
-| expr_nostruct OREQ expr_nostruct                    { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
-| expr_nostruct PLUSEQ expr_nostruct                  { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
-| expr_nostruct STAREQ expr_nostruct                  { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
-| expr_nostruct SLASHEQ expr_nostruct                 { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
-| expr_nostruct CARETEQ expr_nostruct                 { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
-| expr_nostruct PERCENTEQ expr_nostruct               { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
-| expr_nostruct OROR expr_nostruct                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
-| expr_nostruct ANDAND expr_nostruct                  { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
-| expr_nostruct EQEQ expr_nostruct                    { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
-| expr_nostruct NE expr_nostruct                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
-| expr_nostruct '<' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
-| expr_nostruct '>' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
-| expr_nostruct LE expr_nostruct                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
-| expr_nostruct GE expr_nostruct                      { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
-| expr_nostruct '|' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
-| expr_nostruct '^' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
-| expr_nostruct '&' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
-| expr_nostruct SHL expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
-| expr_nostruct SHR expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
-| expr_nostruct '+' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
-| expr_nostruct '-' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
-| expr_nostruct '*' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
-| expr_nostruct '/' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
-| expr_nostruct '%' expr_nostruct                     { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
-| expr_nostruct DOTDOT               %prec RANGE      { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
-| expr_nostruct DOTDOT expr_nostruct                  { $$ = mk_node("ExprRange", 2, $1, $3); }
-|               DOTDOT expr_nostruct                  { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
-|               DOTDOT                                { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); }
-| expr_nostruct AS ty                                 { $$ = mk_node("ExprCast", 2, $1, $3); }
-| BOX nonparen_expr                                   { $$ = mk_node("ExprBox", 1, $2); }
-| %prec BOXPLACE BOX '(' maybe_expr ')' expr_nostruct { $$ = mk_node("ExprBox", 1, $3, $5); }
-| expr_qualified_path
-| block_expr
-| block
-| nonblock_prefix_expr_nostruct
-;
-
-nonblock_prefix_expr_nostruct
-: '-' expr_nostruct                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); }
-| '!' expr_nostruct                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); }
-| '*' expr_nostruct                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); }
-| '&' maybe_mut expr_nostruct               { $$ = mk_node("ExprAddrOf", 2, $2, $3); }
-| ANDAND maybe_mut expr_nostruct            { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); }
-| lambda_expr_nostruct
-| MOVE lambda_expr_nostruct                 { $$ = $2; }
-| proc_expr_nostruct
-;
-
-nonblock_prefix_expr
-: '-' expr                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); }
-| '!' expr                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); }
-| '*' expr                         { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); }
-| '&' maybe_mut expr               { $$ = mk_node("ExprAddrOf", 2, $2, $3); }
-| ANDAND maybe_mut expr            { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); }
-| lambda_expr
-| MOVE lambda_expr                 { $$ = $2; }
-| proc_expr
-;
-
-expr_qualified_path
-: '<' ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_qpath_params
-{
-  $$ = mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7);
-}
-| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident
-{
-  $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10);
-}
-| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident
-{
-  $$ = mk_node("ExprQualifiedPath", 3, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11);
-}
-| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident maybe_as_trait_ref '>' MOD_SEP ident generic_args
-{
-  $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 3, $2, $3, $6), $7, $10, $11);
-}
-| SHL ty_sum maybe_as_trait_ref '>' MOD_SEP ident generic_args maybe_as_trait_ref '>' MOD_SEP ident generic_args
-{
-  $$ = mk_node("ExprQualifiedPath", 4, mk_node("ExprQualifiedPath", 4, $2, $3, $6, $7), $8, $11, $12);
-}
-
-maybe_qpath_params
-: MOD_SEP generic_args { $$ = $2; }
-| %empty               { $$ = mk_none(); }
-;
-
-maybe_as_trait_ref
-: AS trait_ref { $$ = $2; }
-| %empty       { $$ = mk_none(); }
-;
-
-lambda_expr
-: %prec LAMBDA
-  OROR ret_ty expr                                        { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); }
-| %prec LAMBDA
-  '|' maybe_unboxed_closure_kind '|' ret_ty expr          { $$ = mk_node("ExprFnBlock", 3, mk_none(), $4, $5); }
-| %prec LAMBDA
-  '|' inferrable_params '|' ret_ty expr                   { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); }
-| %prec LAMBDA
-  '|' '&' maybe_mut ':' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $5, $7, $8); }
-| %prec LAMBDA
-  '|' ':' inferrable_params '|' ret_ty expr               { $$ = mk_node("ExprFnBlock", 3, $3, $5, $6); }
-;
-
-lambda_expr_nostruct
-: %prec LAMBDA
-  OROR expr_nostruct                                        { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); }
-| %prec LAMBDA
-  '|' maybe_unboxed_closure_kind '|'  expr_nostruct         { $$ = mk_node("ExprFnBlock", 2, mk_none(), $4); }
-| %prec LAMBDA
-  '|' inferrable_params '|' expr_nostruct                   { $$ = mk_node("ExprFnBlock", 2, $2, $4); }
-| %prec LAMBDA
-  '|' '&' maybe_mut ':' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $5, $7); }
-| %prec LAMBDA
-  '|' ':' inferrable_params '|' expr_nostruct               { $$ = mk_node("ExprFnBlock", 2, $3, $5); }
-
-;
-
-proc_expr
-: %prec LAMBDA
-  PROC '(' ')' expr                         { $$ = mk_node("ExprProc", 2, mk_none(), $4); }
-| %prec LAMBDA
-  PROC '(' inferrable_params ')' expr       { $$ = mk_node("ExprProc", 2, $3, $5); }
-;
-
-proc_expr_nostruct
-: %prec LAMBDA
-  PROC '(' ')' expr_nostruct                     { $$ = mk_node("ExprProc", 2, mk_none(), $4); }
-| %prec LAMBDA
-  PROC '(' inferrable_params ')' expr_nostruct   { $$ = mk_node("ExprProc", 2, $3, $5); }
-;
-
-vec_expr
-: maybe_exprs
-| exprs ';' expr { $$ = mk_node("VecRepeat", 2, $1, $3); }
-;
-
-struct_expr_fields
-: field_inits
-| field_inits ','
-| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); }
-;
-
-maybe_field_inits
-: field_inits
-| field_inits ','
-| %empty { $$ = mk_none(); }
-;
-
-field_inits
-: field_init                 { $$ = mk_node("FieldInits", 1, $1); }
-| field_inits ',' field_init { $$ = ext_node($1, 1, $3); }
-;
-
-field_init
-: ident ':' expr   { $$ = mk_node("FieldInit", 2, $1, $3); }
-;
-
-default_field_init
-: DOTDOT expr   { $$ = mk_node("DefaultFieldInit", 1, $2); }
-;
-
-block_expr
-: expr_match
-| expr_if
-| expr_if_let
-| expr_while
-| expr_while_let
-| expr_loop
-| expr_for
-| UNSAFE block                                           { $$ = mk_node("UnsafeBlock", 1, $2); }
-| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("Macro", 3, $1, $3, $4); }
-;
-
-full_block_expr
-: block_expr
-| full_block_expr '.' path_generic_args_with_colons %prec IDENT         { $$ = mk_node("ExprField", 2, $1, $3); }
-| full_block_expr '.' path_generic_args_with_colons '[' maybe_expr ']'  { $$ = mk_node("ExprIndex", 3, $1, $3, $5); }
-| full_block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); }
-| full_block_expr '.' LIT_INTEGER                                       { $$ = mk_node("ExprTupleIndex", 1, $1); }
-;
-
-expr_match
-: MATCH expr_nostruct '{' '}'                                     { $$ = mk_node("ExprMatch", 1, $2); }
-| MATCH expr_nostruct '{' match_clauses                       '}' { $$ = mk_node("ExprMatch", 2, $2, $4); }
-| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, ext_node($4, 1, $5)); }
-| MATCH expr_nostruct '{'               nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, mk_node("Arms", 1, $4)); }
-;
-
-match_clauses
-: match_clause               { $$ = mk_node("Arms", 1, $1); }
-| match_clauses match_clause { $$ = ext_node($1, 1, $2); }
-;
-
-match_clause
-: nonblock_match_clause ','
-| block_match_clause
-| block_match_clause ','
-;
-
-nonblock_match_clause
-: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr   { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
-| maybe_outer_attrs pats_or maybe_guard FAT_ARROW full_block_expr { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
-;
-
-block_match_clause
-: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
-;
-
-maybe_guard
-: IF expr_nostruct           { $$ = $2; }
-| %empty                     { $$ = mk_none(); }
-;
-
-expr_if
-: IF expr_nostruct block                              { $$ = mk_node("ExprIf", 2, $2, $3); }
-| IF expr_nostruct block ELSE block_or_if             { $$ = mk_node("ExprIf", 3, $2, $3, $5); }
-;
-
-expr_if_let
-: IF LET pat '=' expr_nostruct block                  { $$ = mk_node("ExprIfLet", 3, $3, $5, $6); }
-| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIfLet", 4, $3, $5, $6, $8); }
-;
-
-block_or_if
-: block
-| expr_if
-| expr_if_let
-;
-
-expr_while
-: maybe_label WHILE expr_nostruct block               { $$ = mk_node("ExprWhile", 3, $1, $3, $4); }
-;
-
-expr_while_let
-: maybe_label WHILE LET pat '=' expr_nostruct block   { $$ = mk_node("ExprWhileLet", 4, $1, $4, $6, $7); }
-;
-
-expr_loop
-: maybe_label LOOP block                              { $$ = mk_node("ExprLoop", 2, $1, $3); }
-;
-
-expr_for
-: maybe_label FOR pat IN expr_nostruct block          { $$ = mk_node("ExprForLoop", 4, $1, $3, $5, $6); }
-;
-
-maybe_label
-: lifetime ':'
-| %empty { $$ = mk_none(); }
-;
-
-let
-: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node("DeclLocal", 3, $2, $3, $4); }
-;
-
-////////////////////////////////////////////////////////////////////////
-// Part 5: Macros and misc. rules
-////////////////////////////////////////////////////////////////////////
-
-lit
-: LIT_BYTE                   { $$ = mk_node("LitByte", 1, mk_atom(yytext)); }
-| LIT_CHAR                   { $$ = mk_node("LitChar", 1, mk_atom(yytext)); }
-| LIT_INTEGER                { $$ = mk_node("LitInteger", 1, mk_atom(yytext)); }
-| LIT_FLOAT                  { $$ = mk_node("LitFloat", 1, mk_atom(yytext)); }
-| TRUE                       { $$ = mk_node("LitBool", 1, mk_atom(yytext)); }
-| FALSE                      { $$ = mk_node("LitBool", 1, mk_atom(yytext)); }
-| str
-;
-
-str
-: LIT_STR                    { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); }
-| LIT_STR_RAW                { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); }
-| LIT_BYTE_STR                 { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("ByteStr")); }
-| LIT_BYTE_STR_RAW             { $$ = mk_node("LitByteStr", 1, mk_atom(yytext), mk_atom("RawByteStr")); }
-;
-
-maybe_ident
-: %empty { $$ = mk_none(); }
-| ident
-;
-
-ident
-: IDENT                      { $$ = mk_node("ident", 1, mk_atom(yytext)); }
-;
-
-unpaired_token
-: SHL                        { $$ = mk_atom(yytext); }
-| SHR                        { $$ = mk_atom(yytext); }
-| LE                         { $$ = mk_atom(yytext); }
-| EQEQ                       { $$ = mk_atom(yytext); }
-| NE                         { $$ = mk_atom(yytext); }
-| GE                         { $$ = mk_atom(yytext); }
-| ANDAND                     { $$ = mk_atom(yytext); }
-| OROR                       { $$ = mk_atom(yytext); }
-| LARROW                     { $$ = mk_atom(yytext); }
-| SHLEQ                      { $$ = mk_atom(yytext); }
-| SHREQ                      { $$ = mk_atom(yytext); }
-| MINUSEQ                    { $$ = mk_atom(yytext); }
-| ANDEQ                      { $$ = mk_atom(yytext); }
-| OREQ                       { $$ = mk_atom(yytext); }
-| PLUSEQ                     { $$ = mk_atom(yytext); }
-| STAREQ                     { $$ = mk_atom(yytext); }
-| SLASHEQ                    { $$ = mk_atom(yytext); }
-| CARETEQ                    { $$ = mk_atom(yytext); }
-| PERCENTEQ                  { $$ = mk_atom(yytext); }
-| DOTDOT                     { $$ = mk_atom(yytext); }
-| DOTDOTDOT                  { $$ = mk_atom(yytext); }
-| MOD_SEP                    { $$ = mk_atom(yytext); }
-| RARROW                     { $$ = mk_atom(yytext); }
-| FAT_ARROW                  { $$ = mk_atom(yytext); }
-| LIT_BYTE                   { $$ = mk_atom(yytext); }
-| LIT_CHAR                   { $$ = mk_atom(yytext); }
-| LIT_INTEGER                { $$ = mk_atom(yytext); }
-| LIT_FLOAT                  { $$ = mk_atom(yytext); }
-| LIT_STR                    { $$ = mk_atom(yytext); }
-| LIT_STR_RAW                { $$ = mk_atom(yytext); }
-| LIT_BYTE_STR               { $$ = mk_atom(yytext); }
-| LIT_BYTE_STR_RAW           { $$ = mk_atom(yytext); }
-| IDENT                      { $$ = mk_atom(yytext); }
-| UNDERSCORE                 { $$ = mk_atom(yytext); }
-| LIFETIME                   { $$ = mk_atom(yytext); }
-| SELF                       { $$ = mk_atom(yytext); }
-| STATIC                     { $$ = mk_atom(yytext); }
-| AS                         { $$ = mk_atom(yytext); }
-| BREAK                      { $$ = mk_atom(yytext); }
-| CRATE                      { $$ = mk_atom(yytext); }
-| ELSE                       { $$ = mk_atom(yytext); }
-| ENUM                       { $$ = mk_atom(yytext); }
-| EXTERN                     { $$ = mk_atom(yytext); }
-| FALSE                      { $$ = mk_atom(yytext); }
-| FN                         { $$ = mk_atom(yytext); }
-| FOR                        { $$ = mk_atom(yytext); }
-| IF                         { $$ = mk_atom(yytext); }
-| IMPL                       { $$ = mk_atom(yytext); }
-| IN                         { $$ = mk_atom(yytext); }
-| LET                        { $$ = mk_atom(yytext); }
-| LOOP                       { $$ = mk_atom(yytext); }
-| MATCH                      { $$ = mk_atom(yytext); }
-| MOD                        { $$ = mk_atom(yytext); }
-| MOVE                       { $$ = mk_atom(yytext); }
-| MUT                        { $$ = mk_atom(yytext); }
-| PRIV                       { $$ = mk_atom(yytext); }
-| PUB                        { $$ = mk_atom(yytext); }
-| REF                        { $$ = mk_atom(yytext); }
-| RETURN                     { $$ = mk_atom(yytext); }
-| STRUCT                     { $$ = mk_atom(yytext); }
-| TRUE                       { $$ = mk_atom(yytext); }
-| TRAIT                      { $$ = mk_atom(yytext); }
-| TYPE                       { $$ = mk_atom(yytext); }
-| UNSAFE                     { $$ = mk_atom(yytext); }
-| USE                        { $$ = mk_atom(yytext); }
-| WHILE                      { $$ = mk_atom(yytext); }
-| CONTINUE                   { $$ = mk_atom(yytext); }
-| PROC                       { $$ = mk_atom(yytext); }
-| BOX                        { $$ = mk_atom(yytext); }
-| CONST                      { $$ = mk_atom(yytext); }
-| WHERE                      { $$ = mk_atom(yytext); }
-| TYPEOF                     { $$ = mk_atom(yytext); }
-| INNER_DOC_COMMENT          { $$ = mk_atom(yytext); }
-| OUTER_DOC_COMMENT          { $$ = mk_atom(yytext); }
-| SHEBANG                    { $$ = mk_atom(yytext); }
-| STATIC_LIFETIME            { $$ = mk_atom(yytext); }
-| ';'                        { $$ = mk_atom(yytext); }
-| ','                        { $$ = mk_atom(yytext); }
-| '.'                        { $$ = mk_atom(yytext); }
-| '@'                        { $$ = mk_atom(yytext); }
-| '#'                        { $$ = mk_atom(yytext); }
-| '~'                        { $$ = mk_atom(yytext); }
-| ':'                        { $$ = mk_atom(yytext); }
-| '$'                        { $$ = mk_atom(yytext); }
-| '='                        { $$ = mk_atom(yytext); }
-| '?'                        { $$ = mk_atom(yytext); }
-| '!'                        { $$ = mk_atom(yytext); }
-| '<'                        { $$ = mk_atom(yytext); }
-| '>'                        { $$ = mk_atom(yytext); }
-| '-'                        { $$ = mk_atom(yytext); }
-| '&'                        { $$ = mk_atom(yytext); }
-| '|'                        { $$ = mk_atom(yytext); }
-| '+'                        { $$ = mk_atom(yytext); }
-| '*'                        { $$ = mk_atom(yytext); }
-| '/'                        { $$ = mk_atom(yytext); }
-| '^'                        { $$ = mk_atom(yytext); }
-| '%'                        { $$ = mk_atom(yytext); }
-;
-
-token_trees
-: %empty                     { $$ = mk_node("TokenTrees", 0); }
-| token_trees token_tree     { $$ = ext_node($1, 1, $2); }
-;
-
-token_tree
-: delimited_token_trees
-| unpaired_token         { $$ = mk_node("TTTok", 1, $1); }
-;
-
-delimited_token_trees
-: parens_delimited_token_trees
-| braces_delimited_token_trees
-| brackets_delimited_token_trees
-;
-
-parens_delimited_token_trees
-: '(' token_trees ')'
-{
-  $$ = mk_node("TTDelim", 3,
-               mk_node("TTTok", 1, mk_atom("(")),
-               $2,
-               mk_node("TTTok", 1, mk_atom(")")));
-}
-;
-
-braces_delimited_token_trees
-: '{' token_trees '}'
-{
-  $$ = mk_node("TTDelim", 3,
-               mk_node("TTTok", 1, mk_atom("{")),
-               $2,
-               mk_node("TTTok", 1, mk_atom("}")));
-}
-;
-
-brackets_delimited_token_trees
-: '[' token_trees ']'
-{
-  $$ = mk_node("TTDelim", 3,
-               mk_node("TTTok", 1, mk_atom("[")),
-               $2,
-               mk_node("TTTok", 1, mk_atom("]")));
-}
-;
\ No newline at end of file
diff --git a/src/grammar/raw-string-literal-ambiguity.md b/src/grammar/raw-string-literal-ambiguity.md
deleted file mode 100644
index c909f233314..00000000000
--- a/src/grammar/raw-string-literal-ambiguity.md
+++ /dev/null
@@ -1,64 +0,0 @@
-Rust's lexical grammar is not context-free. Raw string literals are the source
-of the problem. Informally, a raw string literal is an `r`, followed by `N`
-hashes (where N can be zero), a quote, any characters, then a quote followed
-by `N` hashes. Critically, once inside the first pair of quotes,
-another quote cannot be followed by `N` consecutive hashes. e.g.
-`r###""###"###` is invalid.
-
-This grammar describes this as best possible:
-
-    R -> 'r' S
-    S -> '"' B '"'
-    S -> '#' S '#'
-    B -> . B
-    B -> ε
-
-Where `.` represents any character, and `ε` the empty string. Consider the
-string `r#""#"#`. This string is not a valid raw string literal, but can be
-accepted as one by the above grammar, using the derivation:
-
-    R : #""#"#
-    S : ""#"
-    S : "#
-    B : #
-    B : ε
-
-(Where `T : U` means the rule `T` is applied, and `U` is the remainder of the
-string.) The difficulty arises from the fact that it is fundamentally
-context-sensitive. In particular, the context needed is the number of hashes.
-
-To prove that Rust's string literals are not context-free, we will use
-the fact that context-free languages are closed under intersection with
-regular languages, and the
-[pumping lemma for context-free languages](https://en.wikipedia.org/wiki/Pumping_lemma_for_context-free_languages).
-
-Consider the regular language `R = r#+""#*"#+`. If Rust's raw string literals are
-context-free, then their intersection with `R`, `R'`, should also be context-free.
-Therefore, to prove that raw string literals are not context-free,
-it is sufficient to prove that `R'` is not context-free.
-
-The language `R'` is `{r#^n""#^m"#^n | m < n}`.
-
-Assume `R'` *is* context-free. Then `R'` has some pumping length `p > 0` for which
-the pumping lemma applies. Consider the following string `s` in `R'`:
-
-`r#^p""#^{p-1}"#^p`
-
-e.g. for `p = 2`: `s = r##""#"##`
-
-Then `s = uvwxy` for some choice of `uvwxy` such that `vx` is non-empty,
-`|vwx| < p+1`, and `uv^iwx^iy` is in `R'` for all `i >= 0`.
-
-Neither `v` nor `x` can contain a `"` or `r`, as the number of these characters
-in any string in `R'` is fixed. So `v` and `x` contain only hashes.
-Consequently, of the three sequences of hashes, `v` and `x` combined
-can only pump two of them.
-If we ever choose the central sequence of hashes, then one of the outer sequences
-will not grow when we pump, leading to an imbalance between the outer sequences.
-Therefore, we must pump both outer sequences of hashes. However,
-there are `p+2` characters between these two sequences of hashes, and `|vwx|` must
-be less than `p+1`. Therefore we have a contradiction, and `R'` must not be
-context-free.
-
-Since `R'` is not context-free, it follows that the Rust's raw string literals
-must not be context-free.
diff --git a/src/grammar/testparser.py b/src/grammar/testparser.py
deleted file mode 100755
index 37be41b935f..00000000000
--- a/src/grammar/testparser.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-# ignore-tidy-linelength
-
-import sys
-
-import os
-import subprocess
-import argparse
-
-# usage: testparser.py [-h] [-p PARSER [PARSER ...]] -s SOURCE_DIR
-
-# Parsers should read from stdin and return exit status 0 for a
-# successful parse, and nonzero for an unsuccessful parse
-
-parser = argparse.ArgumentParser()
-parser.add_argument('-p', '--parser', nargs='+')
-parser.add_argument('-s', '--source-dir', nargs=1, required=True)
-args = parser.parse_args(sys.argv[1:])
-
-total = 0
-ok = {}
-bad = {}
-for parser in args.parser:
-    ok[parser] = 0
-    bad[parser] = []
-devnull = open(os.devnull, 'w')
-print("\n")
-
-for base, dirs, files in os.walk(args.source_dir[0]):
-    for f in filter(lambda p: p.endswith('.rs'), files):
-        p = os.path.join(base, f)
-        parse_fail = 'parse-fail' in p
-        if sys.version_info.major == 3:
-            lines = open(p, encoding='utf-8').readlines()
-        else:
-            lines = open(p).readlines()
-        if any('ignore-test' in line or 'ignore-lexer-test' in line for line in lines):
-            continue
-        total += 1
-        for parser in args.parser:
-            if subprocess.call(parser, stdin=open(p), stderr=subprocess.STDOUT, stdout=devnull) == 0:
-                if parse_fail:
-                    bad[parser].append(p)
-                else:
-                    ok[parser] += 1
-            else:
-                if parse_fail:
-                    ok[parser] += 1
-                else:
-                    bad[parser].append(p)
-        parser_stats = ', '.join(['{}: {}'.format(parser, ok[parser]) for parser in args.parser])
-        sys.stdout.write("\033[K\r total: {}, {}, scanned {}"
-                         .format(total, os.path.relpath(parser_stats), os.path.relpath(p)))
-
-devnull.close()
-
-print("\n")
-
-for parser in args.parser:
-    filename = os.path.basename(parser) + '.bad'
-    print("writing {} files that did not yield the correct result with {} to {}".format(len(bad[parser]), parser, filename))
-    with open(filename, "w") as f:
-        for p in bad[parser]:
-            f.write(p)
-            f.write("\n")
diff --git a/src/grammar/tokens.h b/src/grammar/tokens.h
deleted file mode 100644
index 081bd050259..00000000000
--- a/src/grammar/tokens.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-enum Token {
-  SHL = 257, // Parser generators reserve 0-256 for char literals
-  SHR,
-  LE,
-  EQEQ,
-  NE,
-  GE,
-  ANDAND,
-  OROR,
-  SHLEQ,
-  SHREQ,
-  MINUSEQ,
-  ANDEQ,
-  OREQ,
-  PLUSEQ,
-  STAREQ,
-  SLASHEQ,
-  CARETEQ,
-  PERCENTEQ,
-  DOTDOT,
-  DOTDOTDOT,
-  MOD_SEP,
-  RARROW,
-  FAT_ARROW,
-  LIT_BYTE,
-  LIT_CHAR,
-  LIT_INTEGER,
-  LIT_FLOAT,
-  LIT_STR,
-  LIT_STR_RAW,
-  LIT_BYTE_STR,
-  LIT_BYTE_STR_RAW,
-  IDENT,
-  UNDERSCORE,
-  LIFETIME,
-
-  // keywords
-  SELF,
-  STATIC,
-  AS,
-  BREAK,
-  CRATE,
-  ELSE,
-  ENUM,
-  EXTERN,
-  FALSE,
-  FN,
-  FOR,
-  IF,
-  IMPL,
-  IN,
-  LET,
-  LOOP,
-  MATCH,
-  MOD,
-  MOVE,
-  MUT,
-  PRIV,
-  PUB,
-  REF,
-  RETURN,
-  STRUCT,
-  TRUE,
-  TRAIT,
-  TYPE,
-  UNSAFE,
-  USE,
-  WHILE,
-  CONTINUE,
-  PROC,
-  BOX,
-  CONST,
-  WHERE,
-  TYPEOF,
-  INNER_DOC_COMMENT,
-  OUTER_DOC_COMMENT,
-
-  SHEBANG,
-  SHEBANG_LINE,
-  STATIC_LIFETIME
-};
diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs
deleted file mode 100644
index 3ac043f7aa9..00000000000
--- a/src/grammar/verify.rs
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(plugin, rustc_private)]
-
-extern crate syntax;
-extern crate syntax_pos;
-extern crate rustc;
-
-#[macro_use]
-extern crate log;
-
-use std::collections::HashMap;
-use std::env;
-use std::fs::File;
-use std::io::{BufRead, Read};
-use std::path::Path;
-
-use syntax::parse::lexer;
-use rustc::dep_graph::DepGraph;
-use rustc::session::{self, config};
-use rustc::middle::cstore::DummyCrateStore;
-
-use std::rc::Rc;
-use syntax::ast;
-use syntax::codemap;
-use syntax::parse::token::{self, BinOpToken, DelimToken, Lit, Token};
-use syntax::parse::lexer::TokenAndSpan;
-use syntax_pos::Pos;
-
-use syntax::symbol::{Symbol, keywords};
-
-fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
-    fn id() -> token::Token {
-        Token::Ident(ast::Ident::with_empty_ctxt(keywords::Invalid.name()))
-    }
-
-    let mut res = HashMap::new();
-
-    res.insert("-1".to_string(), Token::Eof);
-
-    for line in file.split('\n') {
-        let eq = match line.trim().rfind('=') {
-            Some(val) => val,
-            None => continue
-        };
-
-        let val = &line[..eq];
-        let num = &line[eq + 1..];
-
-        let tok = match val {
-            "SHR"               => Token::BinOp(BinOpToken::Shr),
-            "DOLLAR"            => Token::Dollar,
-            "LT"                => Token::Lt,
-            "STAR"              => Token::BinOp(BinOpToken::Star),
-            "FLOAT_SUFFIX"      => id(),
-            "INT_SUFFIX"        => id(),
-            "SHL"               => Token::BinOp(BinOpToken::Shl),
-            "LBRACE"            => Token::OpenDelim(DelimToken::Brace),
-            "RARROW"            => Token::RArrow,
-            "LIT_STR"           => Token::Literal(Lit::Str_(keywords::Invalid.name()), None),
-            "DOTDOT"            => Token::DotDot,
-            "MOD_SEP"           => Token::ModSep,
-            "DOTDOTDOT"         => Token::DotDotDot,
-            "NOT"               => Token::Not,
-            "AND"               => Token::BinOp(BinOpToken::And),
-            "LPAREN"            => Token::OpenDelim(DelimToken::Paren),
-            "ANDAND"            => Token::AndAnd,
-            "AT"                => Token::At,
-            "LBRACKET"          => Token::OpenDelim(DelimToken::Bracket),
-            "LIT_STR_RAW"       => Token::Literal(Lit::StrRaw(keywords::Invalid.name(), 0), None),
-            "RPAREN"            => Token::CloseDelim(DelimToken::Paren),
-            "SLASH"             => Token::BinOp(BinOpToken::Slash),
-            "COMMA"             => Token::Comma,
-            "LIFETIME"          => Token::Lifetime(
-                                            ast::Ident::with_empty_ctxt(keywords::Invalid.name())),
-            "CARET"             => Token::BinOp(BinOpToken::Caret),
-            "TILDE"             => Token::Tilde,
-            "IDENT"             => id(),
-            "PLUS"              => Token::BinOp(BinOpToken::Plus),
-            "LIT_CHAR"          => Token::Literal(Lit::Char(keywords::Invalid.name()), None),
-            "LIT_BYTE"          => Token::Literal(Lit::Byte(keywords::Invalid.name()), None),
-            "EQ"                => Token::Eq,
-            "RBRACKET"          => Token::CloseDelim(DelimToken::Bracket),
-            "COMMENT"           => Token::Comment,
-            "DOC_COMMENT"       => Token::DocComment(keywords::Invalid.name()),
-            "DOT"               => Token::Dot,
-            "EQEQ"              => Token::EqEq,
-            "NE"                => Token::Ne,
-            "GE"                => Token::Ge,
-            "PERCENT"           => Token::BinOp(BinOpToken::Percent),
-            "RBRACE"            => Token::CloseDelim(DelimToken::Brace),
-            "BINOP"             => Token::BinOp(BinOpToken::Plus),
-            "POUND"             => Token::Pound,
-            "OROR"              => Token::OrOr,
-            "LIT_INTEGER"       => Token::Literal(Lit::Integer(keywords::Invalid.name()), None),
-            "BINOPEQ"           => Token::BinOpEq(BinOpToken::Plus),
-            "LIT_FLOAT"         => Token::Literal(Lit::Float(keywords::Invalid.name()), None),
-            "WHITESPACE"        => Token::Whitespace,
-            "UNDERSCORE"        => Token::Underscore,
-            "MINUS"             => Token::BinOp(BinOpToken::Minus),
-            "SEMI"              => Token::Semi,
-            "COLON"             => Token::Colon,
-            "FAT_ARROW"         => Token::FatArrow,
-            "OR"                => Token::BinOp(BinOpToken::Or),
-            "GT"                => Token::Gt,
-            "LE"                => Token::Le,
-            "LIT_BINARY"        => Token::Literal(Lit::ByteStr(keywords::Invalid.name()), None),
-            "LIT_BINARY_RAW"    => Token::Literal(
-                                            Lit::ByteStrRaw(keywords::Invalid.name(), 0), None),
-            "QUESTION"          => Token::Question,
-            "SHEBANG"           => Token::Shebang(keywords::Invalid.name()),
-            _                   => continue,
-        };
-
-        res.insert(num.to_string(), tok);
-    }
-
-    debug!("Token map: {:?}", res);
-    res
-}
-
-fn str_to_binop(s: &str) -> token::BinOpToken {
-    match s {
-        "+"     => BinOpToken::Plus,
-        "/"     => BinOpToken::Slash,
-        "-"     => BinOpToken::Minus,
-        "*"     => BinOpToken::Star,
-        "%"     => BinOpToken::Percent,
-        "^"     => BinOpToken::Caret,
-        "&"     => BinOpToken::And,
-        "|"     => BinOpToken::Or,
-        "<<"    => BinOpToken::Shl,
-        ">>"    => BinOpToken::Shr,
-        _       => panic!("Bad binop str `{}`", s),
-    }
-}
-
-/// Assuming a string/byte string literal, strip out the leading/trailing
-/// hashes and surrounding quotes/raw/byte prefix.
-fn fix(mut lit: &str) -> ast::Name {
-    let prefix: Vec<char> = lit.chars().take(2).collect();
-    if prefix[0] == 'r' {
-        if prefix[1] == 'b' {
-            lit = &lit[2..]
-        } else {
-            lit = &lit[1..];
-        }
-    } else if prefix[0] == 'b' {
-        lit = &lit[1..];
-    }
-
-    let leading_hashes = count(lit);
-
-    // +1/-1 to adjust for single quotes
-    Symbol::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1])
-}
-
-/// Assuming a char/byte literal, strip the 'b' prefix and the single quotes.
-fn fixchar(mut lit: &str) -> ast::Name {
-    let prefix = lit.chars().next().unwrap();
-    if prefix == 'b' {
-        lit = &lit[1..];
-    }
-
-    Symbol::intern(&lit[1..lit.len() - 1])
-}
-
-fn count(lit: &str) -> usize {
-    lit.chars().take_while(|c| *c == '#').count()
-}
-
-fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>, surrogate_pairs_pos: &[usize],
-                     has_bom: bool)
-                     -> TokenAndSpan {
-    // old regex:
-    // \[@(?P<seq>\d+),(?P<start>\d+):(?P<end>\d+)='(?P<content>.+?)',<(?P<toknum>-?\d+)>,\d+:\d+]
-    let start = s.find("[@").unwrap();
-    let comma = start + s[start..].find(",").unwrap();
-    let colon = comma + s[comma..].find(":").unwrap();
-    let content_start = colon + s[colon..].find("='").unwrap();
-    // Use rfind instead of find, because we don't want to stop at the content
-    let content_end = content_start + s[content_start..].rfind("',<").unwrap();
-    let toknum_end = content_end + s[content_end..].find(">,").unwrap();
-
-    let start = &s[comma + 1 .. colon];
-    let end = &s[colon + 1 .. content_start];
-    let content = &s[content_start + 2 .. content_end];
-    let toknum = &s[content_end + 3 .. toknum_end];
-
-    let not_found = format!("didn't find token {:?} in the map", toknum);
-    let proto_tok = tokens.get(toknum).expect(&not_found);
-
-    let nm = Symbol::intern(content);
-
-    debug!("What we got: content (`{}`), proto: {:?}", content, proto_tok);
-
-    let real_tok = match *proto_tok {
-        Token::BinOp(..)           => Token::BinOp(str_to_binop(content)),
-        Token::BinOpEq(..)         => Token::BinOpEq(str_to_binop(&content[..content.len() - 1])),
-        Token::Literal(Lit::Str_(..), n)      => Token::Literal(Lit::Str_(fix(content)), n),
-        Token::Literal(Lit::StrRaw(..), n)    => Token::Literal(Lit::StrRaw(fix(content),
-                                                                             count(content)), n),
-        Token::Literal(Lit::Char(..), n)      => Token::Literal(Lit::Char(fixchar(content)), n),
-        Token::Literal(Lit::Byte(..), n)      => Token::Literal(Lit::Byte(fixchar(content)), n),
-        Token::DocComment(..)      => Token::DocComment(nm),
-        Token::Literal(Lit::Integer(..), n)   => Token::Literal(Lit::Integer(nm), n),
-        Token::Literal(Lit::Float(..), n)     => Token::Literal(Lit::Float(nm), n),
-        Token::Literal(Lit::ByteStr(..), n)    => Token::Literal(Lit::ByteStr(nm), n),
-        Token::Literal(Lit::ByteStrRaw(..), n) => Token::Literal(Lit::ByteStrRaw(fix(content),
-                                                                                count(content)), n),
-        Token::Ident(..)           => Token::Ident(ast::Ident::with_empty_ctxt(nm)),
-        Token::Lifetime(..)        => Token::Lifetime(ast::Ident::with_empty_ctxt(nm)),
-        ref t => t.clone()
-    };
-
-    let start_offset = if real_tok == Token::Eof {
-        1
-    } else {
-        0
-    };
-
-    let offset = if has_bom { 1 } else { 0 };
-
-    let mut lo = start.parse::<u32>().unwrap() - start_offset - offset;
-    let mut hi = end.parse::<u32>().unwrap() + 1 - offset;
-
-    // Adjust the span: For each surrogate pair already encountered, subtract one position.
-    lo -= surrogate_pairs_pos.binary_search(&(lo as usize)).unwrap_or_else(|x| x) as u32;
-    hi -= surrogate_pairs_pos.binary_search(&(hi as usize)).unwrap_or_else(|x| x) as u32;
-
-    let sp = syntax_pos::Span {
-        lo: syntax_pos::BytePos(lo),
-        hi: syntax_pos::BytePos(hi),
-        expn_id: syntax_pos::NO_EXPANSION
-    };
-
-    TokenAndSpan {
-        tok: real_tok,
-        sp: sp
-    }
-}
-
-fn tok_cmp(a: &token::Token, b: &token::Token) -> bool {
-    match a {
-        &Token::Ident(id) => match b {
-                &Token::Ident(id2) => id == id2,
-                _ => false
-        },
-        _ => a == b
-    }
-}
-
-fn span_cmp(antlr_sp: codemap::Span, rust_sp: codemap::Span, cm: &codemap::CodeMap) -> bool {
-    antlr_sp.expn_id == rust_sp.expn_id &&
-        antlr_sp.lo.to_usize() == cm.bytepos_to_file_charpos(rust_sp.lo).to_usize() &&
-        antlr_sp.hi.to_usize() == cm.bytepos_to_file_charpos(rust_sp.hi).to_usize()
-}
-
-fn main() {
-    fn next(r: &mut lexer::StringReader) -> TokenAndSpan {
-        use syntax::parse::lexer::Reader;
-        r.next_token()
-    }
-
-    let mut args = env::args().skip(1);
-    let filename = args.next().unwrap();
-    if filename.find("parse-fail").is_some() {
-        return;
-    }
-
-    // Rust's lexer
-    let mut code = String::new();
-    File::open(&Path::new(&filename)).unwrap().read_to_string(&mut code).unwrap();
-
-    let surrogate_pairs_pos: Vec<usize> = code.chars().enumerate()
-                                                     .filter(|&(_, c)| c as usize > 0xFFFF)
-                                                     .map(|(n, _)| n)
-                                                     .enumerate()
-                                                     .map(|(x, n)| x + n)
-                                                     .collect();
-
-    let has_bom = code.starts_with("\u{feff}");
-
-    debug!("Pairs: {:?}", surrogate_pairs_pos);
-
-    let options = config::basic_options();
-    let session = session::build_session(options, &DepGraph::new(false), None,
-                                         syntax::errors::registry::Registry::new(&[]),
-                                         Rc::new(DummyCrateStore));
-    let filemap = session.parse_sess.codemap()
-                         .new_filemap("<n/a>".to_string(), code);
-    let mut lexer = lexer::StringReader::new(session.diagnostic(), filemap);
-    let cm = session.codemap();
-
-    // ANTLR
-    let mut token_file = File::open(&Path::new(&args.next().unwrap())).unwrap();
-    let mut token_list = String::new();
-    token_file.read_to_string(&mut token_list).unwrap();
-    let token_map = parse_token_list(&token_list);
-
-    let stdin = std::io::stdin();
-    let lock = stdin.lock();
-    let lines = lock.lines();
-    let antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().trim(),
-                                                       &token_map,
-                                                       &surrogate_pairs_pos,
-                                                       has_bom));
-
-    for antlr_tok in antlr_tokens {
-        let rustc_tok = next(&mut lexer);
-        if rustc_tok.tok == Token::Eof && antlr_tok.tok == Token::Eof {
-            continue
-        }
-
-        assert!(span_cmp(antlr_tok.sp, rustc_tok.sp, cm), "{:?} and {:?} have different spans",
-                rustc_tok,
-                antlr_tok);
-
-        macro_rules! matches {
-            ( $($x:pat),+ ) => (
-                match rustc_tok.tok {
-                    $($x => match antlr_tok.tok {
-                        $x => {
-                            if !tok_cmp(&rustc_tok.tok, &antlr_tok.tok) {
-                                // FIXME #15677: needs more robust escaping in
-                                // antlr
-                                warn!("Different names for {:?} and {:?}", rustc_tok, antlr_tok);
-                            }
-                        }
-                        _ => panic!("{:?} is not {:?}", antlr_tok, rustc_tok)
-                    },)*
-                    ref c => assert!(c == &antlr_tok.tok, "{:?} is not {:?}", antlr_tok, rustc_tok)
-                }
-            )
-        }
-
-        matches!(
-            Token::Literal(Lit::Byte(..), _),
-            Token::Literal(Lit::Char(..), _),
-            Token::Literal(Lit::Integer(..), _),
-            Token::Literal(Lit::Float(..), _),
-            Token::Literal(Lit::Str_(..), _),
-            Token::Literal(Lit::StrRaw(..), _),
-            Token::Literal(Lit::ByteStr(..), _),
-            Token::Literal(Lit::ByteStrRaw(..), _),
-            Token::Ident(..),
-            Token::Lifetime(..),
-            Token::Interpolated(..),
-            Token::DocComment(..),
-            Token::Shebang(..)
-        );
-    }
-}
diff --git a/src/grammar/xidcontinue.g4 b/src/grammar/xidcontinue.g4
deleted file mode 100644
index f3a1a3b40f9..00000000000
--- a/src/grammar/xidcontinue.g4
+++ /dev/null
@@ -1,473 +0,0 @@
-lexer grammar Xidcontinue;
-
-fragment XID_Continue:
-      '\u0030' .. '\u0039'
-    | '\u0041' .. '\u005a'
-    | '\u005f'
-    | '\u0061' .. '\u007a'
-    | '\u00aa'
-    | '\u00b5'
-    | '\u00b7'
-    | '\u00ba'
-    | '\u00c0' .. '\u00d6'
-    | '\u00d8' .. '\u00f6'
-    | '\u00f8' .. '\u0236'
-    | '\u0250' .. '\u02c1'
-    | '\u02c6' .. '\u02d1'
-    | '\u02e0' .. '\u02e4'
-    | '\u02ee'
-    | '\u0300' .. '\u0357'
-    | '\u035d' .. '\u036f'
-    | '\u0386'
-    | '\u0388' .. '\u038a'
-    | '\u038c'
-    | '\u038e' .. '\u03a1'
-    | '\u03a3' .. '\u03ce'
-    | '\u03d0' .. '\u03f5'
-    | '\u03f7' .. '\u03fb'
-    | '\u0400' .. '\u0481'
-    | '\u0483' .. '\u0486'
-    | '\u048a' .. '\u04ce'
-    | '\u04d0' .. '\u04f5'
-    | '\u04f8' .. '\u04f9'
-    | '\u0500' .. '\u050f'
-    | '\u0531' .. '\u0556'
-    | '\u0559'
-    | '\u0561' .. '\u0587'
-    | '\u0591' .. '\u05a1'
-    | '\u05a3' .. '\u05b9'
-    | '\u05bb' .. '\u05bd'
-    | '\u05bf'
-    | '\u05c1' .. '\u05c2'
-    | '\u05c4'
-    | '\u05d0' .. '\u05ea'
-    | '\u05f0' .. '\u05f2'
-    | '\u0610' .. '\u0615'
-    | '\u0621' .. '\u063a'
-    | '\u0640' .. '\u0658'
-    | '\u0660' .. '\u0669'
-    | '\u066e' .. '\u06d3'
-    | '\u06d5' .. '\u06dc'
-    | '\u06df' .. '\u06e8'
-    | '\u06ea' .. '\u06fc'
-    | '\u06ff'
-    | '\u0710' .. '\u074a'
-    | '\u074d' .. '\u074f'
-    | '\u0780' .. '\u07b1'
-    | '\u0901' .. '\u0939'
-    | '\u093c' .. '\u094d'
-    | '\u0950' .. '\u0954'
-    | '\u0958' .. '\u0963'
-    | '\u0966' .. '\u096f'
-    | '\u0981' .. '\u0983'
-    | '\u0985' .. '\u098c'
-    | '\u098f' .. '\u0990'
-    | '\u0993' .. '\u09a8'
-    | '\u09aa' .. '\u09b0'
-    | '\u09b2'
-    | '\u09b6' .. '\u09b9'
-    | '\u09bc' .. '\u09c4'
-    | '\u09c7' .. '\u09c8'
-    | '\u09cb' .. '\u09cd'
-    | '\u09d7'
-    | '\u09dc' .. '\u09dd'
-    | '\u09df' .. '\u09e3'
-    | '\u09e6' .. '\u09f1'
-    | '\u0a01' .. '\u0a03'
-    | '\u0a05' .. '\u0a0a'
-    | '\u0a0f' .. '\u0a10'
-    | '\u0a13' .. '\u0a28'
-    | '\u0a2a' .. '\u0a30'
-    | '\u0a32' .. '\u0a33'
-    | '\u0a35' .. '\u0a36'
-    | '\u0a38' .. '\u0a39'
-    | '\u0a3c'
-    | '\u0a3e' .. '\u0a42'
-    | '\u0a47' .. '\u0a48'
-    | '\u0a4b' .. '\u0a4d'
-    | '\u0a59' .. '\u0a5c'
-    | '\u0a5e'
-    | '\u0a66' .. '\u0a74'
-    | '\u0a81' .. '\u0a83'
-    | '\u0a85' .. '\u0a8d'
-    | '\u0a8f' .. '\u0a91'
-    | '\u0a93' .. '\u0aa8'
-    | '\u0aaa' .. '\u0ab0'
-    | '\u0ab2' .. '\u0ab3'
-    | '\u0ab5' .. '\u0ab9'
-    | '\u0abc' .. '\u0ac5'
-    | '\u0ac7' .. '\u0ac9'
-    | '\u0acb' .. '\u0acd'
-    | '\u0ad0'
-    | '\u0ae0' .. '\u0ae3'
-    | '\u0ae6' .. '\u0aef'
-    | '\u0b01' .. '\u0b03'
-    | '\u0b05' .. '\u0b0c'
-    | '\u0b0f' .. '\u0b10'
-    | '\u0b13' .. '\u0b28'
-    | '\u0b2a' .. '\u0b30'
-    | '\u0b32' .. '\u0b33'
-    | '\u0b35' .. '\u0b39'
-    | '\u0b3c' .. '\u0b43'
-    | '\u0b47' .. '\u0b48'
-    | '\u0b4b' .. '\u0b4d'
-    | '\u0b56' .. '\u0b57'
-    | '\u0b5c' .. '\u0b5d'
-    | '\u0b5f' .. '\u0b61'
-    | '\u0b66' .. '\u0b6f'
-    | '\u0b71'
-    | '\u0b82' .. '\u0b83'
-    | '\u0b85' .. '\u0b8a'
-    | '\u0b8e' .. '\u0b90'
-    | '\u0b92' .. '\u0b95'
-    | '\u0b99' .. '\u0b9a'
-    | '\u0b9c'
-    | '\u0b9e' .. '\u0b9f'
-    | '\u0ba3' .. '\u0ba4'
-    | '\u0ba8' .. '\u0baa'
-    | '\u0bae' .. '\u0bb5'
-    | '\u0bb7' .. '\u0bb9'
-    | '\u0bbe' .. '\u0bc2'
-    | '\u0bc6' .. '\u0bc8'
-    | '\u0bca' .. '\u0bcd'
-    | '\u0bd7'
-    | '\u0be7' .. '\u0bef'
-    | '\u0c01' .. '\u0c03'
-    | '\u0c05' .. '\u0c0c'
-    | '\u0c0e' .. '\u0c10'
-    | '\u0c12' .. '\u0c28'
-    | '\u0c2a' .. '\u0c33'
-    | '\u0c35' .. '\u0c39'
-    | '\u0c3e' .. '\u0c44'
-    | '\u0c46' .. '\u0c48'
-    | '\u0c4a' .. '\u0c4d'
-    | '\u0c55' .. '\u0c56'
-    | '\u0c60' .. '\u0c61'
-    | '\u0c66' .. '\u0c6f'
-    | '\u0c82' .. '\u0c83'
-    | '\u0c85' .. '\u0c8c'
-    | '\u0c8e' .. '\u0c90'
-    | '\u0c92' .. '\u0ca8'
-    | '\u0caa' .. '\u0cb3'
-    | '\u0cb5' .. '\u0cb9'
-    | '\u0cbc' .. '\u0cc4'
-    | '\u0cc6' .. '\u0cc8'
-    | '\u0cca' .. '\u0ccd'
-    | '\u0cd5' .. '\u0cd6'
-    | '\u0cde'
-    | '\u0ce0' .. '\u0ce1'
-    | '\u0ce6' .. '\u0cef'
-    | '\u0d02' .. '\u0d03'
-    | '\u0d05' .. '\u0d0c'
-    | '\u0d0e' .. '\u0d10'
-    | '\u0d12' .. '\u0d28'
-    | '\u0d2a' .. '\u0d39'
-    | '\u0d3e' .. '\u0d43'
-    | '\u0d46' .. '\u0d48'
-    | '\u0d4a' .. '\u0d4d'
-    | '\u0d57'
-    | '\u0d60' .. '\u0d61'
-    | '\u0d66' .. '\u0d6f'
-    | '\u0d82' .. '\u0d83'
-    | '\u0d85' .. '\u0d96'
-    | '\u0d9a' .. '\u0db1'
-    | '\u0db3' .. '\u0dbb'
-    | '\u0dbd'
-    | '\u0dc0' .. '\u0dc6'
-    | '\u0dca'
-    | '\u0dcf' .. '\u0dd4'
-    | '\u0dd6'
-    | '\u0dd8' .. '\u0ddf'
-    | '\u0df2' .. '\u0df3'
-    | '\u0e01' .. '\u0e3a'
-    | '\u0e40' .. '\u0e4e'
-    | '\u0e50' .. '\u0e59'
-    | '\u0e81' .. '\u0e82'
-    | '\u0e84'
-    | '\u0e87' .. '\u0e88'
-    | '\u0e8a'
-    | '\u0e8d'
-    | '\u0e94' .. '\u0e97'
-    | '\u0e99' .. '\u0e9f'
-    | '\u0ea1' .. '\u0ea3'
-    | '\u0ea5'
-    | '\u0ea7'
-    | '\u0eaa' .. '\u0eab'
-    | '\u0ead' .. '\u0eb9'
-    | '\u0ebb' .. '\u0ebd'
-    | '\u0ec0' .. '\u0ec4'
-    | '\u0ec6'
-    | '\u0ec8' .. '\u0ecd'
-    | '\u0ed0' .. '\u0ed9'
-    | '\u0edc' .. '\u0edd'
-    | '\u0f00'
-    | '\u0f18' .. '\u0f19'
-    | '\u0f20' .. '\u0f29'
-    | '\u0f35'
-    | '\u0f37'
-    | '\u0f39'
-    | '\u0f3e' .. '\u0f47'
-    | '\u0f49' .. '\u0f6a'
-    | '\u0f71' .. '\u0f84'
-    | '\u0f86' .. '\u0f8b'
-    | '\u0f90' .. '\u0f97'
-    | '\u0f99' .. '\u0fbc'
-    | '\u0fc6'
-    | '\u1000' .. '\u1021'
-    | '\u1023' .. '\u1027'
-    | '\u1029' .. '\u102a'
-    | '\u102c' .. '\u1032'
-    | '\u1036' .. '\u1039'
-    | '\u1040' .. '\u1049'
-    | '\u1050' .. '\u1059'
-    | '\u10a0' .. '\u10c5'
-    | '\u10d0' .. '\u10f8'
-    | '\u1100' .. '\u1159'
-    | '\u115f' .. '\u11a2'
-    | '\u11a8' .. '\u11f9'
-    | '\u1200' .. '\u1206'
-    | '\u1208' .. '\u1246'
-    | '\u1248'
-    | '\u124a' .. '\u124d'
-    | '\u1250' .. '\u1256'
-    | '\u1258'
-    | '\u125a' .. '\u125d'
-    | '\u1260' .. '\u1286'
-    | '\u1288'
-    | '\u128a' .. '\u128d'
-    | '\u1290' .. '\u12ae'
-    | '\u12b0'
-    | '\u12b2' .. '\u12b5'
-    | '\u12b8' .. '\u12be'
-    | '\u12c0'
-    | '\u12c2' .. '\u12c5'
-    | '\u12c8' .. '\u12ce'
-    | '\u12d0' .. '\u12d6'
-    | '\u12d8' .. '\u12ee'
-    | '\u12f0' .. '\u130e'
-    | '\u1310'
-    | '\u1312' .. '\u1315'
-    | '\u1318' .. '\u131e'
-    | '\u1320' .. '\u1346'
-    | '\u1348' .. '\u135a'
-    | '\u1369' .. '\u1371'
-    | '\u13a0' .. '\u13f4'
-    | '\u1401' .. '\u166c'
-    | '\u166f' .. '\u1676'
-    | '\u1681' .. '\u169a'
-    | '\u16a0' .. '\u16ea'
-    | '\u16ee' .. '\u16f0'
-    | '\u1700' .. '\u170c'
-    | '\u170e' .. '\u1714'
-    | '\u1720' .. '\u1734'
-    | '\u1740' .. '\u1753'
-    | '\u1760' .. '\u176c'
-    | '\u176e' .. '\u1770'
-    | '\u1772' .. '\u1773'
-    | '\u1780' .. '\u17b3'
-    | '\u17b6' .. '\u17d3'
-    | '\u17d7'
-    | '\u17dc' .. '\u17dd'
-    | '\u17e0' .. '\u17e9'
-    | '\u180b' .. '\u180d'
-    | '\u1810' .. '\u1819'
-    | '\u1820' .. '\u1877'
-    | '\u1880' .. '\u18a9'
-    | '\u1900' .. '\u191c'
-    | '\u1920' .. '\u192b'
-    | '\u1930' .. '\u193b'
-    | '\u1946' .. '\u196d'
-    | '\u1970' .. '\u1974'
-    | '\u1d00' .. '\u1d6b'
-    | '\u1e00' .. '\u1e9b'
-    | '\u1ea0' .. '\u1ef9'
-    | '\u1f00' .. '\u1f15'
-    | '\u1f18' .. '\u1f1d'
-    | '\u1f20' .. '\u1f45'
-    | '\u1f48' .. '\u1f4d'
-    | '\u1f50' .. '\u1f57'
-    | '\u1f59'
-    | '\u1f5b'
-    | '\u1f5d'
-    | '\u1f5f' .. '\u1f7d'
-    | '\u1f80' .. '\u1fb4'
-    | '\u1fb6' .. '\u1fbc'
-    | '\u1fbe'
-    | '\u1fc2' .. '\u1fc4'
-    | '\u1fc6' .. '\u1fcc'
-    | '\u1fd0' .. '\u1fd3'
-    | '\u1fd6' .. '\u1fdb'
-    | '\u1fe0' .. '\u1fec'
-    | '\u1ff2' .. '\u1ff4'
-    | '\u1ff6' .. '\u1ffc'
-    | '\u203f' .. '\u2040'
-    | '\u2054'
-    | '\u2071'
-    | '\u207f'
-    | '\u20d0' .. '\u20dc'
-    | '\u20e1'
-    | '\u20e5' .. '\u20ea'
-    | '\u2102'
-    | '\u2107'
-    | '\u210a' .. '\u2113'
-    | '\u2115'
-    | '\u2118' .. '\u211d'
-    | '\u2124'
-    | '\u2126'
-    | '\u2128'
-    | '\u212a' .. '\u2131'
-    | '\u2133' .. '\u2139'
-    | '\u213d' .. '\u213f'
-    | '\u2145' .. '\u2149'
-    | '\u2160' .. '\u2183'
-    | '\u3005' .. '\u3007'
-    | '\u3021' .. '\u302f'
-    | '\u3031' .. '\u3035'
-    | '\u3038' .. '\u303c'
-    | '\u3041' .. '\u3096'
-    | '\u3099' .. '\u309a'
-    | '\u309d' .. '\u309f'
-    | '\u30a1' .. '\u30ff'
-    | '\u3105' .. '\u312c'
-    | '\u3131' .. '\u318e'
-    | '\u31a0' .. '\u31b7'
-    | '\u31f0' .. '\u31ff'
-    | '\u3400' .. '\u4db5'
-    | '\u4e00' .. '\u9fa5'
-    | '\ua000' .. '\ua48c'
-    | '\uac00' .. '\ud7a3'
-    | '\uf900' .. '\ufa2d'
-    | '\ufa30' .. '\ufa6a'
-    | '\ufb00' .. '\ufb06'
-    | '\ufb13' .. '\ufb17'
-    | '\ufb1d' .. '\ufb28'
-    | '\ufb2a' .. '\ufb36'
-    | '\ufb38' .. '\ufb3c'
-    | '\ufb3e'
-    | '\ufb40' .. '\ufb41'
-    | '\ufb43' .. '\ufb44'
-    | '\ufb46' .. '\ufbb1'
-    | '\ufbd3' .. '\ufc5d'
-    | '\ufc64' .. '\ufd3d'
-    | '\ufd50' .. '\ufd8f'
-    | '\ufd92' .. '\ufdc7'
-    | '\ufdf0' .. '\ufdf9'
-    | '\ufe00' .. '\ufe0f'
-    | '\ufe20' .. '\ufe23'
-    | '\ufe33' .. '\ufe34'
-    | '\ufe4d' .. '\ufe4f'
-    | '\ufe71'
-    | '\ufe73'
-    | '\ufe77'
-    | '\ufe79'
-    | '\ufe7b'
-    | '\ufe7d'
-    | '\ufe7f' .. '\ufefc'
-    | '\uff10' .. '\uff19'
-    | '\uff21' .. '\uff3a'
-    | '\uff3f'
-    | '\uff41' .. '\uff5a'
-    | '\uff65' .. '\uffbe'
-    | '\uffc2' .. '\uffc7'
-    | '\uffca' .. '\uffcf'
-    | '\uffd2' .. '\uffd7'
-    | '\uffda' .. '\uffdc'
-    | '\ud800' '\udc00' .. '\udc0a'
-    | '\ud800' '\udc0d' .. '\udc25'
-    | '\ud800' '\udc28' .. '\udc39'
-    | '\ud800' '\udc3c' .. '\udc3c'
-    | '\ud800' '\udc3f' .. '\udc4c'
-    | '\ud800' '\udc50' .. '\udc5c'
-    | '\ud800' '\udc80' .. '\udcf9'
-    | '\ud800' '\udf00' .. '\udf1d'
-    | '\ud800' '\udf30' .. '\udf49'
-    | '\ud800' '\udf80' .. '\udf9c'
-    | '\ud801' '\ue000' .. '\ue09c'
-    | '\ud801' '\ue0a0' .. '\ue0a8'
-    | '\ud802' '\ue400' .. '\ue404'
-    | '\ud802' '\u0808'
-    | '\ud802' '\ue40a' .. '\ue434'
-    | '\ud802' '\ue437' .. '\ue437'
-    | '\ud802' '\u083c'
-    | '\ud802' '\u083f'
-    | '\ud834' '\uad65' .. '\uad68'
-    | '\ud834' '\uad6d' .. '\uad71'
-    | '\ud834' '\uad7b' .. '\uad81'
-    | '\ud834' '\uad85' .. '\uad8a'
-    | '\ud834' '\uadaa' .. '\uadac'
-    | '\ud835' '\ub000' .. '\ub053'
-    | '\ud835' '\ub056' .. '\ub09b'
-    | '\ud835' '\ub09e' .. '\ub09e'
-    | '\ud835' '\ud4a2'
-    | '\ud835' '\ub0a5' .. '\ub0a5'
-    | '\ud835' '\ub0a9' .. '\ub0ab'
-    | '\ud835' '\ub0ae' .. '\ub0b8'
-    | '\ud835' '\ud4bb'
-    | '\ud835' '\ub0bd' .. '\ub0c2'
-    | '\ud835' '\ub0c5' .. '\ub104'
-    | '\ud835' '\ub107' .. '\ub109'
-    | '\ud835' '\ub10d' .. '\ub113'
-    | '\ud835' '\ub116' .. '\ub11b'
-    | '\ud835' '\ub11e' .. '\ub138'
-    | '\ud835' '\ub13b' .. '\ub13d'
-    | '\ud835' '\ub140' .. '\ub143'
-    | '\ud835' '\ud546'
-    | '\ud835' '\ub14a' .. '\ub14f'
-    | '\ud835' '\ub152' .. '\ub2a2'
-    | '\ud835' '\ub2a8' .. '\ub2bf'
-    | '\ud835' '\ub2c2' .. '\ub2d9'
-    | '\ud835' '\ub2dc' .. '\ub2f9'
-    | '\ud835' '\ub2fc' .. '\ub313'
-    | '\ud835' '\ub316' .. '\ub333'
-    | '\ud835' '\ub336' .. '\ub34d'
-    | '\ud835' '\ub350' .. '\ub36d'
-    | '\ud835' '\ub370' .. '\ub387'
-    | '\ud835' '\ub38a' .. '\ub3a7'
-    | '\ud835' '\ub3aa' .. '\ub3c1'
-    | '\ud835' '\ub3c4' .. '\ub3c8'
-    | '\ud835' '\ub3ce' .. '\ub3fe'
-    | '\ud840' '\udc00' .. '\udffe'
-    | '\ud841' '\ue000' .. '\ue3fe'
-    | '\ud842' '\ue400' .. '\ue7fe'
-    | '\ud843' '\ue800' .. '\uebfe'
-    | '\ud844' '\uec00' .. '\ueffe'
-    | '\ud845' '\uf000' .. '\uf3fe'
-    | '\ud846' '\uf400' .. '\uf7fe'
-    | '\ud847' '\uf800' .. '\ufbfe'
-    | '\ud848' '\ufc00' .. '\ufffe'
-    | '\ud849' '\u0000' .. '\u03fe'
-    | '\ud84a' '\u0400' .. '\u07fe'
-    | '\ud84b' '\u0800' .. '\u0bfe'
-    | '\ud84c' '\u0c00' .. '\u0ffe'
-    | '\ud84d' '\u1000' .. '\u13fe'
-    | '\ud84e' '\u1400' .. '\u17fe'
-    | '\ud84f' '\u1800' .. '\u1bfe'
-    | '\ud850' '\u1c00' .. '\u1ffe'
-    | '\ud851' '\u2000' .. '\u23fe'
-    | '\ud852' '\u2400' .. '\u27fe'
-    | '\ud853' '\u2800' .. '\u2bfe'
-    | '\ud854' '\u2c00' .. '\u2ffe'
-    | '\ud855' '\u3000' .. '\u33fe'
-    | '\ud856' '\u3400' .. '\u37fe'
-    | '\ud857' '\u3800' .. '\u3bfe'
-    | '\ud858' '\u3c00' .. '\u3ffe'
-    | '\ud859' '\u4000' .. '\u43fe'
-    | '\ud85a' '\u4400' .. '\u47fe'
-    | '\ud85b' '\u4800' .. '\u4bfe'
-    | '\ud85c' '\u4c00' .. '\u4ffe'
-    | '\ud85d' '\u5000' .. '\u53fe'
-    | '\ud85e' '\u5400' .. '\u57fe'
-    | '\ud85f' '\u5800' .. '\u5bfe'
-    | '\ud860' '\u5c00' .. '\u5ffe'
-    | '\ud861' '\u6000' .. '\u63fe'
-    | '\ud862' '\u6400' .. '\u67fe'
-    | '\ud863' '\u6800' .. '\u6bfe'
-    | '\ud864' '\u6c00' .. '\u6ffe'
-    | '\ud865' '\u7000' .. '\u73fe'
-    | '\ud866' '\u7400' .. '\u77fe'
-    | '\ud867' '\u7800' .. '\u7bfe'
-    | '\ud868' '\u7c00' .. '\u7ffe'
-    | '\ud869' '\u8000' .. '\u82d5'
-    | '\ud87e' '\ud400' .. '\ud61c'
-    | '\udb40' '\udd00' .. '\uddee'
-    ;
diff --git a/src/grammar/xidstart.g4 b/src/grammar/xidstart.g4
deleted file mode 100644
index 53fb50f4584..00000000000
--- a/src/grammar/xidstart.g4
+++ /dev/null
@@ -1,379 +0,0 @@
-lexer grammar Xidstart;
-
-fragment XID_Start :
-      '\u0041' .. '\u005a'
-    | '_'
-    | '\u0061' .. '\u007a'
-    | '\u00aa'
-    | '\u00b5'
-    | '\u00ba'
-    | '\u00c0' .. '\u00d6'
-    | '\u00d8' .. '\u00f6'
-    | '\u00f8' .. '\u0236'
-    | '\u0250' .. '\u02c1'
-    | '\u02c6' .. '\u02d1'
-    | '\u02e0' .. '\u02e4'
-    | '\u02ee'
-    | '\u0386'
-    | '\u0388' .. '\u038a'
-    | '\u038c'
-    | '\u038e' .. '\u03a1'
-    | '\u03a3' .. '\u03ce'
-    | '\u03d0' .. '\u03f5'
-    | '\u03f7' .. '\u03fb'
-    | '\u0400' .. '\u0481'
-    | '\u048a' .. '\u04ce'
-    | '\u04d0' .. '\u04f5'
-    | '\u04f8' .. '\u04f9'
-    | '\u0500' .. '\u050f'
-    | '\u0531' .. '\u0556'
-    | '\u0559'
-    | '\u0561' .. '\u0587'
-    | '\u05d0' .. '\u05ea'
-    | '\u05f0' .. '\u05f2'
-    | '\u0621' .. '\u063a'
-    | '\u0640' .. '\u064a'
-    | '\u066e' .. '\u066f'
-    | '\u0671' .. '\u06d3'
-    | '\u06d5'
-    | '\u06e5' .. '\u06e6'
-    | '\u06ee' .. '\u06ef'
-    | '\u06fa' .. '\u06fc'
-    | '\u06ff'
-    | '\u0710'
-    | '\u0712' .. '\u072f'
-    | '\u074d' .. '\u074f'
-    | '\u0780' .. '\u07a5'
-    | '\u07b1'
-    | '\u0904' .. '\u0939'
-    | '\u093d'
-    | '\u0950'
-    | '\u0958' .. '\u0961'
-    | '\u0985' .. '\u098c'
-    | '\u098f' .. '\u0990'
-    | '\u0993' .. '\u09a8'
-    | '\u09aa' .. '\u09b0'
-    | '\u09b2'
-    | '\u09b6' .. '\u09b9'
-    | '\u09bd'
-    | '\u09dc' .. '\u09dd'
-    | '\u09df' .. '\u09e1'
-    | '\u09f0' .. '\u09f1'
-    | '\u0a05' .. '\u0a0a'
-    | '\u0a0f' .. '\u0a10'
-    | '\u0a13' .. '\u0a28'
-    | '\u0a2a' .. '\u0a30'
-    | '\u0a32' .. '\u0a33'
-    | '\u0a35' .. '\u0a36'
-    | '\u0a38' .. '\u0a39'
-    | '\u0a59' .. '\u0a5c'
-    | '\u0a5e'
-    | '\u0a72' .. '\u0a74'
-    | '\u0a85' .. '\u0a8d'
-    | '\u0a8f' .. '\u0a91'
-    | '\u0a93' .. '\u0aa8'
-    | '\u0aaa' .. '\u0ab0'
-    | '\u0ab2' .. '\u0ab3'
-    | '\u0ab5' .. '\u0ab9'
-    | '\u0abd'
-    | '\u0ad0'
-    | '\u0ae0' .. '\u0ae1'
-    | '\u0b05' .. '\u0b0c'
-    | '\u0b0f' .. '\u0b10'
-    | '\u0b13' .. '\u0b28'
-    | '\u0b2a' .. '\u0b30'
-    | '\u0b32' .. '\u0b33'
-    | '\u0b35' .. '\u0b39'
-    | '\u0b3d'
-    | '\u0b5c' .. '\u0b5d'
-    | '\u0b5f' .. '\u0b61'
-    | '\u0b71'
-    | '\u0b83'
-    | '\u0b85' .. '\u0b8a'
-    | '\u0b8e' .. '\u0b90'
-    | '\u0b92' .. '\u0b95'
-    | '\u0b99' .. '\u0b9a'
-    | '\u0b9c'
-    | '\u0b9e' .. '\u0b9f'
-    | '\u0ba3' .. '\u0ba4'
-    | '\u0ba8' .. '\u0baa'
-    | '\u0bae' .. '\u0bb5'
-    | '\u0bb7' .. '\u0bb9'
-    | '\u0c05' .. '\u0c0c'
-    | '\u0c0e' .. '\u0c10'
-    | '\u0c12' .. '\u0c28'
-    | '\u0c2a' .. '\u0c33'
-    | '\u0c35' .. '\u0c39'
-    | '\u0c60' .. '\u0c61'
-    | '\u0c85' .. '\u0c8c'
-    | '\u0c8e' .. '\u0c90'
-    | '\u0c92' .. '\u0ca8'
-    | '\u0caa' .. '\u0cb3'
-    | '\u0cb5' .. '\u0cb9'
-    | '\u0cbd'
-    | '\u0cde'
-    | '\u0ce0' .. '\u0ce1'
-    | '\u0d05' .. '\u0d0c'
-    | '\u0d0e' .. '\u0d10'
-    | '\u0d12' .. '\u0d28'
-    | '\u0d2a' .. '\u0d39'
-    | '\u0d60' .. '\u0d61'
-    | '\u0d85' .. '\u0d96'
-    | '\u0d9a' .. '\u0db1'
-    | '\u0db3' .. '\u0dbb'
-    | '\u0dbd'
-    | '\u0dc0' .. '\u0dc6'
-    | '\u0e01' .. '\u0e30'
-    | '\u0e32'
-    | '\u0e40' .. '\u0e46'
-    | '\u0e81' .. '\u0e82'
-    | '\u0e84'
-    | '\u0e87' .. '\u0e88'
-    | '\u0e8a'
-    | '\u0e8d'
-    | '\u0e94' .. '\u0e97'
-    | '\u0e99' .. '\u0e9f'
-    | '\u0ea1' .. '\u0ea3'
-    | '\u0ea5'
-    | '\u0ea7'
-    | '\u0eaa' .. '\u0eab'
-    | '\u0ead' .. '\u0eb0'
-    | '\u0eb2'
-    | '\u0ebd'
-    | '\u0ec0' .. '\u0ec4'
-    | '\u0ec6'
-    | '\u0edc' .. '\u0edd'
-    | '\u0f00'
-    | '\u0f40' .. '\u0f47'
-    | '\u0f49' .. '\u0f6a'
-    | '\u0f88' .. '\u0f8b'
-    | '\u1000' .. '\u1021'
-    | '\u1023' .. '\u1027'
-    | '\u1029' .. '\u102a'
-    | '\u1050' .. '\u1055'
-    | '\u10a0' .. '\u10c5'
-    | '\u10d0' .. '\u10f8'
-    | '\u1100' .. '\u1159'
-    | '\u115f' .. '\u11a2'
-    | '\u11a8' .. '\u11f9'
-    | '\u1200' .. '\u1206'
-    | '\u1208' .. '\u1246'
-    | '\u1248'
-    | '\u124a' .. '\u124d'
-    | '\u1250' .. '\u1256'
-    | '\u1258'
-    | '\u125a' .. '\u125d'
-    | '\u1260' .. '\u1286'
-    | '\u1288'
-    | '\u128a' .. '\u128d'
-    | '\u1290' .. '\u12ae'
-    | '\u12b0'
-    | '\u12b2' .. '\u12b5'
-    | '\u12b8' .. '\u12be'
-    | '\u12c0'
-    | '\u12c2' .. '\u12c5'
-    | '\u12c8' .. '\u12ce'
-    | '\u12d0' .. '\u12d6'
-    | '\u12d8' .. '\u12ee'
-    | '\u12f0' .. '\u130e'
-    | '\u1310'
-    | '\u1312' .. '\u1315'
-    | '\u1318' .. '\u131e'
-    | '\u1320' .. '\u1346'
-    | '\u1348' .. '\u135a'
-    | '\u13a0' .. '\u13f4'
-    | '\u1401' .. '\u166c'
-    | '\u166f' .. '\u1676'
-    | '\u1681' .. '\u169a'
-    | '\u16a0' .. '\u16ea'
-    | '\u16ee' .. '\u16f0'
-    | '\u1700' .. '\u170c'
-    | '\u170e' .. '\u1711'
-    | '\u1720' .. '\u1731'
-    | '\u1740' .. '\u1751'
-    | '\u1760' .. '\u176c'
-    | '\u176e' .. '\u1770'
-    | '\u1780' .. '\u17b3'
-    | '\u17d7'
-    | '\u17dc'
-    | '\u1820' .. '\u1877'
-    | '\u1880' .. '\u18a8'
-    | '\u1900' .. '\u191c'
-    | '\u1950' .. '\u196d'
-    | '\u1970' .. '\u1974'
-    | '\u1d00' .. '\u1d6b'
-    | '\u1e00' .. '\u1e9b'
-    | '\u1ea0' .. '\u1ef9'
-    | '\u1f00' .. '\u1f15'
-    | '\u1f18' .. '\u1f1d'
-    | '\u1f20' .. '\u1f45'
-    | '\u1f48' .. '\u1f4d'
-    | '\u1f50' .. '\u1f57'
-    | '\u1f59'
-    | '\u1f5b'
-    | '\u1f5d'
-    | '\u1f5f' .. '\u1f7d'
-    | '\u1f80' .. '\u1fb4'
-    | '\u1fb6' .. '\u1fbc'
-    | '\u1fbe'
-    | '\u1fc2' .. '\u1fc4'
-    | '\u1fc6' .. '\u1fcc'
-    | '\u1fd0' .. '\u1fd3'
-    | '\u1fd6' .. '\u1fdb'
-    | '\u1fe0' .. '\u1fec'
-    | '\u1ff2' .. '\u1ff4'
-    | '\u1ff6' .. '\u1ffc'
-    | '\u2071'
-    | '\u207f'
-    | '\u2102'
-    | '\u2107'
-    | '\u210a' .. '\u2113'
-    | '\u2115'
-    | '\u2118' .. '\u211d'
-    | '\u2124'
-    | '\u2126'
-    | '\u2128'
-    | '\u212a' .. '\u2131'
-    | '\u2133' .. '\u2139'
-    | '\u213d' .. '\u213f'
-    | '\u2145' .. '\u2149'
-    | '\u2160' .. '\u2183'
-    | '\u3005' .. '\u3007'
-    | '\u3021' .. '\u3029'
-    | '\u3031' .. '\u3035'
-    | '\u3038' .. '\u303c'
-    | '\u3041' .. '\u3096'
-    | '\u309d' .. '\u309f'
-    | '\u30a1' .. '\u30fa'
-    | '\u30fc' .. '\u30ff'
-    | '\u3105' .. '\u312c'
-    | '\u3131' .. '\u318e'
-    | '\u31a0' .. '\u31b7'
-    | '\u31f0' .. '\u31ff'
-    | '\u3400' .. '\u4db5'
-    | '\u4e00' .. '\u9fa5'
-    | '\ua000' .. '\ua48c'
-    | '\uac00' .. '\ud7a3'
-    | '\uf900' .. '\ufa2d'
-    | '\ufa30' .. '\ufa6a'
-    | '\ufb00' .. '\ufb06'
-    | '\ufb13' .. '\ufb17'
-    | '\ufb1d'
-    | '\ufb1f' .. '\ufb28'
-    | '\ufb2a' .. '\ufb36'
-    | '\ufb38' .. '\ufb3c'
-    | '\ufb3e'
-    | '\ufb40' .. '\ufb41'
-    | '\ufb43' .. '\ufb44'
-    | '\ufb46' .. '\ufbb1'
-    | '\ufbd3' .. '\ufc5d'
-    | '\ufc64' .. '\ufd3d'
-    | '\ufd50' .. '\ufd8f'
-    | '\ufd92' .. '\ufdc7'
-    | '\ufdf0' .. '\ufdf9'
-    | '\ufe71'
-    | '\ufe73'
-    | '\ufe77'
-    | '\ufe79'
-    | '\ufe7b'
-    | '\ufe7d'
-    | '\ufe7f' .. '\ufefc'
-    | '\uff21' .. '\uff3a'
-    | '\uff41' .. '\uff5a'
-    | '\uff66' .. '\uff9d'
-    | '\uffa0' .. '\uffbe'
-    | '\uffc2' .. '\uffc7'
-    | '\uffca' .. '\uffcf'
-    | '\uffd2' .. '\uffd7'
-    | '\uffda' .. '\uffdc'
-    | '\ud800' '\udc00' .. '\udc0a'
-    | '\ud800' '\udc0d' .. '\udc25'
-    | '\ud800' '\udc28' .. '\udc39'
-    | '\ud800' '\udc3c' .. '\udc3c'
-    | '\ud800' '\udc3f' .. '\udc4c'
-    | '\ud800' '\udc50' .. '\udc5c'
-    | '\ud800' '\udc80' .. '\udcf9'
-    | '\ud800' '\udf00' .. '\udf1d'
-    | '\ud800' '\udf30' .. '\udf49'
-    | '\ud800' '\udf80' .. '\udf9c'
-    | '\ud801' '\ue000' .. '\ue09c'
-    | '\ud802' '\ue400' .. '\ue404'
-    | '\ud802' '\u0808'
-    | '\ud802' '\ue40a' .. '\ue434'
-    | '\ud802' '\ue437' .. '\ue437'
-    | '\ud802' '\u083c'
-    | '\ud802' '\u083f'
-    | '\ud835' '\ub000' .. '\ub053'
-    | '\ud835' '\ub056' .. '\ub09b'
-    | '\ud835' '\ub09e' .. '\ub09e'
-    | '\ud835' '\ud4a2'
-    | '\ud835' '\ub0a5' .. '\ub0a5'
-    | '\ud835' '\ub0a9' .. '\ub0ab'
-    | '\ud835' '\ub0ae' .. '\ub0b8'
-    | '\ud835' '\ud4bb'
-    | '\ud835' '\ub0bd' .. '\ub0c2'
-    | '\ud835' '\ub0c5' .. '\ub104'
-    | '\ud835' '\ub107' .. '\ub109'
-    | '\ud835' '\ub10d' .. '\ub113'
-    | '\ud835' '\ub116' .. '\ub11b'
-    | '\ud835' '\ub11e' .. '\ub138'
-    | '\ud835' '\ub13b' .. '\ub13d'
-    | '\ud835' '\ub140' .. '\ub143'
-    | '\ud835' '\ud546'
-    | '\ud835' '\ub14a' .. '\ub14f'
-    | '\ud835' '\ub152' .. '\ub2a2'
-    | '\ud835' '\ub2a8' .. '\ub2bf'
-    | '\ud835' '\ub2c2' .. '\ub2d9'
-    | '\ud835' '\ub2dc' .. '\ub2f9'
-    | '\ud835' '\ub2fc' .. '\ub313'
-    | '\ud835' '\ub316' .. '\ub333'
-    | '\ud835' '\ub336' .. '\ub34d'
-    | '\ud835' '\ub350' .. '\ub36d'
-    | '\ud835' '\ub370' .. '\ub387'
-    | '\ud835' '\ub38a' .. '\ub3a7'
-    | '\ud835' '\ub3aa' .. '\ub3c1'
-    | '\ud835' '\ub3c4' .. '\ub3c8'
-    | '\ud840' '\udc00' .. '\udffe'
-    | '\ud841' '\ue000' .. '\ue3fe'
-    | '\ud842' '\ue400' .. '\ue7fe'
-    | '\ud843' '\ue800' .. '\uebfe'
-    | '\ud844' '\uec00' .. '\ueffe'
-    | '\ud845' '\uf000' .. '\uf3fe'
-    | '\ud846' '\uf400' .. '\uf7fe'
-    | '\ud847' '\uf800' .. '\ufbfe'
-    | '\ud848' '\ufc00' .. '\ufffe'
-    | '\ud849' '\u0000' .. '\u03fe'
-    | '\ud84a' '\u0400' .. '\u07fe'
-    | '\ud84b' '\u0800' .. '\u0bfe'
-    | '\ud84c' '\u0c00' .. '\u0ffe'
-    | '\ud84d' '\u1000' .. '\u13fe'
-    | '\ud84e' '\u1400' .. '\u17fe'
-    | '\ud84f' '\u1800' .. '\u1bfe'
-    | '\ud850' '\u1c00' .. '\u1ffe'
-    | '\ud851' '\u2000' .. '\u23fe'
-    | '\ud852' '\u2400' .. '\u27fe'
-    | '\ud853' '\u2800' .. '\u2bfe'
-    | '\ud854' '\u2c00' .. '\u2ffe'
-    | '\ud855' '\u3000' .. '\u33fe'
-    | '\ud856' '\u3400' .. '\u37fe'
-    | '\ud857' '\u3800' .. '\u3bfe'
-    | '\ud858' '\u3c00' .. '\u3ffe'
-    | '\ud859' '\u4000' .. '\u43fe'
-    | '\ud85a' '\u4400' .. '\u47fe'
-    | '\ud85b' '\u4800' .. '\u4bfe'
-    | '\ud85c' '\u4c00' .. '\u4ffe'
-    | '\ud85d' '\u5000' .. '\u53fe'
-    | '\ud85e' '\u5400' .. '\u57fe'
-    | '\ud85f' '\u5800' .. '\u5bfe'
-    | '\ud860' '\u5c00' .. '\u5ffe'
-    | '\ud861' '\u6000' .. '\u63fe'
-    | '\ud862' '\u6400' .. '\u67fe'
-    | '\ud863' '\u6800' .. '\u6bfe'
-    | '\ud864' '\u6c00' .. '\u6ffe'
-    | '\ud865' '\u7000' .. '\u73fe'
-    | '\ud866' '\u7400' .. '\u77fe'
-    | '\ud867' '\u7800' .. '\u7bfe'
-    | '\ud868' '\u7c00' .. '\u7ffe'
-    | '\ud869' '\u8000' .. '\u82d5'
-    | '\ud87e' '\ud400' .. '\ud61c'
-    ;
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 3c51dbc2550..c13fd558354 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -1573,12 +1573,30 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// An atomic fence.
 ///
-/// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
-/// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
-/// atomic operations X and Y, both operating on some atomic object 'M' such
+/// Depending on the specified order, a fence prevents the compiler and CPU from
+/// reordering certain types of memory operations around it.
+/// That creates synchronizes-with relationships between it and atomic operations
+/// or fences in other threads.
+///
+/// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
+/// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
+/// exist operations X and Y, both operating on some atomic object 'M' such
 /// that A is sequenced before X, Y is synchronized before B and Y observes
 /// the change to M. This provides a happens-before dependence between A and B.
 ///
+/// ```text
+///     Thread 1                                          Thread 2
+///
+/// fence(Release);      A --------------
+/// x.store(3, Relaxed); X ---------    |
+///                                |    |
+///                                |    |
+///                                -------------> Y  if x.load(Relaxed) == 3 {
+///                                     |-------> B      fence(Acquire);
+///                                                      ...
+///                                                  }
+/// ```
+///
 /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
 /// with a fence.
 ///
@@ -1592,6 +1610,37 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 ///
 /// Panics if `order` is [`Relaxed`].
 ///
+/// # Examples
+///
+/// ```
+/// use std::sync::atomic::AtomicBool;
+/// use std::sync::atomic::fence;
+/// use std::sync::atomic::Ordering;
+///
+/// // A mutual exclusion primitive based on spinlock.
+/// pub struct Mutex {
+///     flag: AtomicBool,
+/// }
+///
+/// impl Mutex {
+///     pub fn new() -> Mutex {
+///         Mutex {
+///             flag: AtomicBool::new(false),
+///         }
+///     }
+///
+///     pub fn lock(&self) {
+///         while !self.flag.compare_and_swap(false, true, Ordering::Relaxed) {}
+///         // This fence syncronizes-with store in `unlock`.
+///         fence(Ordering::Acquire);
+///     }
+///
+///     pub fn unlock(&self) {
+///         self.flag.store(false, Ordering::Release);
+///     }
+/// }
+/// ```
+///
 /// [`Ordering`]: enum.Ordering.html
 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
 /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 63a4e6196a2..37b8a56d916 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -76,6 +76,7 @@ pub enum DepNode<D: Clone + Debug> {
     BorrowCheck(D),
     RvalueCheck(D),
     Reachability,
+    MirKeys,
     LateLintCheck,
     TransCrateItem(D),
     TransInlinedItem(D),
@@ -151,6 +152,8 @@ pub enum DepNode<D: Clone + Debug> {
 
     DescribeDef(D),
     DefSpan(D),
+    Stability(D),
+    Deprecation(D),
 }
 
 impl<D: Clone + Debug> DepNode<D> {
@@ -202,6 +205,7 @@ impl<D: Clone + Debug> DepNode<D> {
             Variance => Some(Variance),
             PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
             Reachability => Some(Reachability),
+            MirKeys => Some(MirKeys),
             LateLintCheck => Some(LateLintCheck),
             TransWriteMetadata => Some(TransWriteMetadata),
 
@@ -258,6 +262,8 @@ impl<D: Clone + Debug> DepNode<D> {
             }
             DescribeDef(ref d) => op(d).map(DescribeDef),
             DefSpan(ref d) => op(d).map(DefSpan),
+            Stability(ref d) => op(d).map(Stability),
+            Deprecation(ref d) => op(d).map(Deprecation),
         }
     }
 }
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index a9f0a44e420..6cb86a30400 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -28,6 +28,5 @@ pub use self::graph::WorkProduct;
 pub use self::query::DepGraphQuery;
 pub use self::safe::AssertDepGraphSafe;
 pub use self::safe::DepGraphSafe;
-pub use self::visit::visit_all_bodies_in_krate;
 pub use self::visit::visit_all_item_likes_in_krate;
 pub use self::raii::DepTask;
diff --git a/src/librustc/dep_graph/safe.rs b/src/librustc/dep_graph/safe.rs
index f85f0338ed9..59dce6f6bb0 100644
--- a/src/librustc/dep_graph/safe.rs
+++ b/src/librustc/dep_graph/safe.rs
@@ -50,6 +50,12 @@ impl<A, B> DepGraphSafe for (A, B)
 {
 }
 
+/// Shared ref to dep-graph-safe stuff should still be dep-graph-safe.
+impl<'a, A> DepGraphSafe for &'a A
+    where A: DepGraphSafe,
+{
+}
+
 /// No data here! :)
 impl DepGraphSafe for () {
 }
diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs
index 93f6e3a83a0..bf3748659fe 100644
--- a/src/librustc/dep_graph/visit.rs
+++ b/src/librustc/dep_graph/visit.rs
@@ -75,15 +75,3 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
     krate.visit_all_item_likes(&mut tracking_visitor)
 }
 
-pub fn visit_all_bodies_in_krate<'a, 'tcx, C>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callback: C)
-    where C: Fn(/* body_owner */
-                DefId,
-                /* body id */
-                hir::BodyId)
-{
-    let krate = tcx.hir.krate();
-    for &body_id in &krate.body_ids {
-        let body_owner_def_id = tcx.hir.body_owner_def_id(body_id);
-        callback(body_owner_def_id, body_id);
-    }
-}
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 48b8a819fff..abc967dec90 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -455,7 +455,7 @@ impl<'hir> Map<'hir> {
                 if let EntryExpr(_, expr) = entry {
                     BodyId { node_id: expr.id }
                 } else {
-                    span_bug!(self.span(id), "id `{}` has no associated body", id);
+                    span_bug!(self.span(id), "id `{}` has no associated body: {:?}", id, entry);
                 }
             }
         } else {
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index a3e5a14dbac..d3954326e7b 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -43,6 +43,9 @@
 #![feature(unboxed_closures)]
 #![feature(discriminant_value)]
 #![feature(sort_unstable)]
+#![feature(trace_macros)]
+
+#![recursion_limit="128"]
 
 extern crate arena;
 extern crate core;
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 50920ca7f7e..303c5059e7c 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -38,7 +38,6 @@ use std::any::Any;
 use std::path::PathBuf;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::attr;
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
@@ -180,8 +179,6 @@ pub trait CrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
 
     // item info
-    fn stability(&self, def: DefId) -> Option<attr::Stability>;
-    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
     fn visibility(&self, def: DefId) -> ty::Visibility;
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
     fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
@@ -306,8 +303,6 @@ impl CrateStore for DummyCrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>
         { bug!("crate_data_as_rc_any") }
     // item info
-    fn stability(&self, def: DefId) -> Option<attr::Stability> { bug!("stability") }
-    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { bug!("deprecation") }
     fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>> {
         bug!("visible_parent_map")
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 1ac7f4fcc95..198f7420f5d 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -636,7 +636,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         if id.is_local() {
             None // The stability cache is filled partially lazily
         } else {
-            self.sess.cstore.stability(id).map(|st| self.intern_stability(st))
+            self.stability(id).map(|st| self.intern_stability(st))
         }
     }
 
@@ -645,7 +645,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         if id.is_local() {
             None // The stability cache is filled partially lazily
         } else {
-            self.sess.cstore.deprecation(id).map(DeprecationEntry::external)
+            self.deprecation(id).map(DeprecationEntry::external)
         }
     }
 }
diff --git a/src/librustc/mir/README.md b/src/librustc/mir/README.md
new file mode 100644
index 00000000000..e8ed8bf104c
--- /dev/null
+++ b/src/librustc/mir/README.md
@@ -0,0 +1,90 @@
+# MIR definition and pass system
+
+This file contains the definition of the MIR datatypes along with the
+various types for the "MIR Pass" system, which lets you easily
+register and define new MIR transformations and analyses.
+
+Most of the code that operates on MIR can be found in the
+`librustc_mir` crate or other crates. The code found here in
+`librustc` is just the datatype definitions, alonging the functions
+which operate on MIR to be placed everywhere else.
+
+## MIR Data Types and visitor
+
+The main MIR data type is `rustc::mir::Mir`, defined in `mod.rs`.
+There is also the MIR visitor (in `visit.rs`) which allows you to walk
+the MIR and override what actions will be taken at various points (you
+can visit in either shared or mutable mode; the latter allows changing
+the MIR in place). Finally `traverse.rs` contains various traversal
+routines for visiting the MIR CFG in [different standard orders][traversal]
+(e.g. pre-order, reverse post-order, and so forth).
+
+[traversal]: https://en.wikipedia.org/wiki/Tree_traversal
+
+## MIR pass suites and their integration into the query system
+
+As a MIR *consumer*, you are expected to use one of the queries that
+returns a "final MIR". As of the time of this writing, there is only
+one: `optimized_mir(def_id)`, but more are expected to come in the
+future. For foreign def-ids, we simply read the MIR from the other
+crate's metadata. But for local query, this query will construct the
+MIR and then iteratively optimize it by putting it through various
+pipeline stages. This section describes those pipeline stages and how
+you can extend them.
+
+To produce the `optimized_mir(D)` for a given def-id `D`, the MIR
+passes through several suites of optimizations, each represented by a
+query. Each suite consists of multiple optimizations and
+transformations. These suites represent useful intermediate points
+where we want to access the MIR for type checking or other purposes:
+
+- `mir_build(D)` -- not a query, but this constructs the initial MIR
+- `mir_const(D)` -- applies some simple transformations to make MIR ready for constant evaluation;
+- `mir_validated(D)` -- applies some more transformations, making MIR ready for borrow checking;
+- `optimized_mir(D)` -- the final state, after all optimizations have been performed.
+
+### Stealing
+
+The intermediate queries `mir_const()` and `mir_validated()` yield up
+a `&'tcx Steal<Mir<'tcx>>`, allocated using
+`tcx.alloc_steal_mir()`. This indicates that the result may be
+**stolen** by the next suite of optimizations -- this is an
+optimization to avoid cloning the MIR. Attempting to use a stolen
+result will cause a panic in the compiler. Therefore, it is important
+that you not read directly from these intermediate queries except as
+part of the MIR processing pipeline.
+
+Because of this stealing mechanism, some care must also be taken to
+ensure that, before the MIR at a particular phase in the processing
+pipeline is stolen, anyone who may want to read from it has already
+done so. Concretely, this means that if you have some query `foo(D)`
+that wants to access the result of `mir_const(D)` or
+`mir_validated(D)`, you need to have the successor pass either "force"
+`foo(D)` using `ty::queries::foo::force(...)`. This will force a query
+to execute even though you don't directly require its result.
+
+As an example, consider MIR const qualification. It wants to read the
+result produced by the `mir_const()` suite. However, that result will
+be **stolen** by the `mir_validated()` suite. If nothing was done,
+then `mir_const_qualif(D)` would succeed if it came before
+`mir_validated(D)`, but fail otherwise. Therefore, `mir_validated(D)`
+will **force** `mir_const_qualif` before it actually steals, thus
+ensuring that the reads have already happened:
+
+```
+mir_const(D) --read-by--> mir_const_qualif(D)
+     |                       ^
+  stolen-by                  |
+     |                    (forces)
+     v                       |
+mir_validated(D) ------------+
+```
+
+### Implementing and registering a pass
+
+To create a new MIR pass, you simply implement the `MirPass` trait for
+some fresh singleton type `Foo`. Once you have implemented a trait for
+your type `Foo`, you then have to insert `Foo` into one of the suites;
+this is done in `librustc_driver/driver.rs` by invoking `push_pass(S,
+Foo)` with the appropriate suite substituted for `S`.
+
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 8f8af8b1036..b517ebabbe7 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! MIR datatypes and passes. See [the README](README.md) for details.
+
 use graphviz::IntoCow;
 use middle::const_val::ConstVal;
 use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
index 4cbbb67c7e4..aa91123ef69 100644
--- a/src/librustc/mir/transform.rs
+++ b/src/librustc/mir/transform.rs
@@ -8,16 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use dep_graph::DepNode;
+//! See [the README](README.md) for details on writing your own pass.
+
 use hir;
+use hir::def_id::DefId;
 use hir::map::DefPathData;
 use mir::{Mir, Promoted};
 use ty::TyCtxt;
+use std::rc::Rc;
 use syntax::ast::NodeId;
-use util::common::time;
 
 use std::borrow::Cow;
-use std::fmt;
 
 /// Where a specific Mir comes from.
 #[derive(Debug, Copy, Clone)]
@@ -36,6 +37,11 @@ pub enum MirSource {
 }
 
 impl<'a, 'tcx> MirSource {
+    pub fn from_local_def_id(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> MirSource {
+        let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
+        Self::from_node(tcx, id)
+    }
+
     pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
         use hir::*;
 
@@ -70,124 +76,111 @@ impl<'a, 'tcx> MirSource {
     }
 }
 
-/// Various information about pass.
-pub trait Pass {
-    // fn should_run(Session) to check if pass should run?
-    fn name<'a>(&self) -> Cow<'static, str> {
-        let name = unsafe { ::std::intrinsics::type_name::<Self>() };
-        if let Some(tail) = name.rfind(":") {
-            Cow::from(&name[tail+1..])
-        } else {
-            Cow::from(name)
-        }
+/// Generates a default name for the pass based on the name of the
+/// type `T`.
+pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
+    let name = unsafe { ::std::intrinsics::type_name::<T>() };
+    if let Some(tail) = name.rfind(":") {
+        Cow::from(&name[tail+1..])
+    } else {
+        Cow::from(name)
     }
-    fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> { None }
 }
 
-/// A pass which inspects the whole Mir map.
-pub trait MirMapPass<'tcx>: Pass {
-    fn run_pass<'a>(
-        &mut self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct MirSuite(pub usize);
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct MirPassIndex(pub usize);
+
+/// A pass hook is invoked both before and after each pass executes.
+/// This is primarily used to dump MIR for debugging.
+///
+/// You can tell whether this is before or after by inspecting the
+/// `mir` parameter -- before the pass executes, it will be `None` (in
+/// which case you can inspect the MIR from previous pass by executing
+/// `mir_cx.read_previous_mir()`); after the pass executes, it will be
+/// `Some()` with the result of the pass (in which case the output
+/// from the previous pass is most likely stolen, so you would not
+/// want to try and access it). If the pass is interprocedural, then
+/// the hook will be invoked once per output.
+pub trait PassHook {
+    fn on_mir_pass<'a, 'tcx: 'a>(&self,
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 suite: MirSuite,
+                                 pass_num: MirPassIndex,
+                                 pass_name: &str,
+                                 source: MirSource,
+                                 mir: &Mir<'tcx>,
+                                 is_after: bool);
 }
 
-pub trait MirPassHook<'tcx>: Pass {
-    fn on_mir_pass<'a>(
-        &mut self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        src: MirSource,
-        mir: &Mir<'tcx>,
-        pass: &Pass,
-        is_after: bool
-    );
-}
-
-/// A pass which inspects Mir of functions in isolation.
-pub trait MirPass<'tcx>: Pass {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    src: MirSource, mir: &mut Mir<'tcx>);
-}
-
-impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
-    fn run_pass<'a>(&mut self,
-                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    hooks: &mut [Box<for<'s> MirPassHook<'s>>])
-    {
-        let def_ids = tcx.maps.mir.borrow().keys();
-        for def_id in def_ids {
-            if !def_id.is_local() {
-                continue;
-            }
-
-            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
-            let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut();
-            tcx.dep_graph.write(DepNode::Mir(def_id));
-
-            let id = tcx.hir.as_local_node_id(def_id).unwrap();
-            let src = MirSource::from_node(tcx, id);
-
-            for hook in &mut *hooks {
-                hook.on_mir_pass(tcx, src, mir, self, false);
-            }
-            MirPass::run_pass(self, tcx, src, mir);
-            for hook in &mut *hooks {
-                hook.on_mir_pass(tcx, src, mir, self, true);
-            }
+/// The full suite of types that identifies a particular
+/// application of a pass to a def-id.
+pub type PassId = (MirSuite, MirPassIndex, DefId);
 
-            for (i, mir) in mir.promoted.iter_enumerated_mut() {
-                let src = MirSource::Promoted(id, i);
-                for hook in &mut *hooks {
-                    hook.on_mir_pass(tcx, src, mir, self, false);
-                }
-                MirPass::run_pass(self, tcx, src, mir);
-                for hook in &mut *hooks {
-                    hook.on_mir_pass(tcx, src, mir, self, true);
-                }
-            }
-        }
+/// A streamlined trait that you can implement to create a pass; the
+/// pass will be named after the type, and it will consist of a main
+/// loop that goes over each available MIR and applies `run_pass`.
+pub trait MirPass {
+    fn name<'a>(&'a self) -> Cow<'a, str> {
+        default_name::<Self>()
     }
+
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          source: MirSource,
+                          mir: &mut Mir<'tcx>);
 }
 
 /// A manager for MIR passes.
+///
+/// FIXME(#41712) -- it is unclear whether we should have this struct.
+#[derive(Clone)]
 pub struct Passes {
-    passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>,
-    pass_hooks: Vec<Box<for<'tcx> MirPassHook<'tcx>>>,
-    plugin_passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>
+    pass_hooks: Vec<Rc<PassHook>>,
+    suites: Vec<Vec<Rc<MirPass>>>,
 }
 
+/// The number of "pass suites" that we have:
+///
+/// - ready for constant evaluation
+/// - unopt
+/// - optimized
+pub const MIR_SUITES: usize = 3;
+
+/// Run the passes we need to do constant qualification and evaluation.
+pub const MIR_CONST: MirSuite = MirSuite(0);
+
+/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
+pub const MIR_VALIDATED: MirSuite = MirSuite(1);
+
+/// Run the passes we need to consider the MIR *optimized*.
+pub const MIR_OPTIMIZED: MirSuite = MirSuite(2);
+
 impl<'a, 'tcx> Passes {
     pub fn new() -> Passes {
-        let passes = Passes {
-            passes: Vec::new(),
+        Passes {
             pass_hooks: Vec::new(),
-            plugin_passes: Vec::new()
-        };
-        passes
-    }
-
-    pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-        let Passes { ref mut passes, ref mut plugin_passes, ref mut pass_hooks } = *self;
-        for pass in plugin_passes.iter_mut().chain(passes.iter_mut()) {
-            time(tcx.sess.time_passes(), &*pass.name(),
-                 || pass.run_pass(tcx, pass_hooks));
+            suites: (0..MIR_SUITES).map(|_| Vec::new()).collect(),
         }
     }
 
     /// Pushes a built-in pass.
-    pub fn push_pass(&mut self, pass: Box<for<'b> MirMapPass<'b>>) {
-        self.passes.push(pass);
+    pub fn push_pass<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
+        self.suites[suite.0].push(Rc::new(pass));
     }
 
     /// Pushes a pass hook.
-    pub fn push_hook(&mut self, hook: Box<for<'b> MirPassHook<'b>>) {
-        self.pass_hooks.push(hook);
+    pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
+        self.pass_hooks.push(Rc::new(hook));
+    }
+
+    pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
+        &self.suites[suite.0]
     }
-}
 
-/// Copies the plugin passes.
-impl ::std::iter::Extend<Box<for<'a> MirMapPass<'a>>> for Passes {
-    fn extend<I: IntoIterator<Item=Box<for <'a> MirMapPass<'a>>>>(&mut self, it: I) {
-        self.plugin_passes.extend(it);
+    pub fn hooks(&self) -> &[Rc<PassHook>] {
+        &self.pass_hooks
     }
 }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index d107e9a8485..fdfcd83d5b4 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1003,6 +1003,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "dump MIR state at various points in translation"),
     dump_mir_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
           "the directory the MIR is dumped into"),
+    dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED],
+          "if set, exclude the pass number when dumping MIR (used in tests)"),
     perf_stats: bool = (false, parse_bool, [UNTRACKED],
           "print some performance-related statistics"),
     hir_stats: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index c8732c31663..ec3eaa124c3 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -21,7 +21,6 @@ use session::config::DebugInfoLevel;
 use ty::tls;
 use util::nodemap::{FxHashMap, FxHashSet};
 use util::common::duration_to_secs_str;
-use mir::transform as mir_pass;
 
 use syntax::ast::NodeId;
 use errors::{self, DiagnosticBuilder};
@@ -85,7 +84,6 @@ pub struct Session {
     /// redundantly verbose output (Issue #24690).
     pub one_time_diagnostics: RefCell<FxHashSet<(lint::LintId, Span, String)>>,
     pub plugin_llvm_passes: RefCell<Vec<String>>,
-    pub mir_passes: RefCell<mir_pass::Passes>,
     pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
     pub crate_types: RefCell<Vec<config::CrateType>>,
     pub dependency_formats: RefCell<dependency_format::Dependencies>,
@@ -670,7 +668,6 @@ pub fn build_session_(sopts: config::Options,
         lints: RefCell::new(lint::LintTable::new()),
         one_time_diagnostics: RefCell::new(FxHashSet()),
         plugin_llvm_passes: RefCell::new(Vec::new()),
-        mir_passes: RefCell::new(mir_pass::Passes::new()),
         plugin_attributes: RefCell::new(Vec::new()),
         crate_types: RefCell::new(Vec::new()),
         dependency_formats: RefCell::new(FxHashMap()),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index ef0240296cc..08807d0ced0 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -25,6 +25,7 @@ use middle::region::{CodeExtent, CodeExtentData};
 use middle::resolve_lifetime;
 use middle::stability;
 use mir::Mir;
+use mir::transform::Passes;
 use ty::subst::{Kind, Substs};
 use ty::ReprOptions;
 use traits;
@@ -39,6 +40,7 @@ use ty::TypeVariants::*;
 use ty::layout::{Layout, TargetDataLayout};
 use ty::inhabitedness::DefIdForest;
 use ty::maps;
+use ty::steal::Steal;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
@@ -47,11 +49,12 @@ use arena::{TypedArena, DroplessArena};
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
+use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
 use std::iter;
-use std::cmp::Ordering;
+use std::rc::Rc;
 use syntax::abi;
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
@@ -68,7 +71,8 @@ pub struct GlobalArenas<'tcx> {
     generics: TypedArena<ty::Generics>,
     trait_def: TypedArena<ty::TraitDef>,
     adt_def: TypedArena<ty::AdtDef>,
-    mir: TypedArena<RefCell<Mir<'tcx>>>,
+    steal_mir: TypedArena<Steal<Mir<'tcx>>>,
+    mir: TypedArena<Mir<'tcx>>,
     tables: TypedArena<ty::TypeckTables<'tcx>>,
 }
 
@@ -79,6 +83,7 @@ impl<'tcx> GlobalArenas<'tcx> {
             generics: TypedArena::new(),
             trait_def: TypedArena::new(),
             adt_def: TypedArena::new(),
+            steal_mir: TypedArena::new(),
             mir: TypedArena::new(),
             tables: TypedArena::new(),
         }
@@ -443,8 +448,11 @@ pub struct GlobalCtxt<'tcx> {
     pub named_region_map: resolve_lifetime::NamedRegionMap,
 
     pub hir: hir_map::Map<'tcx>,
+
     pub maps: maps::Maps<'tcx>,
 
+    pub mir_passes: Rc<Passes>,
+
     // Records the free variables refrenced by every closure
     // expression. Do not track deps for this, just recompute it from
     // scratch every time.
@@ -619,8 +627,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.global_arenas.generics.alloc(generics)
     }
 
-    pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> {
-        self.global_arenas.mir.alloc(RefCell::new(mir))
+    pub fn alloc_steal_mir(self, mir: Mir<'gcx>) -> &'gcx Steal<Mir<'gcx>> {
+        self.global_arenas.steal_mir.alloc(Steal::new(mir))
+    }
+
+    pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx Mir<'gcx> {
+        self.global_arenas.mir.alloc(mir)
     }
 
     pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> {
@@ -714,6 +726,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn create_and_enter<F, R>(s: &'tcx Session,
                                   local_providers: ty::maps::Providers<'tcx>,
                                   extern_providers: ty::maps::Providers<'tcx>,
+                                  mir_passes: Rc<Passes>,
                                   arenas: &'tcx GlobalArenas<'tcx>,
                                   arena: &'tcx DroplessArena,
                                   resolutions: ty::Resolutions,
@@ -748,6 +761,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             fulfilled_predicates: RefCell::new(fulfilled_predicates),
             hir: hir,
             maps: maps::Maps::new(dep_graph, providers),
+            mir_passes,
             freevars: RefCell::new(resolutions.freevars),
             maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
             rcache: RefCell::new(FxHashMap()),
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index ef5dfab779c..66df8dc050a 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -16,22 +16,27 @@ use middle::const_val;
 use middle::privacy::AccessLevels;
 use middle::region::RegionMaps;
 use mir;
+use mir::transform::{MirSuite, MirPassIndex};
 use session::CompileResult;
 use ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use ty::item_path;
+use ty::steal::Steal;
 use ty::subst::Substs;
-use util::nodemap::NodeSet;
+use util::nodemap::{DefIdSet, NodeSet};
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::cell::{RefCell, RefMut};
+use std::fmt::Debug;
+use std::hash::Hash;
 use std::mem;
 use std::collections::BTreeMap;
 use std::ops::Deref;
 use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
+use syntax::attr;
 use syntax::symbol::Symbol;
 
-trait Key {
+pub trait Key: Clone + Hash + Eq + Debug {
     fn map_crate(&self) -> CrateNum;
     fn default_span(&self, tcx: TyCtxt) -> Span;
 }
@@ -101,6 +106,24 @@ impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
     }
 }
 
+impl Key for (MirSuite, DefId) {
+    fn map_crate(&self) -> CrateNum {
+        self.1.map_crate()
+    }
+    fn default_span(&self, tcx: TyCtxt) -> Span {
+        self.1.default_span(tcx)
+    }
+}
+
+impl Key for (MirSuite, MirPassIndex, DefId) {
+    fn map_crate(&self) -> CrateNum {
+        self.2.map_crate()
+    }
+    fn default_span(&self, tcx: TyCtxt) -> Span {
+        self.2.default_span(tcx)
+    }
+}
+
 trait Value<'tcx>: Sized {
     fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
 }
@@ -270,8 +293,13 @@ impl<'tcx> QueryDescription for queries::reachable_set<'tcx> {
 
 impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
     fn describe(tcx: TyCtxt, (def_id, _): (DefId, &'tcx Substs<'tcx>)) -> String {
-        format!("const-evaluating `{}`",
-                tcx.item_path_str(def_id))
+        format!("const-evaluating `{}`", tcx.item_path_str(def_id))
+    }
+}
+
+impl<'tcx> QueryDescription for queries::mir_keys<'tcx> {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
+        format!("getting a list of all mir_keys")
     }
 }
 
@@ -293,6 +321,19 @@ impl<'tcx> QueryDescription for queries::def_span<'tcx> {
     }
 }
 
+
+impl<'tcx> QueryDescription for queries::stability<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("stability")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::deprecation<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        bug!("deprecation")
+    }
+}
+
 impl<'tcx> QueryDescription for queries::item_body_nested_bodies<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("nested item bodies of `{}`", tcx.item_path_str(def_id))
@@ -306,7 +347,7 @@ impl<'tcx> QueryDescription for queries::const_is_rvalue_promotable_to_static<'t
     }
 }
 
-impl<'tcx> QueryDescription for queries::is_item_mir_available<'tcx> {
+impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("checking if item is mir available: `{}`",
             tcx.item_path_str(def_id))
@@ -316,11 +357,10 @@ impl<'tcx> QueryDescription for queries::is_item_mir_available<'tcx> {
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
-       [$($pub:tt)*] $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
-        pub struct Maps<$tcx> {
-            providers: IndexVec<CrateNum, Providers<$tcx>>,
-            query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
-            $($(#[$attr])* $($pub)* $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
+       [$($modifiers:tt)*] $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
+        define_map_struct! {
+            tcx: $tcx,
+            input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
         }
 
         impl<$tcx> Maps<$tcx> {
@@ -400,7 +440,7 @@ macro_rules! define_maps {
                     provider(tcx.global_tcx(), key)
                 })?;
 
-                Ok(f(&tcx.maps.$name.borrow_mut().entry(key).or_insert(result)))
+                Ok(f(tcx.maps.$name.borrow_mut().entry(key).or_insert(result)))
             }
 
             pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
@@ -461,25 +501,153 @@ macro_rules! define_maps {
             })*
         }
 
-        pub struct Providers<$tcx> {
-            $(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $V),*
+        define_provider_struct! {
+            tcx: $tcx,
+            input: ($(([$($modifiers)*] [$name] [$K] [$V]))*),
+            output: ()
         }
 
         impl<$tcx> Copy for Providers<$tcx> {}
         impl<$tcx> Clone for Providers<$tcx> {
             fn clone(&self) -> Self { *self }
         }
+    }
+}
+
+macro_rules! define_map_struct {
+    // Initial state
+    (tcx: $tcx:tt,
+     input: $input:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            input: $input,
+            output: ()
+        }
+    };
+
+    // Final output
+    (tcx: $tcx:tt,
+     input: (),
+     output: ($($output:tt)*)) => {
+        pub struct Maps<$tcx> {
+            providers: IndexVec<CrateNum, Providers<$tcx>>,
+            query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
+            $($output)*
+        }
+    };
+
+    // Field recognized and ready to shift into the output
+    (tcx: $tcx:tt,
+     ready: ([$($pub:tt)*] [$($attr:tt)*] [$name:ident]),
+     input: $input:tt,
+     output: ($($output:tt)*)) => {
+        define_map_struct! {
+            tcx: $tcx,
+            input: $input,
+            output: ($($output)*
+                     $(#[$attr])* $($pub)* $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>,)
+        }
+    };
+
+    // Detect things with the `pub` modifier
+    (tcx: $tcx:tt,
+     input: (([pub $($other_modifiers:tt)*] $attrs:tt $name:tt) $($input:tt)*),
+     output: $output:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            ready: ([pub] $attrs $name),
+            input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // No modifiers left? This is a private item.
+    (tcx: $tcx:tt,
+     input: (([] $attrs:tt $name:tt) $($input:tt)*),
+     output: $output:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            ready: ([pub] $attrs $name),
+            input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // Skip other modifiers
+    (tcx: $tcx:tt,
+     input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*),
+     output: $output:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            input: (([$($modifiers)*] $($fields)*) $($input)*),
+            output: $output
+        }
+    };
+}
+
+macro_rules! define_provider_struct {
+    // Initial state:
+    (tcx: $tcx:tt, input: $input:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            input: $input,
+            output: ()
+        }
+    };
+
+    // Final state:
+    (tcx: $tcx:tt,
+     input: (),
+     output: ($(([$name:ident] [$K:ty] [$R:ty]))*)) => {
+        pub struct Providers<$tcx> {
+            $(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $R,)*
+        }
 
         impl<$tcx> Default for Providers<$tcx> {
             fn default() -> Self {
-                $(fn $name<'a, $tcx>(_: TyCtxt<'a, $tcx, $tcx>, key: $K) -> $V {
+                $(fn $name<'a, $tcx>(_: TyCtxt<'a, $tcx, $tcx>, key: $K) -> $R {
                     bug!("tcx.maps.{}({:?}) unsupported by its crate",
                          stringify!($name), key);
                 })*
                 Providers { $($name),* }
             }
         }
-    }
+    };
+
+    // Something ready to shift:
+    (tcx: $tcx:tt,
+     ready: ($name:tt $K:tt $V:tt),
+     input: $input:tt,
+     output: ($($output:tt)*)) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            input: $input,
+            output: ($($output)* ($name $K $V))
+        }
+    };
+
+    // Regular queries produce a `V` only.
+    (tcx: $tcx:tt,
+     input: (([] $name:tt $K:tt $V:tt) $($input:tt)*),
+     output: $output:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            ready: ($name $K $V),
+            input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // Skip modifiers.
+    (tcx: $tcx:tt,
+     input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*),
+     output: $output:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            input: (([$($modifiers)*] $($fields)*) $($input)*),
+            output: $output
+        }
+    };
 }
 
 // Each of these maps also corresponds to a method on a
@@ -537,20 +705,28 @@ define_maps! { <'tcx>
     /// Methods in these implementations don't need to be exported.
     [] inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
 
-    /// Maps from the def-id of a function/method or const/static
-    /// to its MIR. Mutation is done at an item granularity to
-    /// allow MIR optimization passes to function and still
-    /// access cross-crate MIR (e.g. inlining or const eval).
-    ///
-    /// Note that cross-crate MIR appears to be always borrowed
-    /// (in the `RefCell` sense) to prevent accidental mutation.
-    [pub] mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
+    /// Set of all the def-ids in this crate that have MIR associated with
+    /// them. This includes all the body owners, but also things like struct
+    /// constructors.
+    [] mir_keys: mir_keys(CrateNum) -> Rc<DefIdSet>,
 
     /// Maps DefId's that have an associated Mir to the result
     /// of the MIR qualify_consts pass. The actual meaning of
     /// the value isn't known except to the pass itself.
     [] mir_const_qualif: Mir(DefId) -> u8,
 
+    /// Fetch the MIR for a given def-id up till the point where it is
+    /// ready for const evaluation.
+    ///
+    /// See the README for the `mir` module for details.
+    [] mir_const: Mir(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
+
+    [] mir_validated: Mir(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
+
+    /// MIR after our optimization passes have run. This is MIR that is ready
+    /// for trans. This is also the only query that can fetch non-local MIR, at present.
+    [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>,
+
     /// Records the type of each closure. The def ID is the ID of the
     /// expression defining the closure.
     [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
@@ -598,17 +774,18 @@ define_maps! { <'tcx>
     /// fn item.
     [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps<'tcx>>,
 
-    [] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>,
+    [] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>,
 
     [] def_symbol_name: SymbolName(DefId) -> ty::SymbolName,
     [] symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName,
 
     [] describe_def: DescribeDef(DefId) -> Option<Def>,
     [] def_span: DefSpan(DefId) -> Span,
-
+    [] stability: Stability(DefId) -> Option<attr::Stability>,
+    [] deprecation: Deprecation(DefId) -> Option<attr::Deprecation>,
     [] item_body_nested_bodies: metadata_dep_node(DefId) -> Rc<BTreeMap<hir::BodyId, hir::Body>>,
     [] const_is_rvalue_promotable_to_static: metadata_dep_node(DefId) -> bool,
-    [] is_item_mir_available: metadata_dep_node(DefId) -> bool,
+    [] is_mir_available: metadata_dep_node(DefId) -> bool,
 }
 
 fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -644,3 +821,7 @@ fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode<DefId> {
 fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode<DefId> {
     DepNode::ConstEval(def_id)
 }
+
+fn mir_keys(_: CrateNum) -> DepNode<DefId> {
+    DepNode::MirKeys
+}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index bf0f75cf323..55466b1f36d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -35,7 +35,7 @@ use util::common::ErrorReported;
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
 
 use serialize::{self, Encodable, Encoder};
-use std::cell::{Cell, RefCell, Ref};
+use std::cell::{Cell, RefCell};
 use std::collections::BTreeMap;
 use std::cmp;
 use std::fmt;
@@ -96,6 +96,7 @@ pub mod _match;
 pub mod maps;
 pub mod outlives;
 pub mod relate;
+pub mod steal;
 pub mod subst;
 pub mod trait_def;
 pub mod walk;
@@ -2049,6 +2050,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.typeck_tables_of(self.hir.body_owner_def_id(body))
     }
 
+    /// Returns an iterator of the def-ids for all body-owners in this
+    /// crate. If you would prefer to iterate over the bodies
+    /// themselves, you can do `self.hir.krate().body_ids.iter()`.
+    pub fn body_owners(self) -> impl Iterator<Item = DefId> + 'a {
+        self.hir.krate()
+                .body_ids
+                .iter()
+                .map(move |&body_id| self.hir.body_owner_def_id(body_id))
+    }
+
     pub fn expr_span(self, id: NodeId) -> Span {
         match self.hir.find(id) {
             Some(hir_map::NodeExpr(e)) => {
@@ -2313,33 +2324,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    /// Given the did of an item, returns its MIR, borrowed immutably.
-    pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
-        self.mir(did).borrow()
-    }
-
     /// Return the possibly-auto-generated MIR of a (DefId, Subst) pair.
     pub fn instance_mir(self, instance: ty::InstanceDef<'gcx>)
-                        -> Ref<'gcx, Mir<'gcx>>
+                        -> &'gcx Mir<'gcx>
     {
         match instance {
-            ty::InstanceDef::Item(did) if true => self.item_mir(did),
-            _ => self.mir_shims(instance).borrow(),
+            ty::InstanceDef::Item(did) => {
+                self.optimized_mir(did)
+            }
+            ty::InstanceDef::Intrinsic(..) |
+            ty::InstanceDef::FnPtrShim(..) |
+            ty::InstanceDef::Virtual(..) |
+            ty::InstanceDef::ClosureOnceShim { .. } |
+            ty::InstanceDef::DropGlue(..) => {
+                self.mir_shims(instance)
+            }
         }
     }
 
     /// Given the DefId of an item, returns its MIR, borrowed immutably.
     /// Returns None if there is no MIR for the DefId
-    pub fn maybe_item_mir(self, did: DefId) -> Option<Ref<'gcx, Mir<'gcx>>> {
-        if did.is_local() && !self.maps.mir.borrow().contains_key(&did) {
-            return None;
-        }
-
-        if !did.is_local() && !self.is_item_mir_available(did) {
-            return None;
+    pub fn maybe_optimized_mir(self, did: DefId) -> Option<&'gcx Mir<'gcx>> {
+        if self.is_mir_available(did) {
+            Some(self.optimized_mir(did))
+        } else {
+            None
         }
-
-        Some(self.item_mir(did))
     }
 
     /// Get the attributes of a definition.
@@ -2541,17 +2551,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         dep_graph::visit_all_item_likes_in_krate(self.global_tcx(), dep_node_fn, visitor);
     }
 
-    /// Invokes `callback` for each body in the krate. This will
-    /// create a read edge from `DepNode::Krate` to the current task;
-    /// it is meant to be run in the context of some global task like
-    /// `BorrowckCrate`. The callback would then create a task like
-    /// `BorrowckBody(DefId)` to process each individual item.
-    pub fn visit_all_bodies_in_krate<C>(self, callback: C)
-        where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId),
-    {
-        dep_graph::visit_all_bodies_in_krate(self.global_tcx(), callback)
-    }
-
     /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
     /// with the name of the crate containing the impl.
     pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs
new file mode 100644
index 00000000000..0b081888881
--- /dev/null
+++ b/src/librustc/ty/steal.rs
@@ -0,0 +1,57 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cell::{Ref, RefCell};
+use std::mem;
+
+/// The `Steal` struct is intended to used as the value for a query.
+/// Specifically, we sometimes have queries (*cough* MIR *cough*)
+/// where we create a large, complex value that we want to iteratively
+/// update (e.g., optimize). We could clone the value for each
+/// optimization, but that'd be expensive. And yet we don't just want
+/// to mutate it in place, because that would spoil the idea that
+/// queries are these pure functions that produce an immutable value
+/// (since if you did the query twice, you could observe the
+/// mutations). So instead we have the query produce a `&'tcx
+/// Steal<Mir<'tcx>>` (to be very specific). Now we can read from this
+/// as much as we want (using `borrow()`), but you can also
+/// `steal()`. Once you steal, any further attempt to read will panic.
+/// Therefore we know that -- assuming no ICE -- nobody is observing
+/// the fact that the MIR was updated.
+///
+/// Obviously, whenever you have a query that yields a `Steal` value,
+/// you must treat it with caution, and make sure that you know that
+/// -- once the value is stolen -- it will never be read from again.
+///
+/// FIXME(#41710) -- what is the best way to model linear queries?
+pub struct Steal<T> {
+    value: RefCell<Option<T>>
+}
+
+impl<T> Steal<T> {
+    pub fn new(value: T) -> Self {
+        Steal {
+            value: RefCell::new(Some(value))
+        }
+    }
+
+    pub fn borrow(&self) -> Ref<T> {
+        Ref::map(self.value.borrow(), |opt| match *opt {
+            None => bug!("attempted to read from stolen value"),
+            Some(ref v) => v
+        })
+    }
+
+    pub fn steal(&self) -> T {
+        let value_ref = &mut *self.value.borrow_mut();
+        let value = mem::replace(value_ref, None);
+        value.expect("attempt to read from stolen value")
+    }
+}
diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs
index bccd5a41ab1..6bfe90af2ca 100644
--- a/src/librustc_back/target/arm_linux_androideabi.rs
+++ b/src/librustc_back/target/arm_linux_androideabi.rs
@@ -13,7 +13,8 @@ use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
-    base.features = "+v7,+vfp3,+d16".to_string();
+    // https://developer.android.com/ndk/guides/abis.html#armeabi
+    base.features = "+v5te".to_string();
     base.max_atomic_width = Some(64);
 
     Ok(Target {
diff --git a/src/librustc_back/target/armv7_linux_androideabi.rs b/src/librustc_back/target/armv7_linux_androideabi.rs
index 0c90e834006..b49b1d1c213 100644
--- a/src/librustc_back/target/armv7_linux_androideabi.rs
+++ b/src/librustc_back/target/armv7_linux_androideabi.rs
@@ -18,6 +18,8 @@ pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     base.features = "+v7,+thumb2,+vfp3,+d16,-neon".to_string();
     base.max_atomic_width = Some(64);
+    base.pre_link_args
+        .get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string());
 
     Ok(Target {
         llvm_target: "armv7-none-linux-android".to_string(),
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index 9a72f3866a0..b7ce9d98233 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -73,9 +73,16 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &Vec<Move
         let mut err = report_cannot_move_out_of(bccx, error.move_from.clone());
         let mut is_first_note = true;
         match error.move_to_places.get(0) {
-            Some(&MovePlace { pat_source: PatternSource::LetDecl(_), .. }) => {
+            Some(&MovePlace { pat_source: PatternSource::LetDecl(ref e), .. }) => {
                 // ignore patterns that are found at the top-level of a `let`;
                 // see `get_pattern_source()` for details
+                let initializer =
+                    e.init.as_ref().expect("should have an initializer to get an error");
+                if let Ok(snippet) = bccx.tcx.sess.codemap().span_to_snippet(initializer.span) {
+                    err.span_suggestion(initializer.span,
+                                        "consider using a reference instead",
+                                        format!("&{}", snippet));
+                }
             }
             _ => {
                 for move_to in &error.move_to_places {
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
index ca313622a3a..4ae8bdc284b 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
@@ -16,7 +16,7 @@ use super::{drop_flag_effects_for_location, on_lookup_result_bits};
 use super::MoveDataParamEnv;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
-use rustc::mir::transform::{Pass, MirPass, MirSource};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::middle::const_val::ConstVal;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -32,9 +32,11 @@ use std::u32;
 
 pub struct ElaborateDrops;
 
-impl<'tcx> MirPass<'tcx> for ElaborateDrops {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    src: MirSource, mir: &mut Mir<'tcx>)
+impl MirPass for ElaborateDrops {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          src: MirSource,
+                          mir: &mut Mir<'tcx>)
     {
         debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
         match src {
@@ -74,8 +76,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
     }
 }
 
-impl Pass for ElaborateDrops {}
-
 /// Return the set of basic blocks whose unwind edges are known
 /// to not be reachable, because they are `drop` terminators
 /// that can't drop anything.
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs
index de5613dbfaa..47f708bf583 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/mod.rs
@@ -61,7 +61,10 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     let def_id = tcx.hir.local_def_id(id);
     debug!("borrowck_mir({}) UNIMPLEMENTED", tcx.item_path_str(def_id));
 
-    let mir = &tcx.item_mir(def_id);
+    // It is safe for us to borrow `mir_validated()`: `optimized_mir`
+    // steals it, but it forces the `borrowck` query.
+    let mir = &tcx.mir_validated(def_id).borrow();
+
     let param_env = ty::ParameterEnvironment::for_item(tcx, id);
     let move_data = MoveData::gather_moves(mir, tcx, &param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index e5e5045bc29..f8073455bd0 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -63,9 +63,9 @@ pub struct LoanDataFlowOperator;
 pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+    for body_owner_def_id in tcx.body_owners() {
         tcx.borrowck(body_owner_def_id);
-    });
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -86,6 +86,19 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
 
     let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap();
+
+    match tcx.hir.get(owner_id) {
+        hir_map::NodeStructCtor(_) |
+        hir_map::NodeVariant(_) => {
+            // We get invoked with anything that has MIR, but some of
+            // those things (notably the synthesized constructors from
+            // tuple structs/variants) do not have an associated body
+            // and do not need borrowchecking.
+            return;
+        }
+        _ => { }
+    }
+
     let body_id = tcx.hir.body_owned_by(owner_id);
     let attributes = tcx.get_attrs(owner_def_id);
     let tables = tcx.typeck_tables_of(owner_def_id);
@@ -96,6 +109,16 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
 
     if bccx.tcx.has_attr(owner_def_id, "rustc_mir_borrowck") {
         mir::borrowck_mir(bccx, owner_id, &attributes);
+    } else {
+        // Eventually, borrowck will always read the MIR, but at the
+        // moment we do not. So, for now, we always force MIR to be
+        // constructed for a given fn, since this may result in errors
+        // being reported and we want that to happen.
+        //
+        // Note that `mir_validated` is a "stealable" result; the
+        // thief, `optimized_mir()`, forces borrowck, so we know that
+        // is not yet stolen.
+        tcx.mir_validated(owner_def_id).borrow();
     }
 
     let cfg = cfg::CFG::new(bccx.tcx, &body);
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index aa33d4b5539..9f0f567b6ce 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -20,6 +20,7 @@ use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::middle::{self, dependency_format, stability, reachable};
 use rustc::middle::privacy::AccessLevels;
+use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
 use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
 use rustc::util::common::time;
 use rustc::util::nodemap::NodeSet;
@@ -35,8 +36,7 @@ use rustc_typeck as typeck;
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
 use rustc_plugin as plugin;
-use rustc_passes::{ast_validation, no_asm, loops, consts,
-                   static_recursion, hir_stats, mir_stats};
+use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
 use rustc_const_eval::{self, check_match};
 use super::Compilation;
 
@@ -903,9 +903,44 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // FIXME(eddyb) get rid of this once we replace const_eval with miri.
     rustc_const_eval::provide(&mut extern_providers);
 
+    // Setup the MIR passes that we want to run.
+    let mut passes = Passes::new();
+    passes.push_hook(mir::transform::dump_mir::DumpMir);
+
+    // What we need to do constant evaluation.
+    passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial"));
+    passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir);
+
+    // What we need to run borrowck etc.
+    passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
+    passes.push_pass(MIR_VALIDATED,
+                     mir::transform::simplify_branches::SimplifyBranches::new("initial"));
+    passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
+
+    // Optimizations begin.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("no-landing-pads"));
+
+    // From here on out, regions are gone.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
+
+    // No lifetime analysis based on borrowing can be done from here on out.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::instcombine::InstCombine);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans"));
+
     TyCtxt::create_and_enter(sess,
                              local_providers,
                              extern_providers,
+                             Rc::new(passes),
                              arenas,
                              arena,
                              resolutions,
@@ -963,30 +998,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              || middle::liveness::check_crate(tcx));
 
         time(time_passes,
-             "MIR dump",
-             || mir::mir_map::build_mir_for_crate(tcx));
-
-        if sess.opts.debugging_opts.mir_stats {
-            mir_stats::print_mir_stats(tcx, "PRE CLEANUP MIR STATS");
-        }
-
-        time(time_passes, "MIR cleanup and validation", || {
-            let mut passes = sess.mir_passes.borrow_mut();
-            // Push all the built-in validation passes.
-            // NB: if you’re adding an *optimisation* it ought to go to another set of passes
-            // in stage 4 below.
-            passes.push_hook(box mir::transform::dump_mir::DumpMir);
-            passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial"));
-            passes.push_pass(box mir::transform::type_check::TypeckMir);
-            passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
-            passes.push_pass(
-                box mir::transform::simplify_branches::SimplifyBranches::new("initial"));
-            passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
-            // And run everything.
-            passes.run_passes(tcx);
-        });
-
-        time(time_passes,
              "borrow checking",
              || borrowck::check_crate(tcx));
 
@@ -1034,43 +1045,6 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
          "resolving dependency formats",
          || dependency_format::calculate(&tcx.sess));
 
-    if tcx.sess.opts.debugging_opts.mir_stats {
-        mir_stats::print_mir_stats(tcx, "PRE OPTIMISATION MIR STATS");
-    }
-
-    // Run the passes that transform the MIR into a more suitable form for translation to LLVM
-    // code.
-    time(time_passes, "MIR optimisations", || {
-        let mut passes = ::rustc::mir::transform::Passes::new();
-        passes.push_hook(box mir::transform::dump_mir::DumpMir);
-        passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
-        passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("no-landing-pads"));
-
-        // From here on out, regions are gone.
-        passes.push_pass(box mir::transform::erase_regions::EraseRegions);
-
-        passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
-        passes.push_pass(box borrowck::ElaborateDrops);
-        passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
-        passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
-
-        // No lifetime analysis based on borrowing can be done from here on out.
-        passes.push_pass(box mir::transform::inline::Inline);
-        passes.push_pass(box mir::transform::instcombine::InstCombine::new());
-        passes.push_pass(box mir::transform::deaggregator::Deaggregator);
-        passes.push_pass(box mir::transform::copy_prop::CopyPropagation);
-
-        passes.push_pass(box mir::transform::simplify::SimplifyLocals);
-        passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
-        passes.push_pass(box mir::transform::dump_mir::Marker("PreTrans"));
-
-        passes.run_passes(tcx);
-    });
-
-    if tcx.sess.opts.debugging_opts.mir_stats {
-        mir_stats::print_mir_stats(tcx, "POST OPTIMISATION MIR STATS");
-    }
-
     let translation =
         time(time_passes,
              "translation",
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 18dc504ca8a..d40a2ab0b53 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -41,7 +41,6 @@ use graphviz as dot;
 use std::cell::Cell;
 use std::fs::File;
 use std::io::{self, Write};
-use std::iter;
 use std::option;
 use std::path::Path;
 use std::str::FromStr;
@@ -999,22 +998,14 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                 if let Some(nodeid) = nodeid {
                     let def_id = tcx.hir.local_def_id(nodeid);
                     match ppm {
-                        PpmMir => write_mir_pretty(tcx, iter::once(def_id), &mut out),
-                        PpmMirCFG => write_mir_graphviz(tcx, iter::once(def_id), &mut out),
+                        PpmMir => write_mir_pretty(tcx, Some(def_id), &mut out),
+                        PpmMirCFG => write_mir_graphviz(tcx, Some(def_id), &mut out),
                         _ => unreachable!(),
                     }?;
                 } else {
                     match ppm {
-                        PpmMir => {
-                            write_mir_pretty(tcx,
-                                             tcx.maps.mir.borrow().keys().into_iter(),
-                                             &mut out)
-                        }
-                        PpmMirCFG => {
-                            write_mir_graphviz(tcx,
-                                               tcx.maps.mir.borrow().keys().into_iter(),
-                                               &mut out)
-                        }
+                        PpmMir => write_mir_pretty(tcx, None, &mut out),
+                        PpmMirCFG => write_mir_graphviz(tcx, None, &mut out),
                         _ => unreachable!(),
                     }?;
                 }
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index ced30fd6408..8b95be00fa7 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -27,6 +27,7 @@ use rustc::infer::{self, InferOk, InferResult};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc_metadata::cstore::CStore;
 use rustc::hir::map as hir_map;
+use rustc::mir::transform::Passes;
 use rustc::session::{self, config};
 use std::rc::Rc;
 use syntax::ast;
@@ -141,6 +142,7 @@ fn test_env<F>(source_string: &str,
     TyCtxt::create_and_enter(&sess,
                              ty::maps::Providers::default(),
                              ty::maps::Providers::default(),
+                             Rc::new(Passes::new()),
                              &arenas,
                              &arena,
                              resolutions,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index f5a8accea28..a1794ec2d82 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -30,7 +30,6 @@ use rustc::util::nodemap::{NodeSet, DefIdMap};
 use rustc_back::PanicStrategy;
 
 use std::any::Any;
-use std::mem;
 use std::rc::Rc;
 
 use syntax::ast;
@@ -95,16 +94,13 @@ provide! { <'tcx> tcx, def_id, cdata
             bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
         })
     }
-    mir => {
-        let mir = cdata.maybe_get_item_mir(tcx, def_id.index).unwrap_or_else(|| {
-            bug!("get_item_mir: missing MIR for `{:?}`", def_id)
+    optimized_mir => {
+        let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| {
+            bug!("get_optimized_mir: missing MIR for `{:?}`", def_id)
         });
 
         let mir = tcx.alloc_mir(mir);
 
-        // Perma-borrow MIR from extern crates to prevent mutation.
-        mem::forget(mir.borrow());
-
         mir
     }
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
@@ -115,6 +111,8 @@ provide! { <'tcx> tcx, def_id, cdata
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     describe_def => { cdata.get_def(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
+    stability => { cdata.get_stability(def_id.index) }
+    deprecation => { cdata.get_deprecation(def_id.index) }
     item_body_nested_bodies => {
         let map: BTreeMap<_, _> = cdata.entry(def_id.index).ast.into_iter().flat_map(|ast| {
             ast.decode(cdata).nested_bodies.decode(cdata).map(|body| (body.id(), body))
@@ -126,7 +124,7 @@ provide! { <'tcx> tcx, def_id, cdata
         cdata.entry(def_id.index).ast.expect("const item missing `ast`")
             .decode(cdata).rvalue_promotable_to_static
     }
-    is_item_mir_available => {
+    is_mir_available => {
         !cdata.is_proc_macro(def_id.index) &&
         cdata.maybe_entry(def_id.index).and_then(|item| item.decode(cdata).mir).is_some()
     }
@@ -137,16 +135,6 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(krate)
     }
 
-    fn stability(&self, def: DefId) -> Option<attr::Stability> {
-        self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).get_stability(def.index)
-    }
-
-    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> {
-        self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).get_deprecation(def.index)
-    }
-
     fn visibility(&self, def: DefId) -> ty::Visibility {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_visibility(def.index)
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 5d0e78da2f8..ae755adcf5f 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -779,10 +779,10 @@ impl<'a, 'tcx> CrateMetadata {
         tcx.alloc_tables(ast.tables.decode((self, tcx)))
     }
 
-    pub fn maybe_get_item_mir(&self,
-                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: DefIndex)
-                              -> Option<Mir<'tcx>> {
+    pub fn maybe_get_optimized_mir(&self,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   id: DefIndex)
+                                   -> Option<Mir<'tcx>> {
         match self.is_proc_macro(id) {
             true => None,
             false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))),
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 189b94a1b62..125026b799c 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -295,7 +295,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: None,
-            mir: self.encode_mir(def_id),
+            mir: self.encode_optimized_mir(def_id),
         }
     }
 
@@ -433,7 +433,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: None,
-            mir: self.encode_mir(def_id),
+            mir: self.encode_optimized_mir(def_id),
         }
     }
 
@@ -528,7 +528,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             } else {
                 None
             },
-            mir: self.encode_mir(def_id),
+            mir: self.encode_optimized_mir(def_id),
         }
     }
 
@@ -598,7 +598,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: ast.map(|body| self.encode_body(body)),
-            mir: if mir { self.encode_mir(def_id) } else { None },
+            mir: if mir { self.encode_optimized_mir(def_id) } else { None },
         }
     }
 
@@ -619,9 +619,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
         self.lazy_seq(names.iter().map(|name| name.node))
     }
 
-    fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
+    fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
         debug!("EntryBuilder::encode_mir({:?})", def_id);
-        self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
+        if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
+            let mir = self.tcx.optimized_mir(def_id);
+            Some(self.lazy(&mir))
+        } else {
+            None
+        }
     }
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
@@ -856,15 +861,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             },
             mir: match item.node {
                 hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => {
-                    self.encode_mir(def_id)
+                    self.encode_optimized_mir(def_id)
                 }
-                hir::ItemConst(..) => self.encode_mir(def_id),
+                hir::ItemConst(..) => self.encode_optimized_mir(def_id),
                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
                     let tps_len = generics.ty_params.len();
                     let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     if needs_inline || constness == hir::Constness::Const || always_encode_mir {
-                        self.encode_mir(def_id)
+                        self.encode_optimized_mir(def_id)
                     } else {
                         None
                     }
@@ -1161,7 +1166,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             predicates: None,
 
             ast: None,
-            mir: self.encode_mir(def_id),
+            mir: self.encode_optimized_mir(def_id),
         }
     }
 
@@ -1187,7 +1192,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: Some(self.encode_body(body)),
-            mir: self.encode_mir(def_id),
+            mir: self.encode_optimized_mir(def_id),
         }
     }
 
diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs
index 5c133780e43..0d912513c6c 100644
--- a/src/librustc_mir/build/into.rs
+++ b/src/librustc_mir/build/into.rs
@@ -18,7 +18,7 @@ use build::{BlockAnd, Builder};
 use hair::*;
 use rustc::mir::*;
 
-pub trait EvalInto<'tcx> {
+pub(in build) trait EvalInto<'tcx> {
     fn eval_into<'a, 'gcx>(self,
                            builder: &mut Builder<'a, 'gcx, 'tcx>,
                            destination: &Lvalue<'tcx>,
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index b8f1b754b48..8c057b02df2 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -8,24 +8,225 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+
+use build;
 use hair::cx::Cx;
 use hair::Pattern;
-
+use rustc::hir;
+use rustc::hir::def_id::DefId;
 use rustc::middle::region::{CodeExtent, CodeExtentData};
-use rustc::ty::{self, Ty};
 use rustc::mir::*;
+use rustc::mir::transform::MirSource;
+use rustc::mir::visit::MutVisitor;
+use rustc::traits::Reveal;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeMap;
-use rustc::hir;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use shim;
+use std::mem;
+use std::u32;
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax::symbol::keywords;
 use syntax_pos::Span;
+use util as mir_util;
 
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+/// Construct the MIR for a given def-id.
+pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
+    let id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let unsupported = || {
+        span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
+    };
 
-use std::u32;
+    // Figure out what primary body this item has.
+    let body_id = match tcx.hir.get(id) {
+        hir::map::NodeItem(item) => {
+            match item.node {
+                hir::ItemConst(_, body) |
+                hir::ItemStatic(_, _, body) |
+                hir::ItemFn(.., body) => body,
+                _ => unsupported()
+            }
+        }
+        hir::map::NodeTraitItem(item) => {
+            match item.node {
+                hir::TraitItemKind::Const(_, Some(body)) |
+                hir::TraitItemKind::Method(_,
+                    hir::TraitMethod::Provided(body)) => body,
+                _ => unsupported()
+            }
+        }
+        hir::map::NodeImplItem(item) => {
+            match item.node {
+                hir::ImplItemKind::Const(_, body) |
+                hir::ImplItemKind::Method(_, body) => body,
+                _ => unsupported()
+            }
+        }
+        hir::map::NodeExpr(expr) => {
+            // FIXME(eddyb) Closures should have separate
+            // function definition IDs and expression IDs.
+            // Type-checking should not let closures get
+            // this far in a constant position.
+            // Assume that everything other than closures
+            // is a constant "initializer" expression.
+            match expr.node {
+                hir::ExprClosure(_, _, body, _) => body,
+                _ => hir::BodyId { node_id: expr.id }
+            }
+        }
+        hir::map::NodeVariant(variant) =>
+            return create_constructor_shim(tcx, id, &variant.node.data),
+        hir::map::NodeStructCtor(ctor) =>
+            return create_constructor_shim(tcx, id, ctor),
+        _ => unsupported()
+    };
+
+    let src = MirSource::from_node(tcx, id);
+    tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
+        let cx = Cx::new(&infcx, src);
+        let mut mir = if cx.tables().tainted_by_errors {
+            build::construct_error(cx, body_id)
+        } else if let MirSource::Fn(id) = src {
+            // fetch the fully liberated fn signature (that is, all bound
+            // types/lifetimes replaced)
+            let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
+
+            let ty = tcx.type_of(tcx.hir.local_def_id(id));
+            let mut abi = fn_sig.abi;
+            let implicit_argument = if let ty::TyClosure(..) = ty.sty {
+                // HACK(eddyb) Avoid having RustCall on closures,
+                // as it adds unnecessary (and wrong) auto-tupling.
+                abi = Abi::Rust;
+                Some((closure_self_ty(tcx, id, body_id), None))
+            } else {
+                None
+            };
+
+            let body = tcx.hir.body(body_id);
+            let explicit_arguments =
+                body.arguments
+                    .iter()
+                    .enumerate()
+                    .map(|(index, arg)| {
+                        (fn_sig.inputs()[index], Some(&*arg.pat))
+                    });
+
+            let arguments = implicit_argument.into_iter().chain(explicit_arguments);
+            build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body)
+        } else {
+            build::construct_const(cx, body_id)
+        };
+
+        // Convert the Mir to global types.
+        let mut globalizer = GlobalizeMir {
+            tcx: tcx,
+            span: mir.span
+        };
+        globalizer.visit_mir(&mut mir);
+        let mir = unsafe {
+            mem::transmute::<Mir, Mir<'tcx>>(mir)
+        };
+
+        mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
+
+        mir
+    })
+}
+
+/// A pass to lift all the types and substitutions in a Mir
+/// to the global tcx. Sadly, we don't have a "folder" that
+/// can change 'tcx so we have to transmute afterwards.
+struct GlobalizeMir<'a, 'gcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+    span: Span
+}
+
+impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>) {
+        if let Some(lifted) = self.tcx.lift(ty) {
+            *ty = lifted;
+        } else {
+            span_bug!(self.span,
+                      "found type `{:?}` with inference types/regions in MIR",
+                      ty);
+        }
+    }
+
+    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
+        if let Some(lifted) = self.tcx.lift(substs) {
+            *substs = lifted;
+        } else {
+            span_bug!(self.span,
+                      "found substs `{:?}` with inference types/regions in MIR",
+                      substs);
+        }
+    }
+}
+
+fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     ctor_id: ast::NodeId,
+                                     v: &'tcx hir::VariantData)
+                                     -> Mir<'tcx>
+{
+    let span = tcx.hir.span(ctor_id);
+    if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
+        let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
+        tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
+            let (mut mir, src) =
+                shim::build_adt_ctor(&infcx, ctor_id, fields, span);
+
+            // Convert the Mir to global types.
+            let tcx = infcx.tcx.global_tcx();
+            let mut globalizer = GlobalizeMir {
+                tcx: tcx,
+                span: mir.span
+            };
+            globalizer.visit_mir(&mut mir);
+            let mir = unsafe {
+                mem::transmute::<Mir, Mir<'tcx>>(mir)
+            };
+
+            mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
+
+            mir
+        })
+    } else {
+        span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
+
+fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             closure_expr_id: ast::NodeId,
+                             body_id: hir::BodyId)
+                             -> Ty<'tcx> {
+    let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
+
+    let region = ty::ReFree(ty::FreeRegion {
+        scope: Some(tcx.item_extent(body_id.node_id)),
+        bound_region: ty::BoundRegion::BrEnv,
+    });
+    let region = tcx.mk_region(region);
+
+    match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
+        ty::ClosureKind::Fn =>
+            tcx.mk_ref(region,
+                       ty::TypeAndMut { ty: closure_ty,
+                                        mutbl: hir::MutImmutable }),
+        ty::ClosureKind::FnMut =>
+            tcx.mk_ref(region,
+                       ty::TypeAndMut { ty: closure_ty,
+                                        mutbl: hir::MutMutable }),
+        ty::ClosureKind::FnOnce =>
+            closure_ty
+    }
+}
 
-pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     hir: Cx<'a, 'gcx, 'tcx>,
     cfg: CFG<'tcx>,
 
@@ -82,7 +283,7 @@ impl Idx for ScopeId {
 /// convenient.
 
 #[must_use] // if you don't use one of these results, you're leaving a dangling edge
-pub struct BlockAnd<T>(BasicBlock, T);
+struct BlockAnd<T>(BasicBlock, T);
 
 trait BlockAndExtension {
     fn and<T>(self, v: T) -> BlockAnd<T>;
@@ -121,13 +322,13 @@ macro_rules! unpack {
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
-pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
-                                       fn_id: ast::NodeId,
-                                       arguments: A,
-                                       abi: Abi,
-                                       return_ty: Ty<'gcx>,
-                                       body: &'gcx hir::Body)
-                                       -> Mir<'tcx>
+fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
+                                   fn_id: ast::NodeId,
+                                   arguments: A,
+                                   abi: Abi,
+                                   return_ty: Ty<'gcx>,
+                                   body: &'gcx hir::Body)
+                                   -> Mir<'tcx>
     where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
 {
     let arguments: Vec<_> = arguments.collect();
diff --git a/src/librustc_mir/callgraph.rs b/src/librustc_mir/callgraph.rs
deleted file mode 100644
index 69416289d8e..00000000000
--- a/src/librustc_mir/callgraph.rs
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! MIR-based callgraph.
-//!
-//! This only considers direct calls
-
-use rustc::hir::def_id::DefId;
-use rustc_data_structures::graph;
-
-use rustc::mir::*;
-use rustc::mir::visit::*;
-
-use rustc::ty;
-
-use rustc::util::nodemap::DefIdMap;
-
-pub struct CallGraph {
-    node_map: DefIdMap<graph::NodeIndex>,
-    graph: graph::Graph<DefId, ()>
-}
-
-impl CallGraph {
-    // FIXME: allow for construction of a callgraph that inspects
-    // cross-crate MIRs if available.
-    pub fn build<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> CallGraph {
-        let def_ids = tcx.maps.mir.borrow().keys();
-
-        let mut callgraph = CallGraph {
-            node_map: DefIdMap(),
-            graph: graph::Graph::new()
-        };
-
-        for def_id in def_ids {
-            if !def_id.is_local() { continue; }
-
-            let idx = callgraph.add_node(def_id);
-
-            let mut call_visitor = CallVisitor {
-                caller: idx,
-                graph: &mut callgraph
-            };
-
-            let mir = tcx.item_mir(def_id);
-            call_visitor.visit_mir(&mir);
-        }
-
-        callgraph
-    }
-
-    // Iterate over the strongly-connected components of the graph
-    pub fn scc_iter(&self) -> SCCIterator {
-        SCCIterator::new(&self.graph)
-    }
-
-    // Get the def_id for the given graph node
-    pub fn def_id(&self, node: graph::NodeIndex) -> DefId {
-        *self.graph.node_data(node)
-    }
-
-    fn add_node(&mut self, id: DefId) -> graph::NodeIndex {
-        let graph = &mut self.graph;
-        *self.node_map.entry(id).or_insert_with(|| {
-            graph.add_node(id)
-        })
-    }
-}
-
-struct CallVisitor<'a> {
-    caller: graph::NodeIndex,
-    graph: &'a mut CallGraph
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for CallVisitor<'a> {
-    fn visit_terminator_kind(&mut self, _block: BasicBlock,
-                             kind: &TerminatorKind<'tcx>, _loc: Location) {
-        if let TerminatorKind::Call {
-            func: Operand::Constant(ref f)
-            , .. } = *kind {
-            if let ty::TyFnDef(def_id, _, _) = f.ty.sty {
-                let callee = self.graph.add_node(def_id);
-                self.graph.graph.add_edge(self.caller, callee, ());
-            }
-        }
-    }
-}
-
-struct StackElement<'g> {
-    node: graph::NodeIndex,
-    lowlink: usize,
-    children: graph::AdjacentTargets<'g, DefId, ()>
-}
-
-/**
- * Iterator over strongly-connected-components using Tarjan's algorithm[1]
- *
- * [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
- */
-pub struct SCCIterator<'g> {
-    graph: &'g graph::Graph<DefId, ()>,
-    index: usize,
-    node_indices: Vec<Option<usize>>,
-    scc_stack: Vec<graph::NodeIndex>,
-    current_scc: Vec<graph::NodeIndex>,
-    visit_stack: Vec<StackElement<'g>>,
-}
-
-impl<'g> SCCIterator<'g> {
-    pub fn new(graph: &'g graph::Graph<DefId, ()>) -> SCCIterator<'g> {
-        if graph.len_nodes() == 0 {
-            return SCCIterator {
-                graph: graph,
-                index: 0,
-                node_indices: Vec::new(),
-                scc_stack: Vec::new(),
-                current_scc: Vec::new(),
-                visit_stack: Vec::new()
-            };
-        }
-
-        let first = graph::NodeIndex(0);
-
-        SCCIterator::with_entry(graph, first)
-    }
-
-    pub fn with_entry(graph: &'g graph::Graph<DefId, ()>,
-                      entry: graph::NodeIndex) -> SCCIterator<'g> {
-        let mut iter = SCCIterator {
-            graph: graph,
-            index: 0,
-            node_indices: Vec::with_capacity(graph.len_nodes()),
-            scc_stack: Vec::new(),
-            current_scc: Vec::new(),
-            visit_stack: Vec::new()
-        };
-
-        iter.visit_one(entry);
-
-        iter
-    }
-
-    fn get_next(&mut self) {
-        self.current_scc.clear();
-
-        while !self.visit_stack.is_empty() {
-            self.visit_children();
-
-            let node = self.visit_stack.pop().unwrap();
-
-            if let Some(last) = self.visit_stack.last_mut() {
-                if last.lowlink > node.lowlink {
-                    last.lowlink = node.lowlink;
-                }
-            }
-
-            debug!("TarjanSCC: Popped node {:?} : lowlink = {:?}; index = {:?}",
-                   node.node, node.lowlink, self.node_index(node.node).unwrap());
-
-            if node.lowlink != self.node_index(node.node).unwrap() {
-                continue;
-            }
-
-            loop {
-                let n = self.scc_stack.pop().unwrap();
-                self.current_scc.push(n);
-                self.set_node_index(n, !0);
-                if n == node.node { return; }
-            }
-        }
-    }
-
-    fn visit_one(&mut self, node: graph::NodeIndex) {
-        self.index += 1;
-        let idx =  self.index;
-        self.set_node_index(node, idx);
-        self.scc_stack.push(node);
-        self.visit_stack.push(StackElement {
-            node: node,
-            lowlink: self.index,
-            children: self.graph.successor_nodes(node)
-        });
-        debug!("TarjanSCC: Node {:?} : index = {:?}", node, idx);
-    }
-
-    fn visit_children(&mut self) {
-        while let Some(child) = self.visit_stack.last_mut().unwrap().children.next() {
-            if let Some(child_num) = self.node_index(child) {
-                let cur = self.visit_stack.last_mut().unwrap();
-                if cur.lowlink > child_num {
-                    cur.lowlink = child_num;
-                }
-            } else {
-                self.visit_one(child);
-            }
-        }
-    }
-
-    fn node_index(&self, node: graph::NodeIndex) -> Option<usize> {
-        self.node_indices.get(node.node_id()).and_then(|&idx| idx)
-    }
-
-    fn set_node_index(&mut self, node: graph::NodeIndex, idx: usize) {
-        let i = node.node_id();
-        if i >= self.node_indices.len() {
-            self.node_indices.resize(i + 1, None);
-        }
-        self.node_indices[i] = Some(idx);
-    }
-}
-
-impl<'g> Iterator for SCCIterator<'g> {
-    type Item = Vec<graph::NodeIndex>;
-
-    fn next(&mut self) -> Option<Vec<graph::NodeIndex>> {
-        self.get_next();
-
-        if self.current_scc.is_empty() {
-            // Try a new root for the next SCC, if the node_indices
-            // map is doesn't contain all nodes, use the smallest one
-            // with no entry, otherwise find the first empty node.
-            //
-            // FIXME: This should probably use a set of precomputed
-            // roots instead
-            if self.node_indices.len() < self.graph.len_nodes() {
-                let idx = graph::NodeIndex(self.node_indices.len());
-                self.visit_one(idx);
-            } else {
-                for idx in 0..self.node_indices.len() {
-                    if self.node_indices[idx].is_none() {
-                        let idx = graph::NodeIndex(idx);
-                        self.visit_one(idx);
-                        break;
-                    }
-                }
-            }
-            self.get_next();
-        }
-
-        if self.current_scc.is_empty() {
-            None
-        } else {
-            Some(self.current_scc.clone())
-        }
-    }
-}
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 3e9bcb3e186..ee8547e5dd6 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -26,7 +26,7 @@ use rustc::middle::region::RegionMaps;
 use rustc::infer::InferCtxt;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::Symbol;
 use rustc::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
 use std::rc::Rc;
@@ -103,10 +103,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         self.tcx.mk_nil()
     }
 
-    pub fn str_literal(&mut self, value: InternedString) -> Literal<'tcx> {
-        Literal::Value { value: ConstVal::Str(value) }
-    }
-
     pub fn true_literal(&mut self) -> Literal<'tcx> {
         Literal::Value { value: ConstVal::Bool(true) }
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 8b55cdf06d2..5fa56bac137 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -46,18 +46,15 @@ extern crate rustc_const_eval;
 
 pub mod diagnostics;
 
-pub mod build;
-pub mod callgraph;
+mod build;
 mod hair;
 mod shim;
-pub mod mir_map;
 pub mod transform;
 pub mod util;
 
 use rustc::ty::maps::Providers;
 
 pub fn provide(providers: &mut Providers) {
-    mir_map::provide(providers);
     shim::provide(providers);
-    transform::qualify_consts::provide(providers);
+    transform::provide(providers);
 }
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
deleted file mode 100644
index 1abae515ae6..00000000000
--- a/src/librustc_mir/mir_map.rs
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! An experimental pass that scources for `#[rustc_mir]` attributes,
-//! builds the resulting MIR, and dumps it out into a file for inspection.
-//!
-//! The attribute formats that are currently accepted are:
-//!
-//! - `#[rustc_mir(graphviz="file.gv")]`
-//! - `#[rustc_mir(pretty="file.mir")]`
-
-use build;
-use rustc::hir::def_id::DefId;
-use rustc::dep_graph::DepNode;
-use rustc::mir::Mir;
-use rustc::mir::transform::MirSource;
-use rustc::mir::visit::MutVisitor;
-use shim;
-use hair::cx::Cx;
-use util as mir_util;
-
-use rustc::traits::Reveal;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::maps::Providers;
-use rustc::ty::subst::Substs;
-use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use syntax::abi::Abi;
-use syntax::ast;
-use syntax_pos::Span;
-
-use std::cell::RefCell;
-use std::mem;
-
-pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.dep_graph.with_task(DepNode::MirKrate, tcx, (), build_mir_for_crate_task);
-
-    fn build_mir_for_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
-        tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
-            tcx.item_mir(body_owner_def_id);
-        });
-
-        // Tuple struct/variant constructors don't have a BodyId, so we need
-        // to build them separately.
-        struct GatherCtors<'a, 'tcx: 'a> {
-            tcx: TyCtxt<'a, 'tcx, 'tcx>
-        }
-        impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
-            fn visit_variant_data(&mut self,
-                                  v: &'tcx hir::VariantData,
-                                  _: ast::Name,
-                                  _: &'tcx hir::Generics,
-                                  _: ast::NodeId,
-                                  _: Span) {
-                if let hir::VariantData::Tuple(_, node_id) = *v {
-                    self.tcx.item_mir(self.tcx.hir.local_def_id(node_id));
-                }
-                intravisit::walk_struct_def(self, v)
-            }
-            fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
-                NestedVisitorMap::None
-            }
-        }
-        tcx.hir.krate().visit_all_item_likes(&mut GatherCtors {
-            tcx: tcx
-        }.as_deep_visitor());
-    }
-}
-
-pub fn provide(providers: &mut Providers) {
-    providers.mir = build_mir;
-}
-
-fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                       -> &'tcx RefCell<Mir<'tcx>> {
-    let id = tcx.hir.as_local_node_id(def_id).unwrap();
-    let unsupported = || {
-        span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
-    };
-
-    // Figure out what primary body this item has.
-    let body_id = match tcx.hir.get(id) {
-        hir::map::NodeItem(item) => {
-            match item.node {
-                hir::ItemConst(_, body) |
-                hir::ItemStatic(_, _, body) |
-                hir::ItemFn(.., body) => body,
-                _ => unsupported()
-            }
-        }
-        hir::map::NodeTraitItem(item) => {
-            match item.node {
-                hir::TraitItemKind::Const(_, Some(body)) |
-                hir::TraitItemKind::Method(_,
-                    hir::TraitMethod::Provided(body)) => body,
-                _ => unsupported()
-            }
-        }
-        hir::map::NodeImplItem(item) => {
-            match item.node {
-                hir::ImplItemKind::Const(_, body) |
-                hir::ImplItemKind::Method(_, body) => body,
-                _ => unsupported()
-            }
-        }
-        hir::map::NodeExpr(expr) => {
-            // FIXME(eddyb) Closures should have separate
-            // function definition IDs and expression IDs.
-            // Type-checking should not let closures get
-            // this far in a constant position.
-            // Assume that everything other than closures
-            // is a constant "initializer" expression.
-            match expr.node {
-                hir::ExprClosure(_, _, body, _) => body,
-                _ => hir::BodyId { node_id: expr.id }
-            }
-        }
-        hir::map::NodeVariant(variant) =>
-            return create_constructor_shim(tcx, id, &variant.node.data),
-        hir::map::NodeStructCtor(ctor) =>
-            return create_constructor_shim(tcx, id, ctor),
-        _ => unsupported()
-    };
-
-    let src = MirSource::from_node(tcx, id);
-    tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
-        let cx = Cx::new(&infcx, src);
-        let mut mir = if cx.tables().tainted_by_errors {
-            build::construct_error(cx, body_id)
-        } else if let MirSource::Fn(id) = src {
-            // fetch the fully liberated fn signature (that is, all bound
-            // types/lifetimes replaced)
-            let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
-
-            let ty = tcx.type_of(tcx.hir.local_def_id(id));
-            let mut abi = fn_sig.abi;
-            let implicit_argument = if let ty::TyClosure(..) = ty.sty {
-                // HACK(eddyb) Avoid having RustCall on closures,
-                // as it adds unnecessary (and wrong) auto-tupling.
-                abi = Abi::Rust;
-                Some((closure_self_ty(tcx, id, body_id), None))
-            } else {
-                None
-            };
-
-            let body = tcx.hir.body(body_id);
-            let explicit_arguments =
-                body.arguments
-                    .iter()
-                    .enumerate()
-                    .map(|(index, arg)| {
-                        (fn_sig.inputs()[index], Some(&*arg.pat))
-                    });
-
-            let arguments = implicit_argument.into_iter().chain(explicit_arguments);
-            build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body)
-        } else {
-            build::construct_const(cx, body_id)
-        };
-
-        // Convert the Mir to global types.
-        let mut globalizer = GlobalizeMir {
-            tcx: tcx,
-            span: mir.span
-        };
-        globalizer.visit_mir(&mut mir);
-        let mir = unsafe {
-            mem::transmute::<Mir, Mir<'tcx>>(mir)
-        };
-
-        mir_util::dump_mir(tcx, "mir_map", &0, src, &mir);
-
-        tcx.alloc_mir(mir)
-    })
-}
-
-/// A pass to lift all the types and substitutions in a Mir
-/// to the global tcx. Sadly, we don't have a "folder" that
-/// can change 'tcx so we have to transmute afterwards.
-struct GlobalizeMir<'a, 'gcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'gcx>,
-    span: Span
-}
-
-impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>) {
-        if let Some(lifted) = self.tcx.lift(ty) {
-            *ty = lifted;
-        } else {
-            span_bug!(self.span,
-                      "found type `{:?}` with inference types/regions in MIR",
-                      ty);
-        }
-    }
-
-    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
-        if let Some(lifted) = self.tcx.lift(substs) {
-            *substs = lifted;
-        } else {
-            span_bug!(self.span,
-                      "found substs `{:?}` with inference types/regions in MIR",
-                      substs);
-        }
-    }
-}
-
-fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     ctor_id: ast::NodeId,
-                                     v: &'tcx hir::VariantData)
-                                     -> &'tcx RefCell<Mir<'tcx>>
-{
-    let span = tcx.hir.span(ctor_id);
-    if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
-        let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
-        tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
-            let (mut mir, src) =
-                shim::build_adt_ctor(&infcx, ctor_id, fields, span);
-
-            // Convert the Mir to global types.
-            let tcx = infcx.tcx.global_tcx();
-            let mut globalizer = GlobalizeMir {
-                tcx: tcx,
-                span: mir.span
-            };
-            globalizer.visit_mir(&mut mir);
-            let mir = unsafe {
-                mem::transmute::<Mir, Mir<'tcx>>(mir)
-            };
-
-            mir_util::dump_mir(tcx, "mir_map", &0, src, &mir);
-
-            tcx.alloc_mir(mir)
-        })
-    } else {
-        span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
-
-fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             closure_expr_id: ast::NodeId,
-                             body_id: hir::BodyId)
-                             -> Ty<'tcx> {
-    let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
-
-    let region = ty::ReFree(ty::FreeRegion {
-        scope: Some(tcx.item_extent(body_id.node_id)),
-        bound_region: ty::BoundRegion::BrEnv,
-    });
-    let region = tcx.mk_region(region);
-
-    match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
-        ty::ClosureKind::Fn =>
-            tcx.mk_ref(region,
-                       ty::TypeAndMut { ty: closure_ty,
-                                        mutbl: hir::MutImmutable }),
-        ty::ClosureKind::FnMut =>
-            tcx.mk_ref(region,
-                       ty::TypeAndMut { ty: closure_ty,
-                                        mutbl: hir::MutMutable }),
-        ty::ClosureKind::FnOnce =>
-            closure_ty
-    }
-}
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index f2a550ec23a..1458ea7fdd6 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -24,10 +24,8 @@ use syntax::abi::Abi;
 use syntax::ast;
 use syntax_pos::Span;
 
-use std::cell::RefCell;
 use std::fmt;
 use std::iter;
-use std::mem;
 
 use transform::{add_call_guards, no_landing_pads, simplify};
 use util::elaborate_drops::{self, DropElaborator, DropStyle, DropFlagMode};
@@ -39,7 +37,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                        instance: ty::InstanceDef<'tcx>)
-                       -> &'tcx RefCell<Mir<'tcx>>
+                       -> &'tcx Mir<'tcx>
 {
     debug!("make_shim({:?})", instance);
     let did = instance.def_id();
@@ -116,10 +114,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
         add_call_guards::add_call_guards(&mut result);
     debug!("make_shim({:?}) = {:?}", instance, result);
 
-    let result = tcx.alloc_mir(result);
-    // Perma-borrow MIR from shims to prevent mutation.
-    mem::forget(result.borrow());
-    result
+    tcx.alloc_mir(result)
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs
index 80b17c6a008..b7c7a1774dd 100644
--- a/src/librustc_mir/transform/add_call_guards.rs
+++ b/src/librustc_mir/transform/add_call_guards.rs
@@ -10,7 +10,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 pub struct AddCallGuards;
@@ -35,8 +35,11 @@ pub struct AddCallGuards;
  *
  */
 
-impl<'tcx> MirPass<'tcx> for AddCallGuards {
-    fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for AddCallGuards {
+    fn run_pass<'a, 'tcx>(&self,
+                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _src: MirSource,
+                          mir: &mut Mir<'tcx>) {
         add_call_guards(mir);
     }
 }
@@ -82,5 +85,3 @@ pub fn add_call_guards(mir: &mut Mir) {
 
     mir.basic_blocks_mut().extend(new_blocks);
 }
-
-impl Pass for AddCallGuards {}
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 5d127a5aed4..fbb67161bac 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -30,7 +30,7 @@
 //! future.
 
 use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
 use util::def_use::DefUseAnalysis;
@@ -38,13 +38,11 @@ use transform::qualify_consts;
 
 pub struct CopyPropagation;
 
-impl Pass for CopyPropagation {}
-
-impl<'tcx> MirPass<'tcx> for CopyPropagation {
-    fn run_pass<'a>(&mut self,
-                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    source: MirSource,
-                    mir: &mut Mir<'tcx>) {
+impl MirPass for CopyPropagation {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          source: MirSource,
+                          mir: &mut Mir<'tcx>) {
         match source {
             MirSource::Const(_) => {
                 // Don't run on constants, because constant qualification might reject the
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index 3a93bef36c5..4309f91c635 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -10,16 +10,16 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_vec::Idx;
 
 pub struct Deaggregator;
 
-impl Pass for Deaggregator {}
-
-impl<'tcx> MirPass<'tcx> for Deaggregator {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    source: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for Deaggregator {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          source: MirSource,
+                          mir: &mut Mir<'tcx>) {
         let node_id = source.item_id();
         let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));
         debug!("running on: {:?}", node_path);
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index 5b3113f962b..67a3281dba4 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -10,70 +10,66 @@
 
 //! This pass just dumps MIR at a specified point.
 
+use std::borrow::Cow;
 use std::fmt;
 use std::fs::File;
 use std::io;
 
+use rustc::mir::Mir;
+use rustc::mir::transform::{MirPass, MirPassIndex, MirSource, MirSuite, PassHook};
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
-use rustc::mir::*;
-use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource};
 use util as mir_util;
 
-pub struct Marker<'a>(pub &'a str);
+pub struct Marker(pub &'static str);
 
-impl<'b, 'tcx> MirPass<'tcx> for Marker<'b> {
-    fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    _src: MirSource, _mir: &mut Mir<'tcx>)
-    {}
-}
+impl MirPass for Marker {
+    fn name<'a>(&'a self) -> Cow<'a, str> {
+        Cow::Borrowed(self.0)
+    }
 
-impl<'b> Pass for Marker<'b> {
-    fn name(&self) -> ::std::borrow::Cow<'static, str> { String::from(self.0).into() }
+    fn run_pass<'a, 'tcx>(&self,
+                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _source: MirSource,
+                          _mir: &mut Mir<'tcx>)
+    {
+    }
 }
 
-pub struct Disambiguator<'a> {
-    pass: &'a Pass,
+pub struct Disambiguator {
     is_after: bool
 }
 
-impl<'a> fmt::Display for Disambiguator<'a> {
+impl fmt::Display for Disambiguator {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         let title = if self.is_after { "after" } else { "before" };
-        if let Some(fmt) = self.pass.disambiguator() {
-            write!(formatter, "{}-{}", fmt, title)
-        } else {
-            write!(formatter, "{}", title)
-        }
+        write!(formatter, "{}", title)
     }
 }
 
 pub struct DumpMir;
 
-impl<'tcx> MirPassHook<'tcx> for DumpMir {
-    fn on_mir_pass<'a>(
-        &mut self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        src: MirSource,
-        mir: &Mir<'tcx>,
-        pass: &Pass,
-        is_after: bool)
+impl PassHook for DumpMir {
+    fn on_mir_pass<'a, 'tcx: 'a>(&self,
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 suite: MirSuite,
+                                 pass_num: MirPassIndex,
+                                 pass_name: &str,
+                                 source: MirSource,
+                                 mir: &Mir<'tcx>,
+                                 is_after: bool)
     {
-        mir_util::dump_mir(
-            tcx,
-            &*pass.name(),
-            &Disambiguator {
-                pass: pass,
-                is_after: is_after
-            },
-            src,
-            mir
-        );
+        if mir_util::dump_enabled(tcx, pass_name, source) {
+            mir_util::dump_mir(tcx,
+                               Some((suite, pass_num)),
+                               pass_name,
+                               &Disambiguator { is_after },
+                               source,
+                               mir);
+        }
     }
 }
 
-impl<'b> Pass for DumpMir {}
-
 pub fn emit_mir<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     outputs: &OutputFilenames)
@@ -81,6 +77,6 @@ pub fn emit_mir<'a, 'tcx>(
 {
     let path = outputs.path(OutputType::Mir);
     let mut f = File::create(&path)?;
-    mir_util::write_mir_pretty(tcx, tcx.maps.mir.borrow().keys().into_iter(), &mut f)?;
+    mir_util::write_mir_pretty(tcx, None, &mut f)?;
     Ok(())
 }
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 5cc5cf29793..19714849b09 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -16,7 +16,7 @@ use rustc::ty::subst::Substs;
 use rustc::ty::{Ty, TyCtxt, ClosureSubsts};
 use rustc::mir::*;
 use rustc::mir::visit::MutVisitor;
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -69,11 +69,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
 
 pub struct EraseRegions;
 
-impl Pass for EraseRegions {}
-
-impl<'tcx> MirPass<'tcx> for EraseRegions {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    _: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for EraseRegions {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _: MirSource,
+                          mir: &mut Mir<'tcx>) {
         EraseRegionsVisitor::new(tcx).visit_mir(mir);
     }
 }
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 45bdff9195c..f60dcbed6ba 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -14,24 +14,20 @@ use rustc::hir::def_id::DefId;
 
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::graph;
 
-use rustc::dep_graph::DepNode;
 use rustc::mir::*;
-use rustc::mir::transform::{MirMapPass, MirPassHook, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::*;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Subst,Substs};
-use rustc::util::nodemap::{DefIdSet};
 
+use std::collections::VecDeque;
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
 
 use syntax::{attr};
 use syntax::abi::Abi;
 
-use callgraph;
-
 const DEFAULT_THRESHOLD: usize = 50;
 const HINT_THRESHOLD: usize = 100;
 
@@ -42,178 +38,94 @@ const UNKNOWN_SIZE_COST: usize = 10;
 
 pub struct Inline;
 
-impl<'tcx> MirMapPass<'tcx> for Inline {
-    fn run_pass<'a>(
-        &mut self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
-
-        if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { return; }
-
-        let _ignore = tcx.dep_graph.in_ignore();
-
-        let callgraph = callgraph::CallGraph::build(tcx);
-
-        let mut inliner = Inliner {
-            tcx: tcx,
-        };
-
-        let def_ids = tcx.maps.mir.borrow().keys();
-        for &def_id in &def_ids {
-            if !def_id.is_local() { continue; }
-
-            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
-            let mut mir = if let Some(mir) = tcx.maps.mir.borrow().get(&def_id) {
-                mir.borrow_mut()
-            } else {
-                continue;
-            };
-
-            tcx.dep_graph.write(DepNode::Mir(def_id));
-
-            let id = tcx.hir.as_local_node_id(def_id).unwrap();
-            let src = MirSource::from_node(tcx, id);
-
-            for hook in &mut *hooks {
-                hook.on_mir_pass(tcx, src, &mut mir, self, false);
-            }
-        }
-
-        for scc in callgraph.scc_iter() {
-            inliner.inline_scc(&callgraph, &scc);
-        }
-
-        for def_id in def_ids {
-            if !def_id.is_local() { continue; }
-
-            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
-            let mut mir = tcx.maps.mir.borrow()[&def_id].borrow_mut();
-            tcx.dep_graph.write(DepNode::Mir(def_id));
-
-            let id = tcx.hir.as_local_node_id(def_id).unwrap();
-            let src = MirSource::from_node(tcx, id);
-
-            for hook in &mut *hooks {
-                hook.on_mir_pass(tcx, src, &mut mir, self, true);
-            }
-        }
-    }
-}
-
-impl<'tcx> Pass for Inline { }
-
-struct Inliner<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-}
-
 #[derive(Copy, Clone)]
 struct CallSite<'tcx> {
-    caller: DefId,
     callee: DefId,
     substs: &'tcx Substs<'tcx>,
     bb: BasicBlock,
     location: SourceInfo,
 }
 
-impl<'a, 'tcx> Inliner<'a, 'tcx> {
-    fn inline_scc(&mut self, callgraph: &callgraph::CallGraph, scc: &[graph::NodeIndex]) -> bool {
-        let mut callsites = Vec::new();
-        let mut in_scc = DefIdSet();
-
-        let mut inlined_into = DefIdSet();
+impl MirPass for Inline {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          source: MirSource,
+                          mir: &mut Mir<'tcx>) {
+        if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+            Inliner { tcx, source }.run_pass(mir);
+        }
+    }
+}
 
-        for &node in scc {
-            let def_id = callgraph.def_id(node);
+struct Inliner<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    source: MirSource,
+}
 
-            // Don't inspect functions from other crates
-            let id = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
-                id
-            } else {
-                continue;
-            };
-            let src = MirSource::from_node(self.tcx, id);
-            if let MirSource::Fn(_) = src {
-                if let Some(mir) = self.tcx.maybe_item_mir(def_id) {
-                    for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
-                        // Don't inline calls that are in cleanup blocks.
-                        if bb_data.is_cleanup { continue; }
-
-                        // Only consider direct calls to functions
-                        let terminator = bb_data.terminator();
-                        if let TerminatorKind::Call {
-                            func: Operand::Constant(ref f), .. } = terminator.kind {
-                            if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
-                                callsites.push(CallSite {
-                                    caller: def_id,
-                                    callee: callee_def_id,
-                                    substs: substs,
-                                    bb: bb,
-                                    location: terminator.source_info
-                                });
-                            }
-                        }
+impl<'a, 'tcx> Inliner<'a, 'tcx> {
+    fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
+        // Keep a queue of callsites to try inlining on. We take
+        // advantage of the fact that queries detect cycles here to
+        // allow us to try and fetch the fully optimized MIR of a
+        // call; if it succeeds, we can inline it and we know that
+        // they do not call us.  Otherwise, we just don't try to
+        // inline.
+        //
+        // We use a queue so that we inline "broadly" before we inline
+        // in depth. It is unclear if this is the best heuristic,
+        // really, but that's true of all the heuristics in this
+        // file. =)
+
+        let mut callsites = VecDeque::new();
+
+        // Only do inlining into fn bodies.
+        if let MirSource::Fn(_) = self.source {
+            for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
+                // Don't inline calls that are in cleanup blocks.
+                if bb_data.is_cleanup { continue; }
+
+                // Only consider direct calls to functions
+                let terminator = bb_data.terminator();
+                if let TerminatorKind::Call {
+                    func: Operand::Constant(ref f), .. } = terminator.kind {
+                    if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                        callsites.push_back(CallSite {
+                            callee: callee_def_id,
+                            substs: substs,
+                            bb: bb,
+                            location: terminator.source_info
+                        });
                     }
-
-                    in_scc.insert(def_id);
                 }
             }
         }
 
-        // Move callsites that are in the the SCC to the end so
-        // they're inlined after calls to outside the SCC
-        let mut first_call_in_scc = callsites.len();
-
-        let mut i = 0;
-        while i < first_call_in_scc {
-            let f = callsites[i].caller;
-            if in_scc.contains(&f) {
-                first_call_in_scc -= 1;
-                callsites.swap(i, first_call_in_scc);
-            } else {
-                i += 1;
-            }
-        }
-
         let mut local_change;
         let mut changed = false;
 
         loop {
             local_change = false;
-            let mut csi = 0;
-            while csi < callsites.len() {
-                let callsite = callsites[csi];
-                csi += 1;
-
-                let _task = self.tcx.dep_graph.in_task(DepNode::Mir(callsite.caller));
-                self.tcx.dep_graph.write(DepNode::Mir(callsite.caller));
-
-                let callee_mir = {
-                    if let Some(callee_mir) = self.tcx.maybe_item_mir(callsite.callee) {
-                        if !self.should_inline(callsite, &callee_mir) {
-                            continue;
-                        }
+            while let Some(callsite) = callsites.pop_front() {
+                if !self.tcx.is_mir_available(callsite.callee) {
+                    continue;
+                }
 
+                let callee_mir = match ty::queries::optimized_mir::try_get(self.tcx,
+                                                                           callsite.location.span,
+                                                                           callsite.callee) {
+                    Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
                         callee_mir.subst(self.tcx, callsite.substs)
-                    } else {
-                        continue;
                     }
 
-                };
-
-                let mut caller_mir = {
-                    let map = self.tcx.maps.mir.borrow();
-                    let mir = map.get(&callsite.caller).unwrap();
-                    mir.borrow_mut()
+                    _ => continue,
                 };
 
                 let start = caller_mir.basic_blocks().len();
 
-                if !self.inline_call(callsite, &mut caller_mir, callee_mir) {
+                if !self.inline_call(callsite, caller_mir, callee_mir) {
                     continue;
                 }
 
-                inlined_into.insert(callsite.caller);
-
                 // Add callsites from inlined function
                 for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
                     // Only consider direct calls to functions
@@ -223,8 +135,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                         if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
                             // Don't inline the same function multiple times.
                             if callsite.callee != callee_def_id {
-                                callsites.push(CallSite {
-                                    caller: callsite.caller,
+                                callsites.push_back(CallSite {
                                     callee: callee_def_id,
                                     substs: substs,
                                     bb: bb,
@@ -235,13 +146,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     }
                 }
 
-                csi -= 1;
-                if scc.len() == 1 {
-                    callsites.swap_remove(csi);
-                } else {
-                    callsites.remove(csi);
-                }
-
                 local_change = true;
                 changed = true;
             }
@@ -251,27 +155,19 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             }
         }
 
-        // Simplify functions we inlined into.
-        for def_id in inlined_into {
-            let _task = self.tcx.dep_graph.in_task(DepNode::Mir(def_id));
-            self.tcx.dep_graph.write(DepNode::Mir(def_id));
-
-            let mut caller_mir = {
-                let map = self.tcx.maps.mir.borrow();
-                let mir = map.get(&def_id).unwrap();
-                mir.borrow_mut()
-            };
-
-            debug!("Running simplify cfg on {:?}", def_id);
-            CfgSimplifier::new(&mut caller_mir).simplify();
-            remove_dead_blocks(&mut caller_mir);
+        // Simplify if we inlined anything.
+        if changed {
+            debug!("Running simplify cfg on {:?}", self.source);
+            CfgSimplifier::new(caller_mir).simplify();
+            remove_dead_blocks(caller_mir);
         }
-        changed
     }
 
-    fn should_inline(&self, callsite: CallSite<'tcx>,
-                     callee_mir: &'a Mir<'tcx>) -> bool {
-
+    fn should_inline(&self,
+                     callsite: CallSite<'tcx>,
+                     callee_mir: &Mir<'tcx>)
+                     -> bool
+    {
         let tcx = self.tcx;
 
         // Don't inline closures that have captures
@@ -323,8 +219,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
         // FIXME: Give a bonus to functions with only a single caller
 
-        let id = tcx.hir.as_local_node_id(callsite.caller).expect("Caller not local");
-        let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+        let param_env = ty::ParameterEnvironment::for_item(tcx, self.source.item_id());
 
         let mut first_block = true;
         let mut cost = 0;
@@ -423,22 +318,15 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         }
     }
 
-
-    fn inline_call(&self, callsite: CallSite<'tcx>,
-                             caller_mir: &mut Mir<'tcx>, mut callee_mir: Mir<'tcx>) -> bool {
-
-        // Don't inline a function into itself
-        if callsite.caller == callsite.callee { return false; }
-
-        let _task = self.tcx.dep_graph.in_task(DepNode::Mir(callsite.caller));
-
-
+    fn inline_call(&self,
+                   callsite: CallSite<'tcx>,
+                   caller_mir: &mut Mir<'tcx>,
+                   mut callee_mir: Mir<'tcx>) -> bool {
         let terminator = caller_mir[callsite.bb].terminator.take().unwrap();
         match terminator.kind {
             // FIXME: Handle inlining of diverging calls
             TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
-
-                debug!("Inlined {:?} into {:?}", callsite.callee, callsite.caller);
+                debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
 
                 let is_box_free = Some(callsite.callee) == self.tcx.lang_items.box_free_fn();
 
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 3f6abb31fe9..88a368077d4 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -11,32 +11,20 @@
 //! Performs various peephole optimizations.
 
 use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::TyCtxt;
 use rustc::util::nodemap::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
 
-pub struct InstCombine {
-    optimizations: OptimizationList,
-}
-
-impl InstCombine {
-    pub fn new() -> InstCombine {
-        InstCombine {
-            optimizations: OptimizationList::default(),
-        }
-    }
-}
-
-impl Pass for InstCombine {}
+pub struct InstCombine;
 
-impl<'tcx> MirPass<'tcx> for InstCombine {
-    fn run_pass<'a>(&mut self,
-                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    _: MirSource,
-                    mir: &mut Mir<'tcx>) {
+impl MirPass for InstCombine {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _: MirSource,
+                          mir: &mut Mir<'tcx>) {
         // We only run when optimizing MIR (at any level).
         if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
             return
@@ -45,18 +33,22 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
         // First, find optimization opportunities. This is done in a pre-pass to keep the MIR
         // read-only so that we can do global analyses on the MIR in the process (e.g.
         // `Lvalue::ty()`).
-        {
+        let optimizations = {
             let mut optimization_finder = OptimizationFinder::new(mir, tcx);
             optimization_finder.visit_mir(mir);
-            self.optimizations = optimization_finder.optimizations
-        }
+            optimization_finder.optimizations
+        };
 
         // Then carry out those optimizations.
-        MutVisitor::visit_mir(&mut *self, mir);
+        MutVisitor::visit_mir(&mut InstCombineVisitor { optimizations }, mir);
     }
 }
 
-impl<'tcx> MutVisitor<'tcx> for InstCombine {
+pub struct InstCombineVisitor {
+    optimizations: OptimizationList,
+}
+
+impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
     fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
         if self.optimizations.and_stars.remove(&location) {
             debug!("Replacing `&*`: {:?}", rvalue);
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index cbd054a7249..fcea5d4c860 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -8,6 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use build;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::mir::Mir;
+use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource,
+                            MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
+use rustc::ty::{self, TyCtxt};
+use rustc::ty::maps::Providers;
+use rustc::ty::steal::Steal;
+use rustc::hir;
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use rustc::util::nodemap::DefIdSet;
+use std::rc::Rc;
+use syntax::ast;
+use syntax_pos::{DUMMY_SP, Span};
+use transform;
+
 pub mod simplify_branches;
 pub mod simplify;
 pub mod erase_regions;
@@ -21,3 +37,114 @@ pub mod deaggregator;
 pub mod instcombine;
 pub mod copy_prop;
 pub mod inline;
+
+pub(crate) fn provide(providers: &mut Providers) {
+    self::qualify_consts::provide(providers);
+    *providers = Providers {
+        mir_keys,
+        mir_const,
+        mir_validated,
+        optimized_mir,
+        is_mir_available,
+        ..*providers
+    };
+}
+
+fn is_mir_available<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
+    tcx.mir_keys(def_id.krate).contains(&def_id)
+}
+
+/// Finds the full set of def-ids within the current crate that have
+/// MIR associated with them.
+fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
+                      -> Rc<DefIdSet> {
+    assert_eq!(krate, LOCAL_CRATE);
+
+    let mut set = DefIdSet();
+
+    // All body-owners have MIR associated with them.
+    set.extend(tcx.body_owners());
+
+    // Additionally, tuple struct/variant constructors have MIR, but
+    // they don't have a BodyId, so we need to build them separately.
+    struct GatherCtors<'a, 'tcx: 'a> {
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        set: &'a mut DefIdSet,
+    }
+    impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
+        fn visit_variant_data(&mut self,
+                              v: &'tcx hir::VariantData,
+                              _: ast::Name,
+                              _: &'tcx hir::Generics,
+                              _: ast::NodeId,
+                              _: Span) {
+            if let hir::VariantData::Tuple(_, node_id) = *v {
+                self.set.insert(self.tcx.hir.local_def_id(node_id));
+            }
+            intravisit::walk_struct_def(self, v)
+        }
+        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
+            NestedVisitorMap::None
+        }
+    }
+    tcx.hir.krate().visit_all_item_likes(&mut GatherCtors {
+        tcx: tcx,
+        set: &mut set,
+    }.as_deep_visitor());
+
+    Rc::new(set)
+}
+
+fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+    let mut mir = build::mir_build(tcx, def_id);
+    let source = MirSource::from_local_def_id(tcx, def_id);
+    transform::run_suite(tcx, source, MIR_CONST, &mut mir);
+    tcx.alloc_steal_mir(mir)
+}
+
+fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+    let source = MirSource::from_local_def_id(tcx, def_id);
+    if let MirSource::Const(_) = source {
+        // Ensure that we compute the `mir_const_qualif` for constants at
+        // this point, before we steal the mir-const result. We don't
+        // directly need the result or `mir_const_qualif`, so we can just force it.
+        ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, def_id);
+    }
+
+    let mut mir = tcx.mir_const(def_id).steal();
+    transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
+    tcx.alloc_steal_mir(mir)
+}
+
+fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
+    // Borrowck uses `mir_validated`, so we have to force it to
+    // execute before we can steal.
+    ty::queries::borrowck::force(tcx, DUMMY_SP, def_id);
+
+    let mut mir = tcx.mir_validated(def_id).steal();
+    let source = MirSource::from_local_def_id(tcx, def_id);
+    transform::run_suite(tcx, source, MIR_OPTIMIZED, &mut mir);
+    tcx.alloc_mir(mir)
+}
+
+fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                       source: MirSource,
+                       suite: MirSuite,
+                       mir: &mut Mir<'tcx>)
+{
+    let passes = tcx.mir_passes.passes(suite);
+
+    for (pass, index) in passes.iter().zip(0..) {
+        let pass_num = MirPassIndex(index);
+
+        for hook in tcx.mir_passes.hooks() {
+            hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false);
+        }
+
+        pass.run_pass(tcx, source, mir);
+
+        for hook in tcx.mir_passes.hooks() {
+            hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
+        }
+    }
+}
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index 3654ae6940c..8595663ba18 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -14,10 +14,25 @@
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
 use rustc::mir::visit::MutVisitor;
-use rustc::mir::transform::{Pass, MirPass, MirSource};
+use rustc::mir::transform::{MirPass, MirSource};
 
 pub struct NoLandingPads;
 
+impl MirPass for NoLandingPads {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _: MirSource,
+                          mir: &mut Mir<'tcx>) {
+        no_landing_pads(tcx, mir)
+    }
+}
+
+pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
+    if tcx.sess.no_landing_pads() {
+        NoLandingPads.visit_mir(mir);
+    }
+}
+
 impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
     fn visit_terminator(&mut self,
                         bb: BasicBlock,
@@ -41,18 +56,3 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
         self.super_terminator(bb, terminator, location);
     }
 }
-
-pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
-    if tcx.sess.no_landing_pads() {
-        NoLandingPads.visit_mir(mir);
-    }
-}
-
-impl<'tcx> MirPass<'tcx> for NoLandingPads {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    _: MirSource, mir: &mut Mir<'tcx>) {
-        no_landing_pads(tcx, mir)
-    }
-}
-
-impl Pass for NoLandingPads {}
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index afb775aa01e..4b1c82f383f 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -16,7 +16,6 @@
 
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
@@ -27,7 +26,7 @@ use rustc::ty::cast::CastTy;
 use rustc::ty::maps::Providers;
 use rustc::mir::*;
 use rustc::mir::traversal::ReversePostorder;
-use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{LvalueContext, Visitor};
 use rustc::middle::lang_items;
 use syntax::abi::Abi;
@@ -919,13 +918,21 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
 }
 
 pub fn provide(providers: &mut Providers) {
-    providers.mir_const_qualif = qualify_const_item;
+    *providers = Providers {
+        mir_const_qualif,
+        ..*providers
+    };
 }
 
-fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                def_id: DefId)
-                                -> u8 {
-    let mir = &tcx.item_mir(def_id);
+fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              def_id: DefId)
+                              -> u8 {
+    // NB: This `borrow()` is guaranteed to be valid (i.e., the value
+    // cannot yet be stolen), because `mir_validated()`, which steals
+    // from `mir_const(), forces this query to execute before
+    // performing the steal.
+    let mir = &tcx.mir_const(def_id).borrow();
+
     if mir.return_ty.references_error() {
         return Qualif::NOT_CONST.bits();
     }
@@ -939,45 +946,11 @@ fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 pub struct QualifyAndPromoteConstants;
 
-impl Pass for QualifyAndPromoteConstants {}
-
-impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
-    fn run_pass<'a>(&mut self,
-                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    hooks: &mut [Box<for<'s> MirPassHook<'s>>])
-    {
-        let def_ids = tcx.maps.mir.borrow().keys();
-        for def_id in def_ids {
-            if !def_id.is_local() {
-                continue;
-            }
-
-            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
-            let id = tcx.hir.as_local_node_id(def_id).unwrap();
-            let src = MirSource::from_node(tcx, id);
-
-            if let MirSource::Const(_) = src {
-                tcx.mir_const_qualif(def_id);
-                continue;
-            }
-
-            let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut();
-            tcx.dep_graph.write(DepNode::Mir(def_id));
-
-            for hook in &mut *hooks {
-                hook.on_mir_pass(tcx, src, mir, self, false);
-            }
-            self.run_pass(tcx, src, mir);
-            for hook in &mut *hooks {
-                hook.on_mir_pass(tcx, src, mir, self, true);
-            }
-        }
-    }
-}
-
-impl<'tcx> QualifyAndPromoteConstants {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    src: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for QualifyAndPromoteConstants {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          src: MirSource,
+                          mir: &mut Mir<'tcx>) {
         let id = src.item_id();
         let def_id = tcx.hir.local_def_id(id);
         let mode = match src {
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index ef7990653ba..d5b79c0d1c3 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -41,15 +41,15 @@ use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{MutVisitor, Visitor, LvalueContext};
-use std::fmt;
+use std::borrow::Cow;
 
-pub struct SimplifyCfg<'a> { label: &'a str }
+pub struct SimplifyCfg { label: String }
 
-impl<'a> SimplifyCfg<'a> {
-    pub fn new(label: &'a str) -> Self {
-        SimplifyCfg { label: label }
+impl SimplifyCfg {
+    pub fn new(label: &str) -> Self {
+        SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
     }
 }
 
@@ -61,20 +61,18 @@ pub fn simplify_cfg(mir: &mut Mir) {
     mir.basic_blocks_mut().raw.shrink_to_fit();
 }
 
-impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
-    fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
-        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
-        simplify_cfg(mir);
+impl MirPass for SimplifyCfg {
+    fn name<'a>(&'a self) -> Cow<'a, str> {
+        Cow::Borrowed(&self.label)
     }
-}
 
-impl<'l> Pass for SimplifyCfg<'l> {
-    fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> {
-        Some(Box::new(self.label))
+    fn run_pass<'a, 'tcx>(&self,
+                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _src: MirSource,
+                          mir: &mut Mir<'tcx>) {
+        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
+        simplify_cfg(mir);
     }
-
-    // avoid calling `type_name` - it contains `<'static>`
-    fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyCfg".into() }
 }
 
 pub struct CfgSimplifier<'a, 'tcx: 'a> {
@@ -315,12 +313,11 @@ pub fn remove_dead_blocks(mir: &mut Mir) {
 
 pub struct SimplifyLocals;
 
-impl Pass for SimplifyLocals {
-    fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyLocals".into() }
-}
-
-impl<'tcx> MirPass<'tcx> for SimplifyLocals {
-    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for SimplifyLocals {
+    fn run_pass<'a, 'tcx>(&self,
+                          _: TyCtxt<'a, 'tcx, 'tcx>,
+                          _: MirSource,
+                          mir: &mut Mir<'tcx>) {
         let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) };
         marker.visit_mir(mir);
         // Return pointer and arguments are always live
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 3d5106c4b06..d21a6ddfdfb 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -12,21 +12,28 @@
 
 use rustc::ty::TyCtxt;
 use rustc::middle::const_val::ConstVal;
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::*;
 
-use std::fmt;
+use std::borrow::Cow;
 
-pub struct SimplifyBranches<'a> { label: &'a str }
+pub struct SimplifyBranches { label: String }
 
-impl<'a> SimplifyBranches<'a> {
-    pub fn new(label: &'a str) -> Self {
-        SimplifyBranches { label: label }
+impl SimplifyBranches {
+    pub fn new(label: &str) -> Self {
+        SimplifyBranches { label: format!("SimplifyBranches-{}", label) }
     }
 }
 
-impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> {
-    fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for SimplifyBranches {
+    fn name<'a>(&'a self) -> Cow<'a, str> {
+        Cow::Borrowed(&self.label)
+    }
+
+    fn run_pass<'a, 'tcx>(&self,
+                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _src: MirSource,
+                          mir: &mut Mir<'tcx>) {
         for block in mir.basic_blocks_mut() {
             let terminator = block.terminator_mut();
             terminator.kind = match terminator.kind {
@@ -60,11 +67,3 @@ impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> {
     }
 }
 
-impl<'l> Pass for SimplifyBranches<'l> {
-    fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> {
-        Some(Box::new(self.label))
-    }
-
-    // avoid calling `type_name` - it contains `<'static>`
-    fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyBranches".into() }
-}
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index d2e4c1a9649..b325470ec81 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -18,7 +18,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::tcx::LvalueTy;
-use rustc::mir::transform::{MirPass, MirSource, Pass};
+use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::Visitor;
 use std::fmt;
 use syntax::ast;
@@ -737,9 +737,11 @@ impl TypeckMir {
     }
 }
 
-impl<'tcx> MirPass<'tcx> for TypeckMir {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    src: MirSource, mir: &mut Mir<'tcx>) {
+impl MirPass for TypeckMir {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          src: MirSource,
+                          mir: &mut Mir<'tcx>) {
         let item_id = src.item_id();
         let def_id = tcx.hir.local_def_id(item_id);
         debug!("run_pass: {}", tcx.item_path_str(def_id));
@@ -765,6 +767,3 @@ impl<'tcx> MirPass<'tcx> for TypeckMir {
         });
     }
 }
-
-impl Pass for TypeckMir {
-}
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 91600b947c6..cf13a80e677 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -18,16 +18,18 @@ use syntax::ast::NodeId;
 
 use rustc_data_structures::indexed_vec::Idx;
 
+use super::pretty::dump_mir_def_ids;
+
 /// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                                              iter: I,
-                                              w: &mut W)
-                                              -> io::Result<()>
-    where W: Write, I: Iterator<Item=DefId>
+pub fn write_mir_graphviz<'a, 'tcx, W>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                       single: Option<DefId>,
+                                       w: &mut W)
+                                       -> io::Result<()>
+    where W: Write
 {
-    for def_id in iter {
+    for def_id in dump_mir_def_ids(tcx, single) {
         let nodeid = tcx.hir.as_local_node_id(def_id).unwrap();
-        let mir = &tcx.item_mir(def_id);
+        let mir = &tcx.optimized_mir(def_id);
 
         writeln!(w, "digraph Mir_{} {{", nodeid)?;
 
diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs
index cafc5bca76a..4386bab38c0 100644
--- a/src/librustc_mir/util/mod.rs
+++ b/src/librustc_mir/util/mod.rs
@@ -15,6 +15,6 @@ pub mod patch;
 mod graphviz;
 mod pretty;
 
-pub use self::pretty::{dump_mir, write_mir_pretty};
+pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty};
 pub use self::graphviz::{write_mir_graphviz};
 pub use self::graphviz::write_node_label as write_graphviz_node_label;
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index b202e149510..5f51888019b 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 use rustc::hir;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::*;
-use rustc::mir::transform::MirSource;
+use rustc::mir::transform::{MirSuite, MirPassIndex, MirSource};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::{Idx};
@@ -28,7 +28,7 @@ const ALIGN: usize = 40;
 /// representation of the mir into:
 ///
 /// ```text
-/// rustc.node<node_id>.<pass_name>.<disambiguator>
+/// rustc.node<node_id>.<pass_num>.<pass_name>.<disambiguator>
 /// ```
 ///
 /// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
@@ -39,64 +39,95 @@ const ALIGN: usize = 40;
 ///   that can appear in the pass-name or the `item_path_str` for the given
 ///   node-id. If any one of the substrings match, the data is dumped out.
 pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          pass_num: Option<(MirSuite, MirPassIndex)>,
                           pass_name: &str,
                           disambiguator: &Display,
-                          src: MirSource,
+                          source: MirSource,
                           mir: &Mir<'tcx>) {
+    if !dump_enabled(tcx, pass_name, source) {
+        return;
+    }
+
+    let node_path = tcx.item_path_str(tcx.hir.local_def_id(source.item_id()));
+    dump_matched_mir_node(tcx, pass_num, pass_name, &node_path,
+                          disambiguator, source, mir);
+    for (index, promoted_mir) in mir.promoted.iter_enumerated() {
+        let promoted_source = MirSource::Promoted(source.item_id(), index);
+        dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator,
+                              promoted_source, promoted_mir);
+    }
+}
+
+pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              pass_name: &str,
+                              source: MirSource)
+                              -> bool {
     let filters = match tcx.sess.opts.debugging_opts.dump_mir {
-        None => return,
+        None => return false,
         Some(ref filters) => filters,
     };
-    let node_id = src.item_id();
+    let node_id = source.item_id();
     let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));
-    let is_matched =
-        filters.split("&")
-               .any(|filter| {
-                   filter == "all" ||
-                       pass_name.contains(filter) ||
-                       node_path.contains(filter)
-               });
-    if !is_matched {
-        return;
-    }
+    filters.split("&")
+           .any(|filter| {
+               filter == "all" ||
+                   pass_name.contains(filter) ||
+                   node_path.contains(filter)
+           })
+}
 
-    let promotion_id = match src {
+fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   pass_num: Option<(MirSuite, MirPassIndex)>,
+                                   pass_name: &str,
+                                   node_path: &str,
+                                   disambiguator: &Display,
+                                   source: MirSource,
+                                   mir: &Mir<'tcx>) {
+    let promotion_id = match source {
         MirSource::Promoted(_, id) => format!("-{:?}", id),
         _ => String::new()
     };
 
+    let pass_num = if tcx.sess.opts.debugging_opts.dump_mir_exclude_pass_number {
+        format!("")
+    } else {
+        match pass_num {
+            None => format!(".-------"),
+            Some((suite, pass_num)) => format!(".{:03}-{:03}", suite.0, pass_num.0),
+        }
+    };
+
     let mut file_path = PathBuf::new();
     if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
         let p = Path::new(file_dir);
         file_path.push(p);
     };
-    let file_name = format!("rustc.node{}{}.{}.{}.mir",
-                            node_id, promotion_id, pass_name, disambiguator);
+    let file_name = format!("rustc.node{}{}{}.{}.{}.mir",
+                            source.item_id(), promotion_id, pass_num, pass_name, disambiguator);
     file_path.push(&file_name);
     let _ = fs::File::create(&file_path).and_then(|mut file| {
         writeln!(file, "// MIR for `{}`", node_path)?;
-        writeln!(file, "// node_id = {}", node_id)?;
+        writeln!(file, "// source = {:?}", source)?;
         writeln!(file, "// pass_name = {}", pass_name)?;
         writeln!(file, "// disambiguator = {}", disambiguator)?;
         writeln!(file, "")?;
-        write_mir_fn(tcx, src, mir, &mut file)?;
+        write_mir_fn(tcx, source, mir, &mut file)?;
         Ok(())
     });
 }
 
 /// Write out a human-readable textual representation for the given MIR.
-pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                                         iter: I,
-                                         w: &mut Write)
-                                         -> io::Result<()>
-    where I: Iterator<Item=DefId>, 'tcx: 'a
+pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  single: Option<DefId>,
+                                  w: &mut Write)
+                                  -> io::Result<()>
 {
     writeln!(w, "// WARNING: This output format is intended for human consumers only")?;
     writeln!(w, "// and is subject to change without notice. Knock yourself out.")?;
 
     let mut first = true;
-    for def_id in iter.filter(DefId::is_local) {
-        let mir = &tcx.item_mir(def_id);
+    for def_id in dump_mir_def_ids(tcx, single) {
+        let mir = &tcx.optimized_mir(def_id);
 
         if first {
             first = false;
@@ -312,3 +343,11 @@ fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
 
     Ok(())
 }
+
+pub fn dump_mir_def_ids(tcx: TyCtxt, single: Option<DefId>) -> Vec<DefId> {
+    if let Some(i) = single {
+        vec![i]
+    } else {
+        tcx.mir_keys(LOCAL_CRATE).iter().cloned().collect()
+    }
+}
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index ce02cb0e836..d9921e62330 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -13,6 +13,7 @@
 // completely accurate (some things might be counted twice, others missed).
 
 use rustc_const_math::{ConstUsize};
+use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::const_val::{ConstVal};
 use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
 use rustc::mir::{Constant, Literal, Location, LocalDecl};
@@ -44,10 +45,9 @@ pub fn print_mir_stats<'tcx, 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, title: &str) {
     // For debugging instrumentation like this, we don't need to worry
     // about maintaining the dep graph.
     let _ignore = tcx.dep_graph.in_ignore();
-    let mir_map = tcx.maps.mir.borrow();
-    for def_id in mir_map.keys() {
-        let mir = mir_map.get(&def_id).unwrap();
-        collector.visit_mir(&mir.borrow());
+    for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
+        let mir = tcx.optimized_mir(def_id);
+        collector.visit_mir(&mir);
     }
     collector.print(title);
 }
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 78600116157..6d7d95f5487 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -659,7 +659,7 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
                 // in this crate
                 false
             } else {
-                if !tcx.is_item_mir_available(def_id) {
+                if !tcx.is_mir_available(def_id) {
                     bug!("Cannot create local trans-item for {:?}", def_id)
                 }
                 true
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c401ed428e4..11095e70f62 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -640,9 +640,9 @@ pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult
 fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult {
     debug_assert!(crate_num == LOCAL_CRATE);
     tcx.sess.track_errors(|| {
-        tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+        for body_owner_def_id in tcx.body_owners() {
             tcx.typeck_tables_of(body_owner_def_id);
-        });
+        }
     })
 }
 
diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs
index 9c924a23903..e4eb1aeaf9b 100644
--- a/src/test/mir-opt/basic_assignment.rs
+++ b/src/test/mir-opt/basic_assignment.rs
@@ -36,7 +36,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg.initial-after.mir
+// START rustc.node4.SimplifyCfg-initial.after.mir
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const false;
@@ -82,4 +82,4 @@ fn main() {
 //         StorageDead(_1);
 //         return;
 //     }
-// END rustc.node4.SimplifyCfg.initial-after.mir
+// END rustc.node4.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs
index fbbffe8953b..5a9336e9659 100644
--- a/src/test/mir-opt/issue-38669.rs
+++ b/src/test/mir-opt/issue-38669.rs
@@ -21,7 +21,7 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyCfg.initial-after.mir
+// START rustc.node4.SimplifyCfg-initial.after.mir
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const false;
@@ -48,4 +48,4 @@ fn main() {
 //         _2 = ();
 //         goto -> bb1;
 //     }
-// END rustc.node4.SimplifyCfg.initial-after.mir
+// END rustc.node4.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs
index 6e80a917467..cff108246a5 100644
--- a/src/test/mir-opt/simplify_if.rs
+++ b/src/test/mir-opt/simplify_if.rs
@@ -15,13 +15,13 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.node4.SimplifyBranches.initial-before.mir
+// START rustc.node4.SimplifyBranches-initial.before.mir
 // bb0: {
 //     switchInt(const false) -> [0u8: bb2, otherwise: bb1];
 // }
-// END rustc.node4.SimplifyBranches.initial-before.mir
-// START rustc.node4.SimplifyBranches.initial-after.mir
+// END rustc.node4.SimplifyBranches-initial.before.mir
+// START rustc.node4.SimplifyBranches-initial.after.mir
 // bb0: {
 //     goto -> bb2;
 // }
-// END rustc.node4.SimplifyBranches.initial-after.mir
+// END rustc.node4.SimplifyBranches-initial.after.mir
diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr
index 5e743b6bd3f..de110ac12b7 100644
--- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr
+++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr
@@ -2,7 +2,10 @@ error[E0507]: cannot move out of indexed content
   --> $DIR/issue-40402-1.rs:19:13
    |
 19 |     let e = f.v[0];
-   |             ^^^^^^ cannot move out of indexed content
+   |             ^^^^^^
+   |             |
+   |             help: consider using a reference instead `&f.v[0]`
+   |             cannot move out of indexed content
 
 error: aborting due to previous error
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 731665ce034..a044282666d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1402,18 +1402,16 @@ actual:\n\
                 }
             }
             MirOpt => {
-                args.extend(["-Z",
-                             "dump-mir=all",
-                             "-Z",
-                             "mir-opt-level=3",
-                             "-Z"]
+                args.extend(["-Zdump-mir=all",
+                             "-Zmir-opt-level=3",
+                             "-Zdump-mir-exclude-pass-number"]
                             .iter()
                             .map(|s| s.to_string()));
 
 
                 let mir_dump_dir = self.get_mir_dump_dir();
                 create_dir_all(mir_dump_dir.as_path()).unwrap();
-                let mut dir_opt = "dump-mir-dir=".to_string();
+                let mut dir_opt = "-Zdump-mir-dir=".to_string();
                 dir_opt.push_str(mir_dump_dir.to_str().unwrap());
                 debug!("dir_opt: {:?}", dir_opt);