diff --git a/Cargo.lock b/Cargo.lock
index 488b2bb52a5..c92b7cb9b23 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -11,7 +11,7 @@ name = "atty"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -23,7 +23,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -33,8 +33,8 @@ name = "backtrace-sys"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -42,9 +42,14 @@ name = "bitflags"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "byteorder"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "cargo_metadata"
-version = "0.4.1"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -56,7 +61,7 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -66,11 +71,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "derive-new"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -83,6 +89,14 @@ name = "dtoa"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "ena"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "env_logger"
 version = "0.5.4"
@@ -151,7 +165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.37"
+version = "0.2.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -167,7 +181,7 @@ name = "memchr"
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -197,12 +211,20 @@ name = "parking_lot_core"
 version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "proc-macro2"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "quick-error"
 version = "1.2.1"
@@ -213,13 +235,21 @@ name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "quote"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -255,7 +285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "29.0.0"
+version = "57.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -264,57 +294,58 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "29.0.0"
+version = "57.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "29.0.0"
+version = "57.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "29.0.0"
+version = "57.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "29.0.0"
+version = "57.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "29.0.0"
+version = "57.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -328,21 +359,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "rustfmt-nightly"
 version = "0.4.0"
 dependencies = [
- "cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -417,6 +448,16 @@ dependencies = [
  "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "syn"
+version = "0.12.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "synom"
 version = "0.11.3"
@@ -434,6 +475,15 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "term"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "termcolor"
 version = "0.3.5"
@@ -447,7 +497,7 @@ name = "termion"
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -484,6 +534,11 @@ name = "unicode-xid"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "unreachable"
 version = "1.0.0"
@@ -545,12 +600,14 @@ dependencies = [
 "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
 "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
-"checksum cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f410f43295c912ae1328de55e5c050dbef882c17b836f5ed41cc8b96c40d6cc5"
-"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
+"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
+"checksum cargo_metadata 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab46e9ef52c8e10e1a41fe4064c77fb82abe4a1e532d259c1ee67624c984b099"
+"checksum cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9be26b24e988625409b19736d130f0c7d224f01d06454b5f81d8d23d6c1a618f"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba"
+"checksum derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92f8b8e1d6c8a5f5ea0849a0e4c55941576115c62d3fc425e96918bbbeb3d3c2"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
+"checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
 "checksum env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3cc21490995c841d68e00276eba02071ebb269ec24011d5728bd00eabd39e31"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
@@ -560,26 +617,28 @@ dependencies = [
 "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
-"checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9"
+"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
 "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
 "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
+"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
 "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
 "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b"
 "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
-"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524"
-"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad"
-"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182"
-"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b"
-"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d"
-"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
+"checksum rustc-ap-rustc_cratesio_shim 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cec17c61275586dc539c662c72a34cd907c2a3284656c1c7a73de43c38fb1c4a"
+"checksum rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8358567a8a378e34b5ffcd2e266b02a524ba8189374f6e90f788c1aae748cb63"
+"checksum rustc-ap-rustc_errors 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8e3ed225d3531044c1ddcbf31e79eaa00387451440a485818fec8e6a9e25d03"
+"checksum rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8415efe18266da2aa1b68dc386128485f5f360d6f6e5a4c4ad8d48e6f757c858"
+"checksum rustc-ap-syntax 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afd0049fc03db2c516e50c3089304d21de7ff0c38ed282a8ec655cc012c12145"
+"checksum rustc-ap-syntax_pos 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d51e454e21f66e41737d9294254ec8f7be392699834570a45d0155be30dda75"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
 "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
@@ -590,8 +649,10 @@ dependencies = [
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+"checksum syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)" = "517f6da31bc53bf080b9a77b29fbd0ff8da2f5a2ebd24c73c2238274a94ac7cb"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
+"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
 "checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
@@ -599,6 +660,7 @@ dependencies = [
 "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
+"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
diff --git a/Cargo.toml b/Cargo.toml
index dfaf38876db..3758862da67 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -41,15 +41,15 @@ serde_derive = "1.0"
 serde_json = "1.0"
 unicode-segmentation = "1.0.0"
 regex = "0.2"
-term = "0.4"
+term = "0.5"
 diff = "0.1"
 log = "0.4"
 env_logger = "0.5"
 getopts = "0.2"
 derive-new = "0.5"
-cargo_metadata = "0.4"
-rustc-ap-syntax = "29.0.0"
-rustc-ap-rustc_errors = "29.0.0"
+cargo_metadata = "0.5"
+rustc-ap-syntax = "57.0.0"
+rustc-ap-rustc_errors = "57.0.0"
 
 [dev-dependencies]
 lazy_static = "1.0.0"
diff --git a/src/codemap.rs b/src/codemap.rs
index 224b2083561..f6c05f5be40 100644
--- a/src/codemap.rs
+++ b/src/codemap.rs
@@ -22,6 +22,7 @@ pub trait SpanUtils {
     fn span_after_last(&self, original: Span, needle: &str) -> BytePos;
     fn span_before(&self, original: Span, needle: &str) -> BytePos;
     fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos>;
+    fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos>;
 }
 
 pub trait LineRangeUtils {
@@ -35,10 +36,7 @@ pub trait LineRangeUtils {
 
 impl<'a> SpanUtils for SnippetProvider<'a> {
     fn span_after(&self, original: Span, needle: &str) -> BytePos {
-        let snippet = self.span_to_snippet(original).expect("Bad snippet");
-        let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len();
-
-        original.lo() + BytePos(offset as u32)
+        self.opt_span_after(original, needle).expect("bad span")
     }
 
     fn span_after_last(&self, original: Span, needle: &str) -> BytePos {
@@ -53,15 +51,17 @@ impl<'a> SpanUtils for SnippetProvider<'a> {
     }
 
     fn span_before(&self, original: Span, needle: &str) -> BytePos {
-        let snippet = self.span_to_snippet(original).unwrap();
-        let offset = snippet.find_uncommented(needle).unwrap();
-
-        original.lo() + BytePos(offset as u32)
+        self.opt_span_before(original, needle).expect("bad span")
     }
 
     fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos> {
+        self.opt_span_before(original, needle)
+            .map(|bytepos| bytepos + BytePos(needle.len() as u32))
+    }
+
+    fn opt_span_before(&self, original: Span, needle: &str) -> Option<BytePos> {
         let snippet = self.span_to_snippet(original)?;
-        let offset = snippet.find_uncommented(needle)? + needle.len();
+        let offset = snippet.find_uncommented(needle)?;
 
         Some(original.lo() + BytePos(offset as u32))
     }
diff --git a/src/expr.rs b/src/expr.rs
index 8ce1166cfcd..2945f03a535 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -730,7 +730,7 @@ struct ControlFlow<'a> {
     block: &'a ast::Block,
     else_block: Option<&'a ast::Expr>,
     label: Option<ast::Label>,
-    pat: Option<&'a ast::Pat>,
+    pats: Vec<&'a ast::Pat>,
     keyword: &'a str,
     matcher: &'a str,
     connector: &'a str,
@@ -744,7 +744,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow>
     match expr.node {
         ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if(
             cond,
-            None,
+            vec![],
             if_block,
             else_block.as_ref().map(|e| &**e),
             expr_type == ExprType::SubExpression,
@@ -754,7 +754,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow>
         ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => {
             Some(ControlFlow::new_if(
                 cond,
-                Some(pat),
+                ptr_vec_to_ref_vec(pat),
                 if_block,
                 else_block.as_ref().map(|e| &**e),
                 expr_type == ExprType::SubExpression,
@@ -768,37 +768,47 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow>
         ast::ExprKind::Loop(ref block, label) => {
             Some(ControlFlow::new_loop(block, label, expr.span))
         }
-        ast::ExprKind::While(ref cond, ref block, label) => {
-            Some(ControlFlow::new_while(None, cond, block, label, expr.span))
-        }
+        ast::ExprKind::While(ref cond, ref block, label) => Some(ControlFlow::new_while(
+            vec![],
+            cond,
+            block,
+            label,
+            expr.span,
+        )),
         ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some(
-            ControlFlow::new_while(Some(pat), cond, block, label, expr.span),
+            ControlFlow::new_while(ptr_vec_to_ref_vec(pat), cond, block, label, expr.span),
         ),
         _ => None,
     }
 }
 
+fn choose_matcher(pats: &[&ast::Pat]) -> &'static str {
+    if pats.is_empty() {
+        ""
+    } else {
+        "let"
+    }
+}
+
 impl<'a> ControlFlow<'a> {
     fn new_if(
         cond: &'a ast::Expr,
-        pat: Option<&'a ast::Pat>,
+        pats: Vec<&'a ast::Pat>,
         block: &'a ast::Block,
         else_block: Option<&'a ast::Expr>,
         allow_single_line: bool,
         nested_if: bool,
         span: Span,
     ) -> ControlFlow<'a> {
+        let matcher = choose_matcher(&pats);
         ControlFlow {
             cond: Some(cond),
             block,
             else_block,
             label: None,
-            pat,
+            pats,
             keyword: "if",
-            matcher: match pat {
-                Some(..) => "let",
-                None => "",
-            },
+            matcher,
             connector: " =",
             allow_single_line,
             nested_if,
@@ -812,7 +822,7 @@ impl<'a> ControlFlow<'a> {
             block,
             else_block: None,
             label,
-            pat: None,
+            pats: vec![],
             keyword: "loop",
             matcher: "",
             connector: "",
@@ -823,23 +833,21 @@ impl<'a> ControlFlow<'a> {
     }
 
     fn new_while(
-        pat: Option<&'a ast::Pat>,
+        pats: Vec<&'a ast::Pat>,
         cond: &'a ast::Expr,
         block: &'a ast::Block,
         label: Option<ast::Label>,
         span: Span,
     ) -> ControlFlow<'a> {
+        let matcher = choose_matcher(&pats);
         ControlFlow {
             cond: Some(cond),
             block,
             else_block: None,
             label,
-            pat,
+            pats,
             keyword: "while",
-            matcher: match pat {
-                Some(..) => "let",
-                None => "",
-            },
+            matcher,
             connector: " =",
             allow_single_line: false,
             nested_if: false,
@@ -859,7 +867,7 @@ impl<'a> ControlFlow<'a> {
             block,
             else_block: None,
             label,
-            pat: Some(pat),
+            pats: vec![pat],
             keyword: "for",
             matcher: "",
             connector: " in",
@@ -914,6 +922,46 @@ impl<'a> ControlFlow<'a> {
 }
 
 impl<'a> ControlFlow<'a> {
+    fn rewrite_pat_expr(
+        &self,
+        context: &RewriteContext,
+        expr: &ast::Expr,
+        shape: Shape,
+        offset: usize,
+    ) -> Option<String> {
+        debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pats, expr);
+
+        let cond_shape = shape.offset_left(offset)?;
+        if !self.pats.is_empty() {
+            let matcher = if self.matcher.is_empty() {
+                self.matcher.to_owned()
+            } else {
+                format!("{} ", self.matcher)
+            };
+            let pat_shape = cond_shape
+                .offset_left(matcher.len())?
+                .sub_width(self.connector.len())?;
+            let pat_string = rewrite_multiple_patterns(context, &self.pats, pat_shape)?;
+            let result = format!("{}{}{}", matcher, pat_string, self.connector);
+            return rewrite_assign_rhs(context, result, expr, cond_shape);
+        }
+
+        let expr_rw = expr.rewrite(context, cond_shape);
+        // The expression may (partially) fit on the current line.
+        // We do not allow splitting between `if` and condition.
+        if self.keyword == "if" || expr_rw.is_some() {
+            return expr_rw;
+        }
+
+        // The expression won't fit on the current line, jump to next.
+        let nested_shape = shape
+            .block_indent(context.config.tab_spaces())
+            .with_max_width(context.config);
+        let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config);
+        expr.rewrite(context, nested_shape)
+            .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw))
+    }
+
     fn rewrite_cond(
         &self,
         context: &RewriteContext,
@@ -922,11 +970,7 @@ impl<'a> ControlFlow<'a> {
     ) -> Option<(String, usize)> {
         // Do not take the rhs overhead from the upper expressions into account
         // when rewriting pattern.
-        let new_width = context
-            .config
-            .max_width()
-            .checked_sub(shape.used_width())
-            .unwrap_or(0);
+        let new_width = context.budget(shape.used_width());
         let fresh_shape = Shape {
             width: new_width,
             ..shape
@@ -944,16 +988,7 @@ impl<'a> ControlFlow<'a> {
         let offset = self.keyword.len() + label_string.len() + 1;
 
         let pat_expr_string = match self.cond {
-            Some(cond) => rewrite_pat_expr(
-                context,
-                self.pat,
-                cond,
-                self.matcher,
-                self.connector,
-                self.keyword,
-                constr_shape,
-                offset,
-            )?,
+            Some(cond) => self.rewrite_pat_expr(context, cond, constr_shape, offset)?,
             None => String::new(),
         };
 
@@ -1007,15 +1042,17 @@ impl<'a> ControlFlow<'a> {
             context
                 .snippet_provider
                 .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()),
-            self.pat.map_or(cond_span.lo(), |p| {
+            if self.pats.is_empty() {
+                cond_span.lo()
+            } else {
                 if self.matcher.is_empty() {
-                    p.span.lo()
+                    self.pats[0].span.lo()
                 } else {
                     context
                         .snippet_provider
                         .span_before(self.span, self.matcher.trim())
                 }
-            }),
+            },
         );
 
         let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape);
@@ -1102,7 +1139,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
                 ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => {
                     ControlFlow::new_if(
                         cond,
-                        Some(pat),
+                        ptr_vec_to_ref_vec(pat),
                         if_block,
                         next_else_block.as_ref().map(|e| &**e),
                         false,
@@ -1113,7 +1150,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
                 ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => {
                     ControlFlow::new_if(
                         cond,
-                        None,
+                        vec![],
                         if_block,
                         next_else_block.as_ref().map(|e| &**e),
                         false,
@@ -1231,23 +1268,43 @@ pub fn is_unsafe_block(block: &ast::Block) -> bool {
     }
 }
 
-// A simple wrapper type against ast::Arm. Used inside write_list().
+/// A simple wrapper type against ast::Arm. Used inside write_list().
 struct ArmWrapper<'a> {
     pub arm: &'a ast::Arm,
-    // True if the arm is the last one in match expression. Used to decide on whether we should add
-    // trailing comma to the match arm when `config.trailing_comma() == Never`.
+    /// True if the arm is the last one in match expression. Used to decide on whether we should add
+    /// trailing comma to the match arm when `config.trailing_comma() == Never`.
     pub is_last: bool,
+    /// Holds a byte position of `|` at the beginning of the arm pattern, if available.
+    pub beginning_vert: Option<BytePos>,
 }
 
 impl<'a> ArmWrapper<'a> {
-    pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> {
-        ArmWrapper { arm, is_last }
+    pub fn new(
+        arm: &'a ast::Arm,
+        is_last: bool,
+        beginning_vert: Option<BytePos>,
+    ) -> ArmWrapper<'a> {
+        ArmWrapper {
+            arm,
+            is_last,
+            beginning_vert,
+        }
+    }
+}
+
+impl<'a> Spanned for ArmWrapper<'a> {
+    fn span(&self) -> Span {
+        if let Some(lo) = self.beginning_vert {
+            mk_sp(lo, self.arm.span().hi())
+        } else {
+            self.arm.span()
+        }
     }
 }
 
 impl<'a> Rewrite for ArmWrapper<'a> {
     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
-        rewrite_match_arm(context, self.arm, shape, self.is_last)
+        rewrite_match_arm(context, self.arm, shape, self.is_last, self.beginning_vert)
     }
 }
 
@@ -1344,6 +1401,23 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str {
     }
 }
 
+/// Collect a byte position of the beginning `|` for each arm, if available.
+fn collect_beginning_verts(
+    context: &RewriteContext,
+    arms: &[ast::Arm],
+    span: Span,
+) -> Vec<Option<BytePos>> {
+    let mut beginning_verts = Vec::with_capacity(arms.len());
+    let mut lo = context.snippet_provider.span_after(span, "{");
+    for arm in arms {
+        let hi = arm.pats[0].span.lo();
+        let missing_span = mk_sp(lo, hi);
+        beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|"));
+        lo = arm.span().hi();
+    }
+    beginning_verts
+}
+
 fn rewrite_match_arms(
     context: &RewriteContext,
     arms: &[ast::Arm],
@@ -1359,15 +1433,17 @@ fn rewrite_match_arms(
     let is_last_iter = repeat(false)
         .take(arm_len.checked_sub(1).unwrap_or(0))
         .chain(repeat(true));
+    let beginning_verts = collect_beginning_verts(context, arms, span);
     let items = itemize_list(
         context.snippet_provider,
         arms.iter()
             .zip(is_last_iter)
-            .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)),
+            .zip(beginning_verts.into_iter())
+            .map(|((arm, is_last), beginning_vert)| ArmWrapper::new(arm, is_last, beginning_vert)),
         "}",
         "|",
-        |arm| arm.arm.span().lo(),
-        |arm| arm.arm.span().hi(),
+        |arm| arm.span().lo(),
+        |arm| arm.span().hi(),
         |arm| arm.rewrite(context, arm_shape),
         open_brace_pos,
         span.hi(),
@@ -1394,6 +1470,7 @@ fn rewrite_match_arm(
     arm: &ast::Arm,
     shape: Shape,
     is_last: bool,
+    beginning_vert: Option<BytePos>,
 ) -> Option<String> {
     let (missing_span, attrs_str) = if !arm.attrs.is_empty() {
         if contains_skip(&arm.attrs) {
@@ -1415,9 +1492,9 @@ fn rewrite_match_arm(
     };
     let pats_str = rewrite_match_pattern(
         context,
-        &arm.pats,
+        &ptr_vec_to_ref_vec(&arm.pats),
         &arm.guard,
-        arm.beginning_vert.is_some(),
+        beginning_vert.is_some(),
         shape,
     ).and_then(|pats_str| {
         combine_strs_with_missing_comments(
@@ -1467,13 +1544,15 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
         ast::PatKind::TupleStruct(ref path, ref subpats, _) => {
             path.segments.len() <= 1 && subpats.len() <= 1
         }
-        ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p),
+        ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => {
+            is_short_pattern_inner(&*p)
+        }
     }
 }
 
 fn rewrite_match_pattern(
     context: &RewriteContext,
-    pats: &[ptr::P<ast::Pat>],
+    pats: &[&ast::Pat],
     guard: &Option<ptr::P<ast::Expr>>,
     has_beginning_vert: bool,
     shape: Shape,
@@ -1484,36 +1563,7 @@ fn rewrite_match_pattern(
     let pat_shape = shape
         .sub_width(5)?
         .offset_left(if has_beginning_vert { 2 } else { 0 })?;
-
-    let pat_strs = pats.iter()
-        .map(|p| p.rewrite(context, pat_shape))
-        .collect::<Option<Vec<_>>>()?;
-
-    let use_mixed_layout = pats.iter()
-        .zip(pat_strs.iter())
-        .all(|(pat, pat_str)| is_short_pattern(pat, pat_str));
-    let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect();
-    let tactic = if use_mixed_layout {
-        DefinitiveListTactic::Mixed
-    } else {
-        definitive_tactic(
-            &items,
-            ListTactic::HorizontalVertical,
-            Separator::VerticalBar,
-            pat_shape.width,
-        )
-    };
-    let fmt = ListFormatting {
-        tactic,
-        separator: " |",
-        trailing_separator: SeparatorTactic::Never,
-        separator_place: context.config.binop_separator(),
-        shape: pat_shape,
-        ends_with_newline: false,
-        preserve_newline: false,
-        config: context.config,
-    };
-    let pats_str = write_list(&items, &fmt)?;
+    let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?;
     let beginning_vert = if has_beginning_vert { "| " } else { "" };
 
     // Guard
@@ -1709,48 +1759,40 @@ fn rewrite_guard(
     }
 }
 
-fn rewrite_pat_expr(
+fn rewrite_multiple_patterns(
     context: &RewriteContext,
-    pat: Option<&ast::Pat>,
-    expr: &ast::Expr,
-    matcher: &str,
-    // Connecting piece between pattern and expression,
-    // *without* trailing space.
-    connector: &str,
-    keyword: &str,
+    pats: &[&ast::Pat],
     shape: Shape,
-    offset: usize,
 ) -> Option<String> {
-    debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr);
-    let cond_shape = shape.offset_left(offset)?;
-    if let Some(pat) = pat {
-        let matcher = if matcher.is_empty() {
-            matcher.to_owned()
-        } else {
-            format!("{} ", matcher)
-        };
-        let pat_shape = cond_shape
-            .offset_left(matcher.len())?
-            .sub_width(connector.len())?;
-        let pat_string = pat.rewrite(context, pat_shape)?;
-        let result = format!("{}{}{}", matcher, pat_string, connector);
-        return rewrite_assign_rhs(context, result, expr, cond_shape);
-    }
+    let pat_strs = pats.iter()
+        .map(|p| p.rewrite(context, shape))
+        .collect::<Option<Vec<_>>>()?;
 
-    let expr_rw = expr.rewrite(context, cond_shape);
-    // The expression may (partially) fit on the current line.
-    // We do not allow splitting between `if` and condition.
-    if keyword == "if" || expr_rw.is_some() {
-        return expr_rw;
-    }
-
-    // The expression won't fit on the current line, jump to next.
-    let nested_shape = shape
-        .block_indent(context.config.tab_spaces())
-        .with_max_width(context.config);
-    let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config);
-    expr.rewrite(context, nested_shape)
-        .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw))
+    let use_mixed_layout = pats.iter()
+        .zip(pat_strs.iter())
+        .all(|(pat, pat_str)| is_short_pattern(pat, pat_str));
+    let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect();
+    let tactic = if use_mixed_layout {
+        DefinitiveListTactic::Mixed
+    } else {
+        definitive_tactic(
+            &items,
+            ListTactic::HorizontalVertical,
+            Separator::VerticalBar,
+            shape.width,
+        )
+    };
+    let fmt = ListFormatting {
+        tactic,
+        separator: " |",
+        trailing_separator: SeparatorTactic::Never,
+        separator_place: context.config.binop_separator(),
+        shape: shape,
+        ends_with_newline: false,
+        preserve_newline: false,
+        config: context.config,
+    };
+    write_list(&items, &fmt)
 }
 
 fn can_extend_match_arm_body(body: &ast::Expr) -> bool {
diff --git a/src/items.rs b/src/items.rs
index 3503546c010..ce1bc1ae318 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -16,8 +16,7 @@ use std::cmp::min;
 use config::lists::*;
 use regex::Regex;
 use syntax::{abi, ast, ptr, symbol};
-use syntax::ast::{CrateSugar, ImplItem};
-use syntax::codemap::{BytePos, Span};
+use syntax::codemap::{self, BytePos, Span};
 use syntax::visit;
 
 use codemap::{LineRangeUtils, SpanUtils};
@@ -39,6 +38,11 @@ use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_co
 use vertical::rewrite_with_alignment;
 use visitor::FmtVisitor;
 
+const DEFAULT_VISIBILITY: ast::Visibility = codemap::Spanned {
+    node: ast::VisibilityKind::Inherited,
+    span: codemap::DUMMY_SP,
+};
+
 fn type_annotation_separator(config: &Config) -> &str {
     colon_spaces(config.space_before_colon(), config.space_after_colon())
 }
@@ -191,7 +195,7 @@ impl<'a> FnSig<'a> {
             abi: method_sig.abi,
             decl: &*method_sig.decl,
             generics,
-            visibility: ast::Visibility::Inherited,
+            visibility: DEFAULT_VISIBILITY,
         }
     }
 
@@ -680,7 +684,7 @@ pub fn format_impl(
 
 fn is_impl_single_line(
     context: &RewriteContext,
-    items: &[ImplItem],
+    items: &[ast::ImplItem],
     result: &str,
     where_clause_str: &str,
     item: &ast::Item,
@@ -869,7 +873,7 @@ impl<'a> StructParts<'a> {
         StructParts {
             prefix: "",
             ident: variant.node.name,
-            vis: &ast::Visibility::Inherited,
+            vis: &DEFAULT_VISIBILITY,
             def: &variant.node.data,
             generics: None,
             span: variant.span,
@@ -1208,21 +1212,9 @@ pub fn format_struct_struct(
     }
 }
 
-/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not
-/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need
-/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args.
-fn get_bytepos_after_visibility(
-    context: &RewriteContext,
-    vis: &ast::Visibility,
-    default_span: Span,
-    terminator: &str,
-) -> BytePos {
-    match *vis {
-        ast::Visibility::Crate(s, CrateSugar::PubCrate) => context
-            .snippet_provider
-            .span_after(mk_sp(s.hi(), default_span.hi()), terminator),
-        ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(),
-        ast::Visibility::Restricted { ref path, .. } => path.span.hi(),
+fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> BytePos {
+    match vis.node {
+        ast::VisibilityKind::Crate(..) | ast::VisibilityKind::Restricted { .. } => vis.span.hi(),
         _ => default_span.lo(),
     }
 }
@@ -1240,7 +1232,7 @@ fn format_tuple_struct(
     result.push_str(&header_str);
 
     let body_lo = if fields.is_empty() {
-        let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")");
+        let lo = get_bytepos_after_visibility(struct_parts.vis, span);
         context
             .snippet_provider
             .span_after(mk_sp(lo, span.hi()), "(")
@@ -1522,7 +1514,7 @@ impl<'a> StaticParts<'a> {
         };
         StaticParts {
             prefix: "const",
-            vis: &ast::Visibility::Inherited,
+            vis: &DEFAULT_VISIBILITY,
             ident: ti.ident,
             ty,
             mutability: ast::Mutability::Immutable,
@@ -1874,7 +1866,7 @@ fn rewrite_fn_base(
     }
 
     // Skip `pub(crate)`.
-    let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")");
+    let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
     // A conservative estimation, to goal is to be over all parens in generics
     let args_start = fn_sig
         .generics
diff --git a/src/patterns.rs b/src/patterns.rs
index 4bcf2890c35..e94f13b9daf 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -129,6 +129,8 @@ impl Rewrite for Pat {
                 rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape)
             }
             PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat),
+            PatKind::Paren(ref pat) => pat.rewrite(context, shape.offset_left(1)?.sub_width(1)?)
+                .map(|inner_pat| format!("({})", inner_pat)),
         }
     }
 }
diff --git a/src/spanned.rs b/src/spanned.rs
index 20dd8438798..d1f4865dead 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -89,10 +89,10 @@ impl Spanned for ast::Ty {
 
 impl Spanned for ast::Arm {
     fn span(&self) -> Span {
-        let lo = if let Some(sp) = self.beginning_vert {
-            sp.lo()
-        } else {
+        let lo = if self.attrs.is_empty() {
             self.pats[0].span.lo()
+        } else {
+            self.attrs[0].span.lo()
         };
         span_with_attrs_lo_hi!(self, lo, self.body.span.hi())
     }
diff --git a/src/utils.rs b/src/utils.rs
index 5ec5ee18009..f6d2ff23c34 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -12,7 +12,7 @@ use std::borrow::Cow;
 
 use syntax::{abi, ptr};
 use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem,
-                  NestedMetaItemKind, Path, Visibility};
+                  NestedMetaItemKind, Path, Visibility, VisibilityKind};
 use syntax::codemap::{BytePos, Span, NO_EXPANSION};
 
 use config::Color;
@@ -35,12 +35,12 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize {
 
 // Uses Cow to avoid allocating in the common cases.
 pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
-    match *vis {
-        Visibility::Public => Cow::from("pub "),
-        Visibility::Inherited => Cow::from(""),
-        Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "),
-        Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "),
-        Visibility::Restricted { ref path, .. } => {
+    match vis.node {
+        VisibilityKind::Public => Cow::from("pub "),
+        VisibilityKind::Inherited => Cow::from(""),
+        VisibilityKind::Crate(CrateSugar::PubCrate) => Cow::from("pub(crate) "),
+        VisibilityKind::Crate(CrateSugar::JustCrate) => Cow::from("crate "),
+        VisibilityKind::Restricted { ref path, .. } => {
             let Path { ref segments, .. } = **path;
             let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string());
             if path.is_global() {
diff --git a/tests/source/if_while_or_patterns.rs b/tests/source/if_while_or_patterns.rs
new file mode 100644
index 00000000000..f01df7e9158
--- /dev/null
+++ b/tests/source/if_while_or_patterns.rs
@@ -0,0 +1,27 @@
+#![feature(if_while_or_patterns)]
+
+fn main() {
+    if let 0 | 1 = 0 {
+        println!("hello, world");
+    };
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbbbbbb | cccccccccccccccc | d_100 = 0 {
+        println!("hello, world");
+    }
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbb | ccccccccccccccccccccc | d_101 = 0 {
+        println!("hello, world");
+    }
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbb | ccccccccccccccccccccc | d_103 = 0 {
+        println!("hello, world");
+    }
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbb | ccccccccccccccccccccc | d_105 = 0 {
+        println!("hello, world");
+    }
+
+    while let xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx = foo_bar(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccccccccccccccccc) {
+        println!("hello, world");
+    }
+}
diff --git a/tests/source/visibility.rs b/tests/source/visibility.rs
new file mode 100644
index 00000000000..1c5919ccff9
--- /dev/null
+++ b/tests/source/visibility.rs
@@ -0,0 +1,8 @@
+// #2398
+pub mod outer_mod {
+    pub mod inner_mod {
+       pub ( in outer_mod ) fn outer_mod_visible_fn() {}
+         pub ( super ) fn super_mod_visible_fn() {}
+      pub ( self ) fn inner_mod_visible_fn() {}
+    }
+}
diff --git a/tests/target/if_while_or_patterns.rs b/tests/target/if_while_or_patterns.rs
new file mode 100644
index 00000000000..61a357afcba
--- /dev/null
+++ b/tests/target/if_while_or_patterns.rs
@@ -0,0 +1,38 @@
+#![feature(if_while_or_patterns)]
+
+fn main() {
+    if let 0 | 1 = 0 {
+        println!("hello, world");
+    };
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbbbbbb | cccccccccccccccc | d_100 = 0 {
+        println!("hello, world");
+    }
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbb | ccccccccccccccccccccc | d_101 = 0
+    {
+        println!("hello, world");
+    }
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbb | ccccccccccccccccccccc | d_103 =
+        0
+    {
+        println!("hello, world");
+    }
+
+    if let aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+    | bbbbbbbbbbbbbbbbbbbbbbb
+    | ccccccccccccccccccccc
+    | d_105 = 0
+    {
+        println!("hello, world");
+    }
+
+    while let xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx
+    | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx | xxx = foo_bar(
+        bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
+        cccccccccccccccccccccccccccccccccccccccc,
+    ) {
+        println!("hello, world");
+    }
+}
diff --git a/tests/target/visibility.rs b/tests/target/visibility.rs
new file mode 100644
index 00000000000..ca078422c13
--- /dev/null
+++ b/tests/target/visibility.rs
@@ -0,0 +1,8 @@
+// #2398
+pub mod outer_mod {
+    pub mod inner_mod {
+        pub(in outer_mod) fn outer_mod_visible_fn() {}
+        pub(super) fn super_mod_visible_fn() {}
+        pub(self) fn inner_mod_visible_fn() {}
+    }
+}