From f04ea6c7e1cdac012b31efcd97973f426571a97a Mon Sep 17 00:00:00 2001
From: Eric Huss <eric@huss.org>
Date: Mon, 30 Sep 2019 10:59:32 -0700
Subject: [PATCH 01/18] Document JSON message output.

---
 src/doc/rustc/src/SUMMARY.md                |   1 +
 src/doc/rustc/src/command-line-arguments.md |   9 +-
 src/doc/rustc/src/json.md                   | 231 ++++++++++++++++++++
 3 files changed, 240 insertions(+), 1 deletion(-)
 create mode 100644 src/doc/rustc/src/json.md

diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 3cda8d927973c..d5564fd798f39 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -10,6 +10,7 @@
         - [Warn-by-default lints](lints/listing/warn-by-default.md)
         - [Deny-by-default lints](lints/listing/deny-by-default.md)
 - [Codegen options](codegen-options/index.md)
+- [JSON Output](json.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 5eea9c8687900..b2cc65c11fd2c 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -92,6 +92,7 @@ information about editions may be found in the [edition guide].
 [edition guide]: ../edition-guide/introduction.html
 
 ## `--emit`: specifies the types of output files to generate
+ <a id="option-emit"></a>
 
 This flag controls the types of output files generated by the compiler. It
 accepts a comma-separated list of values, and may be specified multiple times.
@@ -241,12 +242,13 @@ The "sysroot" is where `rustc` looks for the crates that come with the Rust
 distribution; this flag allows that to be overridden.
 
 ## `--error-format`: control how errors are produced
+ <a id="option-error-format"></a>
 
 This flag lets you control the format of messages. Messages are printed to
 stderr. The valid options are:
 
 - `human` — Human-readable output. This is the default.
-- `json` — Structured JSON output.
+- `json` — Structured JSON output. See [the JSON chapter] for more detail.
 - `short` — Short, one-line messages.
 
 ## `--color`: configure coloring of output
@@ -273,6 +275,7 @@ pathname syntax. For example `--remap-path-prefix foo=bar` will match
 `foo/lib.rs` but not `./foo/lib.rs`.
 
 ## `--json`: configure json messages printed by the compiler
+ <a id="option-json"></a>
 
 When the `--error-format=json` option is passed to rustc then all of the
 compiler's diagnostic output will be emitted in the form of JSON blobs. The
@@ -305,9 +308,13 @@ to customize the output:
 Note that it is invalid to combine the `--json` argument with the `--color`
 argument, and it is required to combine `--json` with `--error-format=json`.
 
+See [the JSON chapter] for more detail.
+
 ## `@path`: load command-line flags from a path
 
 If you specify `@path` on the command-line, then it will open `path` and read
 command line options from it. These options are one per line; a blank line indicates
 an empty option. The file can use Unix or Windows style line endings, and must be
 encoded as UTF-8.
+
+[the JSON chapter]: json.md
diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md
new file mode 100644
index 0000000000000..b737849516310
--- /dev/null
+++ b/src/doc/rustc/src/json.md
@@ -0,0 +1,231 @@
+# JSON Output
+
+This chapter documents the JSON structures emitted by `rustc`. JSON may be
+enabled with the [`--error-format=json` flag][option-error-format]. Additional
+options may be specified with the [`--json` flag][option-json] which can
+change which messages are generated, and the format of the messages.
+
+JSON messages are emitted one per line to stderr.
+
+If parsing the output with Rust, the
+[`cargo_metadata`](https://crates.io/crates/cargo_metadata) crate provides
+some support for parsing the messages.
+
+When parsing, care should be taken to be forwards-compatible with future changes
+to the format. Optional values may be `null`. New fields may be added. Enumerated
+fields like "level" or "suggestion_applicability" may add new values.
+
+## Diagnostics
+
+Diagnostic messages provide errors or possible concerns generated during
+compilation. `rustc` provides detailed information about where the diagnostic
+originates, along with hints and suggestions.
+
+Diagnostics are arranged in a parent/child relationship where the parent
+diagnostic value is the core of the diagnostic, and the attached children
+provide additional context, help, and information.
+
+Diagnostics have the following format:
+
+```javascript
+{
+    /* The primary message. */
+    "message": "unused variable: `x`",
+    /* The diagnostic code.
+       Some messages may set this value to null.
+    */
+    "code": {
+        /* A unique string identifying which diagnostic triggered. */
+        "code": "unused_variables",
+        /* An optional string explaining more detail about the diagnostic code. */
+        "explanation": null
+    },
+    /* The severity of the diagnostic.
+       Values may be:
+       - "error": A fatal error that prevents compilation.
+       - "warning": A possible error or concern.
+       - "note": Additional information or context about the diagnostic.
+       - "help": A suggestion on how to resolve the diagnostic.
+       - "failure-note": A note attached to the message for further information.
+       - "error: internal compiler error": Indicates a bug within the compiler.
+    */
+    "level": "warning",
+    /* An array of source code locations to point out specific details about
+       where the diagnostic originates from. This may be empty, for example
+       for some global messages, or child messages attached to a parent.
+
+       Character offsets are offsets of Unicode Scalar Values.
+    */
+    "spans": [
+        {
+            /* The file where the span is located.
+               For spans located within a macro expansion, this will be the
+               name of the expanded macro in the format "<MACRONAME macros>".
+            */
+            "file_name": "lib.rs",
+            /* The byte offset where the span starts (0-based, inclusive). */
+            "byte_start": 21,
+            /* The byte offset where the span ends (0-based, exclusive). */
+            "byte_end": 22,
+            /* The first line number of the span (1-based, inclusive). */
+            "line_start": 2,
+            /* The last line number of the span (1-based, inclusive). */
+            "line_end": 2,
+            /* The first character offset of the line_start (1-based, inclusive). */
+            "column_start": 9,
+            /* The last character offset of the line_end (1-based, exclusive). */
+            "column_end": 10,
+            /* Whether or not this is the "primary" span.
+
+               This indicates that this span is the focal point of the
+               diagnostic.
+
+               There are rare cases where multiple spans may be marked as
+               primary. For example, "immutable borrow occurs here" and
+               "mutable borrow ends here" can be two separate primary spans.
+
+               The top (parent) message should always have at least one
+               primary span, unless it has zero spans. Child messages may have
+               zero or more primary spans.
+            */
+            "is_primary": true,
+            /* An array of objects showing the original source code for this
+               span. This shows the entire lines of text where the span is
+               located. A span across multiple lines will have a separate
+               value for each line.
+            */
+            "text": [
+                {
+                    /* The entire line of the original source code. */
+                    "text": "    let x = 123;",
+                    /* The first character offset of the line of
+                       where the span covers this line (1-based, inclusive). */
+                    "highlight_start": 9,
+                    /* The last character offset of the line of
+                       where the span covers this line (1-based, exclusive). */
+                    "highlight_end": 10
+                }
+            ],
+            /* An optional message to display at this span location.
+               This is typically null for primary spans.
+            */
+            "label": null,
+            /* An optional string of a suggested replacement for this span to
+               solve the issue. Tools may try to replace the contents of the
+               span with this text.
+            */
+            "suggested_replacement": null,
+            /* An optional string that indicates the confidence of the
+               "suggested_replacement". Tools may use this value to determine
+               whether or not suggestions should be automatically applied.
+
+               Possible values may be:
+               - "MachineApplicable": The suggestion is definitely what the
+                 user intended. This suggestion should be automatically
+                 applied.
+               - "MaybeIncorrect": The suggestion may be what the user
+                 intended, but it is uncertain. The suggestion should result
+                 in valid Rust code if it is applied.
+               - "HasPlaceholders": The suggestion contains placeholders like
+                 `(...)`. The suggestion cannot be applied automatically
+                 because it will not result in valid Rust code. The user will
+                 need to fill in the placeholders.
+               - "Unspecified": The applicability of the suggestion is unknown.
+            */
+            "suggestion_applicability": null,
+            /* An optional object indicating the expansion of a macro within
+               this span.
+
+               If a message occurs within a macro invocation, this object will
+               provide details of where within the macro expansion the message
+               is located.
+            */
+            "expansion": {
+                /* The span of the macro invocation.
+                   Uses the same span definition as the "spans" array.
+                */
+                "span": {/*...*/}
+                /* Name of the macro, such as "foo!" or "#[derive(Eq)]". */
+                "macro_decl_name": "some_macro!",
+                /* Optional span where the relevant part of the macro is
+                  defined. */
+                "def_site_span": {/*...*/},
+            }
+        }
+    ],
+    /* Array of attached diagnostic messages.
+       This is an array of objects using the same format as the parent
+       message. Children are not nested (children do not themselves
+       contain "children" definitions).
+    */
+    "children": [
+        {
+            "message": "`#[warn(unused_variables)]` on by default",
+            "code": null,
+            "level": "note",
+            "spans": [],
+            "children": [],
+            "rendered": null
+        },
+        {
+            "message": "consider prefixing with an underscore",
+            "code": null,
+            "level": "help",
+            "spans": [
+                {
+                    "file_name": "lib.rs",
+                    "byte_start": 21,
+                    "byte_end": 22,
+                    "line_start": 2,
+                    "line_end": 2,
+                    "column_start": 9,
+                    "column_end": 10,
+                    "is_primary": true,
+                    "text": [
+                        {
+                            "text": "    let x = 123;",
+                            "highlight_start": 9,
+                            "highlight_end": 10
+                        }
+                    ],
+                    "label": null,
+                    "suggested_replacement": "_x",
+                    "suggestion_applicability": "MachineApplicable",
+                    "expansion": null
+                }
+            ],
+            "children": [],
+            "rendered": null
+        }
+    ],
+    /* Optional string of the rendered version of the diagnostic as displayed
+       by rustc. Note that this may be influenced by the `--json` flag.
+    */
+    "rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n  |\n2 |     let x = 123;\n  |         ^ help: consider prefixing with an underscore: `_x`\n  |\n  = note: `#[warn(unused_variables)]` on by default\n\n"
+}
+```
+
+## Artifact notifications
+
+Artifact notifications are emitted when the [`--json=artifacts`
+flag][option-json] is used. They indicate that a file artifact has been saved
+to disk. More information about emit kinds may be found in the [`--emit`
+flag][option-emit] documentation.
+
+```javascript
+{
+    /* The filename that was generated. */
+    "artifact": "libfoo.rlib",
+    /* The kind of artifact that was generated. Possible values:
+       - "link": The generated crate as specified by the crate-type.
+       - "dep-info": The `.d` file with dependency information in a Makefile-like syntax.
+       - "metadata": The Rust `.rmeta` file containing metadata about the crate.
+       - "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature.
+    */
+    "emit": "link"
+}
+```
+
+[option-emit]: command-line-arguments.md#option-emit
+[option-error-format]: command-line-arguments.md#option-error-format
+[option-json]: command-line-arguments.md#option-json

From 3b0fd82bfad814ff777e7aa236b74804e4c469c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Tue, 8 Oct 2019 00:00:00 +0000
Subject: [PATCH 02/18] Disable Go and OCaml bindings when building LLVM

Instead of instaling OCaml bindings in a location where installation
will not fail, don't build them in the first place.
---
 src/bootstrap/native.rs | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 7bf9ea2688f4c..fb308bc35ebc5 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -157,6 +157,7 @@ impl Step for Llvm {
            .define("WITH_POLLY", "OFF")
            .define("LLVM_ENABLE_TERMINFO", "OFF")
            .define("LLVM_ENABLE_LIBEDIT", "OFF")
+           .define("LLVM_ENABLE_BINDINGS", "OFF")
            .define("LLVM_ENABLE_Z3_SOLVER", "OFF")
            .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
            .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
@@ -169,15 +170,6 @@ impl Step for Llvm {
             }
         }
 
-        // By default, LLVM will automatically find OCaml and, if it finds it,
-        // install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults
-        // to /usr/bin/ocaml.
-        // This causes problem for non-root builds of Rust. Side-step the issue
-        // by setting LLVM_OCAML_INSTALL_PATH to a relative path, so it installs
-        // in the prefix.
-        cfg.define("LLVM_OCAML_INSTALL_PATH",
-            env::var_os("LLVM_OCAML_INSTALL_PATH").unwrap_or_else(|| "usr/lib/ocaml".into()));
-
         let want_lldb = builder.config.lldb_enabled && !self.emscripten;
 
         // This setting makes the LLVM tools link to the dynamic LLVM library,

From bcff26606a74ebd2b5bcbfe03476963a1e21c765 Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Sat, 14 Sep 2019 09:22:07 -0400
Subject: [PATCH 03/18] [const-prop] Handle MIR Rvalue::Repeat

---
 src/librustc_mir/transform/const_prop.rs |  2 +-
 src/test/mir-opt/const_prop/repeat.rs    | 37 ++++++++++++++++++++++++
 src/test/ui/consts/const-prop-ice.rs     |  1 +
 src/test/ui/consts/const-prop-ice.stderr |  8 ++++-
 4 files changed, 46 insertions(+), 2 deletions(-)
 create mode 100644 src/test/mir-opt/const_prop/repeat.rs

diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 49ac1de8fef64..77943e9acd527 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -436,13 +436,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
         // if this isn't a supported operation, then return None
         match rvalue {
-            Rvalue::Repeat(..) |
             Rvalue::Aggregate(..) |
             Rvalue::NullaryOp(NullOp::Box, _) |
             Rvalue::Discriminant(..) => return None,
 
             Rvalue::Use(_) |
             Rvalue::Len(_) |
+            Rvalue::Repeat(..) |
             Rvalue::Cast(..) |
             Rvalue::NullaryOp(..) |
             Rvalue::CheckedBinaryOp(..) |
diff --git a/src/test/mir-opt/const_prop/repeat.rs b/src/test/mir-opt/const_prop/repeat.rs
new file mode 100644
index 0000000000000..fb091ad2a3d53
--- /dev/null
+++ b/src/test/mir-opt/const_prop/repeat.rs
@@ -0,0 +1,37 @@
+// compile-flags: -O
+
+fn main() {
+    let x: u32 = [42; 8][2] + 0;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _3 = [const 42u32; 8];
+//      ...
+//      _4 = const 2usize;
+//      _5 = const 8usize;
+//      _6 = Lt(_4, _5);
+//      assert(move _6, "index out of bounds: the len is move _5 but the index is _4") -> bb1;
+//  }
+//  bb1: {
+//      _2 = _3[_4];
+//      _1 = Add(move _2, const 0u32);
+//      ...
+//      return;
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _6 = const true;
+//      assert(const true, "index out of bounds: the len is move _5 but the index is _4") -> bb1;
+//  }
+//  bb1: {
+//      _2 = const 42u32;
+//      _1 = Add(move _2, const 0u32);
+//      ...
+//      return;
+//  }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs
index 13309f978b672..48c4b7da942e4 100644
--- a/src/test/ui/consts/const-prop-ice.rs
+++ b/src/test/ui/consts/const-prop-ice.rs
@@ -1,3 +1,4 @@
 fn main() {
     [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
+    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
index 4b3880198bf2d..8ecc6f4bc6b12 100644
--- a/src/test/ui/consts/const-prop-ice.stderr
+++ b/src/test/ui/consts/const-prop-ice.stderr
@@ -6,5 +6,11 @@ LL |     [0; 3][3u64 as usize];
    |
    = note: `#[deny(const_err)]` on by default
 
-error: aborting due to previous error
+error: this expression will panic at runtime
+  --> $DIR/const-prop-ice.rs:2:5
+   |
+LL |     [0; 3][3u64 as usize];
+   |     ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3
+
+error: aborting due to 2 previous errors
 

From 714d00d8d848327dfca7aab8bc3bd3b32ea18ebe Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Sat, 14 Sep 2019 14:11:31 -0400
Subject: [PATCH 04/18] [const-prop] Handle MIR Rvalue::Aggregates

---
 src/librustc_mir/transform/const_prop.rs      |  8 +++++-
 src/test/compile-fail/consts/const-err3.rs    |  1 +
 src/test/mir-opt/const_prop/aggregate.rs      | 25 +++++++++++++++++++
 src/test/run-fail/overflowing-rsh-5.rs        |  1 +
 src/test/run-fail/overflowing-rsh-6.rs        |  1 +
 src/test/ui/consts/const-err2.rs              |  1 +
 src/test/ui/consts/const-err2.stderr          |  8 +++++-
 src/test/ui/consts/const-err3.rs              |  1 +
 src/test/ui/consts/const-err3.stderr          |  8 +++++-
 src/test/ui/issues/issue-54348.rs             |  2 ++
 src/test/ui/issues/issue-54348.stderr         | 16 ++++++++++--
 src/test/ui/lint/lint-exceeding-bitshifts2.rs |  2 +-
 .../ui/lint/lint-exceeding-bitshifts2.stderr  |  8 +++++-
 13 files changed, 75 insertions(+), 7 deletions(-)
 create mode 100644 src/test/mir-opt/const_prop/aggregate.rs

diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 77943e9acd527..2119ee1b598ef 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -436,13 +436,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
         // if this isn't a supported operation, then return None
         match rvalue {
-            Rvalue::Aggregate(..) |
             Rvalue::NullaryOp(NullOp::Box, _) |
             Rvalue::Discriminant(..) => return None,
 
             Rvalue::Use(_) |
             Rvalue::Len(_) |
             Rvalue::Repeat(..) |
+            Rvalue::Aggregate(..) |
             Rvalue::Cast(..) |
             Rvalue::NullaryOp(..) |
             Rvalue::CheckedBinaryOp(..) |
@@ -535,6 +535,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     return None;
                 }
             }
+        } else if let Rvalue::Aggregate(_, operands) = rvalue {
+            // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
+            // `SimplifyLocals` doesn't know it can remove.
+            if operands.len() == 0 {
+                return None;
+            }
         }
 
         self.use_ecx(source_info, |this| {
diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs
index fc10824f0c03c..add4eef13c784 100644
--- a/src/test/compile-fail/consts/const-err3.rs
+++ b/src/test/compile-fail/consts/const-err3.rs
@@ -14,6 +14,7 @@ fn main() {
     //~^ ERROR const_err
     let _e = [5u8][1];
     //~^ ERROR const_err
+    //~| ERROR this expression will panic at runtime
     black_box(b);
     black_box(c);
     black_box(d);
diff --git a/src/test/mir-opt/const_prop/aggregate.rs b/src/test/mir-opt/const_prop/aggregate.rs
new file mode 100644
index 0000000000000..0937d37be6b6e
--- /dev/null
+++ b/src/test/mir-opt/const_prop/aggregate.rs
@@ -0,0 +1,25 @@
+// compile-flags: -O
+
+fn main() {
+    let x = (0, 1, 2).1 + 0;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _3 = (const 0i32, const 1i32, const 2i32);
+//      _2 = (_3.1: i32);
+//      _1 = Add(move _2, const 0i32);
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _3 = (const 0i32, const 1i32, const 2i32);
+//      _2 = const 1i32;
+//      _1 = Add(move _2, const 0i32);
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/run-fail/overflowing-rsh-5.rs b/src/test/run-fail/overflowing-rsh-5.rs
index 793f495240d57..58dfc5710ae4e 100644
--- a/src/test/run-fail/overflowing-rsh-5.rs
+++ b/src/test/run-fail/overflowing-rsh-5.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _n = 1i64 >> [64][0];
diff --git a/src/test/run-fail/overflowing-rsh-6.rs b/src/test/run-fail/overflowing-rsh-6.rs
index d6b2f8dc9f9af..c2fec5e4860af 100644
--- a/src/test/run-fail/overflowing-rsh-6.rs
+++ b/src/test/run-fail/overflowing-rsh-6.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 #![feature(const_indexing)]
 
 fn main() {
diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs
index ecbcc2a4b496f..e5ee90fc9f11f 100644
--- a/src/test/ui/consts/const-err2.rs
+++ b/src/test/ui/consts/const-err2.rs
@@ -23,6 +23,7 @@ fn main() {
     //~^ ERROR const_err
     let _e = [5u8][1];
     //~^ ERROR index out of bounds
+    //~| ERROR this expression will panic at runtime
     black_box(a);
     black_box(b);
     black_box(c);
diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr
index 1d84d44dc27b3..0a09a7213dabc 100644
--- a/src/test/ui/consts/const-err2.stderr
+++ b/src/test/ui/consts/const-err2.stderr
@@ -34,5 +34,11 @@ error: index out of bounds: the len is 1 but the index is 1
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: this expression will panic at runtime
+  --> $DIR/const-err2.rs:24:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs
index a9cf04cda7a5a..89373f99f75c2 100644
--- a/src/test/ui/consts/const-err3.rs
+++ b/src/test/ui/consts/const-err3.rs
@@ -23,6 +23,7 @@ fn main() {
     //~^ ERROR const_err
     let _e = [5u8][1];
     //~^ ERROR const_err
+    //~| ERROR this expression will panic at runtime
     black_box(a);
     black_box(b);
     black_box(c);
diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr
index 0602707be7040..42de247c8f7e0 100644
--- a/src/test/ui/consts/const-err3.stderr
+++ b/src/test/ui/consts/const-err3.stderr
@@ -34,5 +34,11 @@ error: index out of bounds: the len is 1 but the index is 1
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: this expression will panic at runtime
+  --> $DIR/const-err3.rs:24:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs
index 68d838054776e..e7221e2cbb1e1 100644
--- a/src/test/ui/issues/issue-54348.rs
+++ b/src/test/ui/issues/issue-54348.rs
@@ -1,5 +1,7 @@
 fn main() {
     [1][0u64 as usize];
     [1][1.5 as usize]; //~ ERROR index out of bounds
+    //~| ERROR this expression will panic at runtime
     [1][1u64 as usize]; //~ ERROR index out of bounds
+    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
index fa77bd6fd7797..79320ef4f31c7 100644
--- a/src/test/ui/issues/issue-54348.stderr
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -6,11 +6,23 @@ LL |     [1][1.5 as usize];
    |
    = note: `#[deny(const_err)]` on by default
 
+error: this expression will panic at runtime
+  --> $DIR/issue-54348.rs:3:5
+   |
+LL |     [1][1.5 as usize];
+   |     ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/issue-54348.rs:4:5
+  --> $DIR/issue-54348.rs:5:5
    |
 LL |     [1][1u64 as usize];
    |     ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: this expression will panic at runtime
+  --> $DIR/issue-54348.rs:5:5
+   |
+LL |     [1][1u64 as usize];
+   |     ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
index 69b627355b801..2c213daddd752 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
@@ -8,7 +8,7 @@ fn main() {
       let n = 1u8 << (4+3);
       let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow
       let n = 1i64 >> [63][0];
-      let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation
+      let n = 1i64 >> [64][0]; //~ ERROR: attempt to shift right with overflow
 
       #[cfg(target_pointer_width = "32")]
       const BITS: usize = 32;
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
index cb96982a78930..d9c76d233d03e 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
@@ -10,6 +10,12 @@ note: lint level defined here
 LL | #![deny(exceeding_bitshifts, const_err)]
    |         ^^^^^^^^^^^^^^^^^^^
 
+error: attempt to shift right with overflow
+  --> $DIR/lint-exceeding-bitshifts2.rs:11:15
+   |
+LL |       let n = 1i64 >> [64][0];
+   |               ^^^^^^^^^^^^^^^
+
 error: attempt to shift left with overflow
   --> $DIR/lint-exceeding-bitshifts2.rs:17:15
    |
@@ -22,5 +28,5 @@ error: attempt to shift left with overflow
 LL |       let n = 1_usize << BITS;
    |               ^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 

From 81fa59187b19c379c4f9e330984e5e8853981b12 Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Sun, 15 Sep 2019 00:05:19 -0400
Subject: [PATCH 05/18] [const-prop] Handle MIR Rvalue::Discriminant

---
 src/librustc_mir/transform/const_prop.rs    |  4 +-
 src/test/mir-opt/const_prop/discriminant.rs | 53 +++++++++++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 src/test/mir-opt/const_prop/discriminant.rs

diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 2119ee1b598ef..fb2cdce2d7aef 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -436,13 +436,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
         // if this isn't a supported operation, then return None
         match rvalue {
-            Rvalue::NullaryOp(NullOp::Box, _) |
-            Rvalue::Discriminant(..) => return None,
+            Rvalue::NullaryOp(NullOp::Box, _) => return None,
 
             Rvalue::Use(_) |
             Rvalue::Len(_) |
             Rvalue::Repeat(..) |
             Rvalue::Aggregate(..) |
+            Rvalue::Discriminant(..) |
             Rvalue::Cast(..) |
             Rvalue::NullaryOp(..) |
             Rvalue::CheckedBinaryOp(..) |
diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs
new file mode 100644
index 0000000000000..07bbd9202b940
--- /dev/null
+++ b/src/test/mir-opt/const_prop/discriminant.rs
@@ -0,0 +1,53 @@
+// compile-flags: -O
+
+fn main() {
+    let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _3 = std::option::Option::<bool>::Some(const true,);
+//      _4 = discriminant(_3);
+//      switchInt(move _4) -> [1isize: bb3, otherwise: bb2];
+//  }
+//  bb1: {
+//      _2 = const 42i32;
+//      goto -> bb4;
+//  }
+//  bb2: {
+//      _2 = const 10i32;
+//      goto -> bb4;
+//  }
+//  bb3: {
+//      switchInt(((_3 as Some).0: bool)) -> [false: bb2, otherwise: bb1];
+//  }
+//  bb4: {
+//      _1 = Add(move _2, const 0i32);
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _3 = const Scalar(0x01) : std::option::Option<bool>;
+//      _4 = const 1isize;
+//      switchInt(const 1isize) -> [1isize: bb3, otherwise: bb2];
+//  }
+//  bb1: {
+//      _2 = const 42i32;
+//      goto -> bb4;
+//  }
+//  bb2: {
+//      _2 = const 10i32;
+//      goto -> bb4;
+//  }
+//  bb3: {
+//      switchInt(const true) -> [false: bb2, otherwise: bb1];
+//  }
+//  bb4: {
+//      _1 = Add(move _2, const 0i32);
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir

From 79c5858bfd07f90201b91cd10cd3aa9f062377cc Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Sun, 15 Sep 2019 12:03:52 -0400
Subject: [PATCH 06/18] [const-prop] Handle MIR Rvalue::Box

---
 src/librustc_mir/transform/const_prop.rs | 19 +--------
 src/test/mir-opt/const_prop/boxes.rs     | 53 ++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 18 deletions(-)
 create mode 100644 src/test/mir-opt/const_prop/boxes.rs

diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index fb2cdce2d7aef..984938d00b2f0 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -8,7 +8,7 @@ use rustc::hir::def::DefKind;
 use rustc::hir::def_id::DefId;
 use rustc::mir::{
     AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
-    Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
+    Local, UnOp, StatementKind, Statement, LocalKind,
     TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp,
     SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
 };
@@ -434,23 +434,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     ) -> Option<Const<'tcx>> {
         let span = source_info.span;
 
-        // if this isn't a supported operation, then return None
-        match rvalue {
-            Rvalue::NullaryOp(NullOp::Box, _) => return None,
-
-            Rvalue::Use(_) |
-            Rvalue::Len(_) |
-            Rvalue::Repeat(..) |
-            Rvalue::Aggregate(..) |
-            Rvalue::Discriminant(..) |
-            Rvalue::Cast(..) |
-            Rvalue::NullaryOp(..) |
-            Rvalue::CheckedBinaryOp(..) |
-            Rvalue::Ref(..) |
-            Rvalue::UnaryOp(..) |
-            Rvalue::BinaryOp(..) => { }
-        }
-
         // perform any special checking for specific Rvalue types
         if let Rvalue::UnaryOp(op, arg) = rvalue {
             trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
diff --git a/src/test/mir-opt/const_prop/boxes.rs b/src/test/mir-opt/const_prop/boxes.rs
new file mode 100644
index 0000000000000..52a7f7ee79503
--- /dev/null
+++ b/src/test/mir-opt/const_prop/boxes.rs
@@ -0,0 +1,53 @@
+// compile-flags: -O
+
+#![feature(box_syntax)]
+
+// Note: this test verifies that we, in fact, do not const prop `box`
+
+fn main() {
+    let x = *(box 42) + 0;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _4 = Box(i32);
+//      (*_4) = const 42i32;
+//      _3 = move _4;
+//      ...
+//      _2 = (*_3);
+//      _1 = Add(move _2, const 0i32);
+//      ...
+//      drop(_3) -> [return: bb2, unwind: bb1];
+//  }
+//  bb1 (cleanup): {
+//      resume;
+//  }
+//  bb2: {
+//      ...
+//      _0 = ();
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _4 = Box(i32);
+//      (*_4) = const 42i32;
+//      _3 = move _4;
+//      ...
+//      _2 = (*_3);
+//      _1 = Add(move _2, const 0i32);
+//      ...
+//      drop(_3) -> [return: bb2, unwind: bb1];
+//  }
+//  bb1 (cleanup): {
+//      resume;
+//  }
+//  bb2: {
+//      ...
+//      _0 = ();
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir

From f2afa98c95960432d2aa3a9d827f493651fdf02b Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Sun, 15 Sep 2019 12:08:09 -0400
Subject: [PATCH 07/18] Cleanup const_prop() some

---
 src/librustc_mir/transform/const_prop.rs | 147 ++++++++++++-----------
 1 file changed, 75 insertions(+), 72 deletions(-)

diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 984938d00b2f0..abb880fd62419 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -118,7 +118,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
 struct ConstPropMachine;
 
 impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
-    type MemoryKinds= !;
+    type MemoryKinds = !;
     type PointerTag = ();
     type ExtraFnVal = !;
 
@@ -435,79 +435,80 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         let span = source_info.span;
 
         // perform any special checking for specific Rvalue types
-        if let Rvalue::UnaryOp(op, arg) = rvalue {
-            trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
-            let overflow_check = self.tcx.sess.overflow_checks();
-
-            self.use_ecx(source_info, |this| {
-                // We check overflow in debug mode already
-                // so should only check in release mode.
-                if *op == UnOp::Neg && !overflow_check {
-                    let ty = arg.ty(&this.local_decls, this.tcx);
-
-                    if ty.is_integral() {
-                        let arg = this.ecx.eval_operand(arg, None)?;
-                        let prim = this.ecx.read_immediate(arg)?;
-                        // Need to do overflow check here: For actual CTFE, MIR
-                        // generation emits code that does this before calling the op.
-                        if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
-                            throw_panic!(OverflowNeg)
+        match rvalue {
+            Rvalue::UnaryOp(UnOp::Neg, arg) => {
+                trace!("checking UnaryOp(op = Neg, arg = {:?})", arg);
+                let overflow_check = self.tcx.sess.overflow_checks();
+
+                self.use_ecx(source_info, |this| {
+                    // We check overflow in debug mode already
+                    // so should only check in release mode.
+                    if !overflow_check {
+                        let ty = arg.ty(&this.local_decls, this.tcx);
+
+                        if ty.is_integral() {
+                            let arg = this.ecx.eval_operand(arg, None)?;
+                            let prim = this.ecx.read_immediate(arg)?;
+                            // Need to do overflow check here: For actual CTFE, MIR
+                            // generation emits code that does this before calling the op.
+                            if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
+                                throw_panic!(OverflowNeg)
+                            }
                         }
                     }
-                }
 
-                Ok(())
-            })?;
-        } else if let Rvalue::BinaryOp(op, left, right) = rvalue {
-            trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
-
-            let r = self.use_ecx(source_info, |this| {
-                this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
-            })?;
-            if *op == BinOp::Shr || *op == BinOp::Shl {
-                let left_bits = place_layout.size.bits();
-                let right_size = r.layout.size;
-                let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
-                if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
-                    let source_scope_local_data = match self.source_scope_local_data {
-                        ClearCrossCrate::Set(ref data) => data,
-                        ClearCrossCrate::Clear => return None,
-                    };
-                    let dir = if *op == BinOp::Shr {
-                        "right"
-                    } else {
-                        "left"
-                    };
-                    let hir_id = source_scope_local_data[source_info.scope].lint_root;
-                    self.tcx.lint_hir(
-                        ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
-                        hir_id,
-                        span,
-                        &format!("attempt to shift {} with overflow", dir));
-                    return None;
-                }
+                    Ok(())
+                })?;
             }
-            self.use_ecx(source_info, |this| {
-                let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
-                let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
-
-                // We check overflow in debug mode already
-                // so should only check in release mode.
-                if !this.tcx.sess.overflow_checks() && overflow {
-                    let err = err_panic!(Overflow(*op)).into();
-                    return Err(err);
+
+            Rvalue::BinaryOp(op, left, right) => {
+                trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
+
+                let r = self.use_ecx(source_info, |this| {
+                    this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
+                })?;
+                if *op == BinOp::Shr || *op == BinOp::Shl {
+                    let left_bits = place_layout.size.bits();
+                    let right_size = r.layout.size;
+                    let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
+                    if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
+                        let source_scope_local_data = match self.source_scope_local_data {
+                            ClearCrossCrate::Set(ref data) => data,
+                            ClearCrossCrate::Clear => return None,
+                        };
+                        let dir = if *op == BinOp::Shr {
+                            "right"
+                        } else {
+                            "left"
+                        };
+                        let hir_id = source_scope_local_data[source_info.scope].lint_root;
+                        self.tcx.lint_hir(
+                            ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
+                            hir_id,
+                            span,
+                            &format!("attempt to shift {} with overflow", dir));
+                        return None;
+                    }
                 }
+                self.use_ecx(source_info, |this| {
+                    let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
+                    let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
+
+                    // We check overflow in debug mode already
+                    // so should only check in release mode.
+                    if !this.tcx.sess.overflow_checks() && overflow {
+                        let err = err_panic!(Overflow(*op)).into();
+                        return Err(err);
+                    }
 
-                Ok(())
-            })?;
-        } else if let Rvalue::Ref(_, _, place) = rvalue {
-            trace!("checking Ref({:?})", place);
-            // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
-            // from a function argument that hasn't been assigned to in this function.
-            if let Place {
-                base: PlaceBase::Local(local),
-                projection: box []
-            } = place {
+                    Ok(())
+                })?;
+            }
+
+            Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => {
+                trace!("checking Ref({:?})", place);
+                // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
+                // from a function argument that hasn't been assigned to in this function.
                 let alive =
                     if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
                         true
@@ -518,12 +519,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     return None;
                 }
             }
-        } else if let Rvalue::Aggregate(_, operands) = rvalue {
-            // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
-            // `SimplifyLocals` doesn't know it can remove.
-            if operands.len() == 0 {
+
+            Rvalue::Aggregate(_, operands) if operands.len() == 0 => {
+                // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
+                // `SimplifyLocals` doesn't know it can remove.
                 return None;
             }
+
+            _ => { }
         }
 
         self.use_ecx(source_info, |this| {

From 77f0aaf0d0a92feb068999d6b14f60dcf325b0c1 Mon Sep 17 00:00:00 2001
From: Georg Semmler <georg_semmler_05@web.de>
Date: Sat, 12 Oct 2019 20:53:11 +0200
Subject: [PATCH 08/18] Add more coherence tests

---
 .../ui/coherence/impl-foreign-for-foreign.rs  | 17 +++++++++++
 .../coherence/impl-foreign-for-foreign.stderr | 12 ++++++++
 .../impl-foreign-for-foreign[foreign].rs      | 25 ++++++++++++++++
 .../impl-foreign-for-foreign[foreign].stderr  | 30 +++++++++++++++++++
 .../impl-foreign-for-foreign[local].rs        | 16 ++++++++++
 .../impl-foreign-for-fundamental[foreign].rs  | 21 +++++++++++++
 ...pl-foreign-for-fundamental[foreign].stderr | 21 +++++++++++++
 .../impl-foreign-for-fundamental[local].rs    | 17 +++++++++++
 .../ui/coherence/impl-foreign-for-local.rs    | 15 ++++++++++
 ...reign[fundemental[foreign]]-for-foreign.rs | 26 ++++++++++++++++
 ...n[fundemental[foreign]]-for-foreign.stderr | 30 +++++++++++++++++++
 ...foreign[fundemental[local]]-for-foreign.rs | 18 +++++++++++
 .../impl[t]-foreign-for-(local, t).rs         | 17 +++++++++++
 .../impl[t]-foreign-for-(local, t).stderr     | 12 ++++++++
 .../impl[t]-foreign-for-foreign[t].rs         | 23 ++++++++++++++
 .../impl[t]-foreign-for-foreign[t].stderr     | 21 +++++++++++++
 .../impl[t]-foreign-for-fundamental[t].rs     | 17 +++++++++++
 .../impl[t]-foreign-for-fundamental[t].stderr | 11 +++++++
 ...eign[fundemental[local]]-for-foreign[t].rs | 17 +++++++++++
 .../impl[t]-foreign[local]-for-foreign[t].rs  | 17 +++++++++++
 ...eign[local]-for-fundamental[foreign[t]].rs | 19 ++++++++++++
 21 files changed, 402 insertions(+)
 create mode 100644 src/test/ui/coherence/impl-foreign-for-foreign.rs
 create mode 100644 src/test/ui/coherence/impl-foreign-for-foreign.stderr
 create mode 100644 src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs
 create mode 100644 src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr
 create mode 100644 src/test/ui/coherence/impl-foreign-for-foreign[local].rs
 create mode 100644 src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs
 create mode 100644 src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
 create mode 100644 src/test/ui/coherence/impl-foreign-for-fundamental[local].rs
 create mode 100644 src/test/ui/coherence/impl-foreign-for-local.rs
 create mode 100644 src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs
 create mode 100644 src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
 create mode 100644 src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs
 create mode 100644 src/test/ui/coherence/impl[t]-foreign-for-(local, t).rs
 create mode 100644 src/test/ui/coherence/impl[t]-foreign-for-(local, t).stderr
 create mode 100644 src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs
 create mode 100644 src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
 create mode 100644 src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs
 create mode 100644 src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
 create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs
 create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs
 create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs

diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.rs b/src/test/ui/coherence/impl-foreign-for-foreign.rs
new file mode 100644
index 0000000000000..de0b66a35eb01
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign.rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote for i32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.stderr b/src/test/ui/coherence/impl-foreign-for-foreign.stderr
new file mode 100644
index 0000000000000..b03a75a77c346
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign.rs:12:1
+   |
+LL | impl Remote for i32 {
+   | ^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs
new file mode 100644
index 0000000000000..5146263d99114
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs
@@ -0,0 +1,25 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote1<Rc<i32>> for i32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl Remote1<Rc<Local>> for f64 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl<T> Remote1<Rc<T>> for f32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr
new file mode 100644
index 0000000000000..bfaec790b20a6
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr
@@ -0,0 +1,30 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign[foreign].rs:12:1
+   |
+LL | impl Remote1<Rc<i32>> for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign[foreign].rs:16:1
+   |
+LL | impl Remote1<Rc<Local>> for f64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-foreign[foreign].rs:20:1
+   |
+LL | impl<T> Remote1<Rc<T>> for f32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[local].rs b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs
new file mode 100644
index 0000000000000..050769dcf4ce8
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local<T>(Rc<T>);
+
+impl Remote1<Local<i32>> for i32 {}
+impl<T> Remote1<Local<T>> for f32 {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs
new file mode 100644
index 0000000000000..03b11edf98b41
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs
@@ -0,0 +1,21 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote for Box<i32> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl<T> Remote for Box<Rc<T>> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
new file mode 100644
index 0000000000000..2ce4921cf938f
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-fundamental[foreign].rs:12:1
+   |
+LL | impl Remote for Box<i32> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign-for-fundamental[foreign].rs:16:1
+   |
+LL | impl<T> Remote for Box<Rc<T>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs
new file mode 100644
index 0000000000000..ae03ce6a440dc
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<T>(Rc<T>);
+
+impl Remote for Box<Local> {}
+impl<T> Remote for Box<Local1<T>> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign-for-local.rs b/src/test/ui/coherence/impl-foreign-for-local.rs
new file mode 100644
index 0000000000000..c9dddeba18dc5
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign-for-local.rs
@@ -0,0 +1,15 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote for Local {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs
new file mode 100644
index 0000000000000..06efb6c2ad75e
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs
@@ -0,0 +1,26 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<T>(Rc<T>);
+
+impl Remote1<Box<String>> for i32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl Remote1<Box<Rc<i32>>> for f64 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+impl<T> Remote1<Box<Rc<T>>> for f32 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
new file mode 100644
index 0000000000000..bf2361a1718af
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
@@ -0,0 +1,30 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:13:1
+   |
+LL | impl Remote1<Box<String>> for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:17:1
+   |
+LL | impl Remote1<Box<Rc<i32>>> for f64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:21:1
+   |
+LL | impl<T> Remote1<Box<Rc<T>>> for f32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs
new file mode 100644
index 0000000000000..d47e0a36a5659
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs
@@ -0,0 +1,18 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<T>(Rc<T>);
+
+impl Remote1<Box<Local>> for i32 {}
+impl Remote1<Box<Local1<i32>>> for f64 {}
+impl<T> Remote1<Box<Local1<T>>> for f32 {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-(local, t).rs b/src/test/ui/coherence/impl[t]-foreign-for-(local, t).rs
new file mode 100644
index 0000000000000..850b6f85d0ed7
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-(local, t).rs	
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote for (Local, T) {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-(local, t).stderr b/src/test/ui/coherence/impl[t]-foreign-for-(local, t).stderr
new file mode 100644
index 0000000000000..ff0b9d6d0da9a
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-(local, t).stderr	
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl[t]-foreign-for-(local, t).rs:12:1
+   |
+LL | impl<T> Remote for (Local, T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs
new file mode 100644
index 0000000000000..db7a2ae8076a3
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs
@@ -0,0 +1,23 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Local;
+
+impl Remote for Rc<Local> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+impl<T> Remote for Arc<T> {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
new file mode 100644
index 0000000000000..d7ffcaf76f9a2
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl[t]-foreign-for-foreign[t].rs:13:1
+   |
+LL | impl Remote for Rc<Local> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl[t]-foreign-for-foreign[t].rs:18:1
+   |
+LL | impl<T> Remote for Arc<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs
new file mode 100644
index 0000000000000..4cc19e1a526ca
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote for Box<T> {
+    //~^ ERROR type parameter `T` must be used as the type parameter for
+    // | some local type (e.g., `MyStruct<T>`)
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
new file mode 100644
index 0000000000000..20ce11ef9759e
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign-for-fundamental[t].rs:12:1
+   |
+LL | impl<T> Remote for Box<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs
new file mode 100644
index 0000000000000..914680f191ac9
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<S>(Rc<S>);
+
+impl<T> Remote1<Box<Local>> for Rc<T> {}
+impl<S, T> Remote1<Box<Local1<S>>> for Rc<T> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs
new file mode 100644
index 0000000000000..1e84ff40c6227
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<S>(Rc<S>);
+
+impl<T> Remote1<Local> for Rc<T> {}
+impl<T, S> Remote1<Local1<S>> for Rc<T> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs
new file mode 100644
index 0000000000000..ea6aa101d209c
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs
@@ -0,0 +1,19 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local1<S>(Rc<S>);
+
+impl<T> Remote1<Local> for Box<Rc<T>> {}
+impl<T, S> Remote1<Local1<S>> for Box<Rc<T>> {}
+impl<T> Remote1<Box<Local>> for Box<Rc<T>> {}
+impl<T, S> Remote1<Box<Local1<S>>> for Box<Rc<T>> {}
+
+fn main() {}

From b6f6dc4f7ffb7e52e5621230728c32908e9b6259 Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Wed, 9 Oct 2019 06:08:46 -0400
Subject: [PATCH 09/18] Don't ICE when evaluating writes to uninhabited enum
 variants

---
 src/librustc/mir/interpret/error.rs           |  7 +++--
 src/librustc_mir/interpret/operand.rs         |  8 ++---
 src/librustc_mir/interpret/place.rs           | 16 ++++++----
 src/librustc_mir/interpret/validity.rs        |  2 +-
 .../write-to-uninhabited-enum-variant.rs      | 29 +++++++++++++++++++
 5 files changed, 49 insertions(+), 13 deletions(-)
 create mode 100644 src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs

diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 71967b513a049..0c0951c69c2ce 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -363,6 +363,8 @@ pub enum UndefinedBehaviorInfo {
     UbExperimental(String),
     /// Unreachable code was executed.
     Unreachable,
+    /// An enum discriminant was set to a value which was outside the range of valid values.
+    InvalidDiscriminant(ScalarMaybeUndef),
 }
 
 impl fmt::Debug for UndefinedBehaviorInfo {
@@ -373,6 +375,8 @@ impl fmt::Debug for UndefinedBehaviorInfo {
                 write!(f, "{}", msg),
             Unreachable =>
                 write!(f, "entered unreachable code"),
+            InvalidDiscriminant(val) =>
+                write!(f, "encountered invalid enum discriminant {}", val),
         }
     }
 }
@@ -404,7 +408,6 @@ pub enum UnsupportedOpInfo<'tcx> {
     InvalidMemoryAccess,
     InvalidFunctionPointer,
     InvalidBool,
-    InvalidDiscriminant(ScalarMaybeUndef),
     PointerOutOfBounds {
         ptr: Pointer,
         msg: CheckInAllocMsg,
@@ -489,8 +492,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
                 write!(f, "incorrect alloc info: expected size {} and align {}, \
                            got size {} and align {}",
                     size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
-            InvalidDiscriminant(val) =>
-                write!(f, "encountered invalid enum discriminant {}", val),
             InvalidMemoryAccess =>
                 write!(f, "tried to access memory through an invalid pointer"),
             DanglingPointerDeref =>
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 4bdd71f9602ac..4d9be55945e02 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -647,7 +647,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let bits_discr = raw_discr
                     .not_undef()
                     .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size))
-                    .map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?;
+                    .map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?;
                 let real_discr = if discr_val.layout.ty.is_signed() {
                     // going from layout tag type to typeck discriminant type
                     // requires first sign extending with the discriminant layout
@@ -677,7 +677,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     _ => bug!("tagged layout for non-adt non-generator"),
 
                 }.ok_or_else(
-                    || err_unsup!(InvalidDiscriminant(raw_discr.erase_tag()))
+                    || err_ub!(InvalidDiscriminant(raw_discr.erase_tag()))
                 )?;
                 (real_discr, index.0)
             },
@@ -689,7 +689,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let variants_start = niche_variants.start().as_u32();
                 let variants_end = niche_variants.end().as_u32();
                 let raw_discr = raw_discr.not_undef().map_err(|_| {
-                    err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef))
+                    err_ub!(InvalidDiscriminant(ScalarMaybeUndef::Undef))
                 })?;
                 match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
                     Err(ptr) => {
@@ -697,7 +697,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         let ptr_valid = niche_start == 0 && variants_start == variants_end &&
                             !self.memory.ptr_may_be_null(ptr);
                         if !ptr_valid {
-                            throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag().into()))
+                            throw_ub!(InvalidDiscriminant(raw_discr.erase_tag().into()))
                         }
                         (dataful_variant.as_u32() as u128, dataful_variant)
                     },
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 3ba989529f18f..6ee6f6095d971 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -1034,9 +1034,13 @@ where
         variant_index: VariantIdx,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
+        let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into();
+
         match dest.layout.variants {
             layout::Variants::Single { index } => {
-                assert_eq!(index, variant_index);
+                if index != variant_index {
+                    throw_ub!(InvalidDiscriminant(variant_scalar));
+                }
             }
             layout::Variants::Multiple {
                 discr_kind: layout::DiscriminantKind::Tag,
@@ -1044,7 +1048,9 @@ where
                 discr_index,
                 ..
             } => {
-                assert!(dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index));
+                if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) {
+                    throw_ub!(InvalidDiscriminant(variant_scalar));
+                }
                 let discr_val =
                     dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
 
@@ -1067,9 +1073,9 @@ where
                 discr_index,
                 ..
             } => {
-                assert!(
-                    variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(),
-                );
+                if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() {
+                    throw_ub!(InvalidDiscriminant(variant_scalar));
+                }
                 if variant_index != dataful_variant {
                     let variants_start = niche_variants.start().as_u32();
                     let variant_index_relative = variant_index.as_u32()
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 853fcb1beabf5..3444fb60f333b 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -344,7 +344,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
         match self.walk_value(op) {
             Ok(()) => Ok(()),
             Err(err) => match err.kind {
-                err_unsup!(InvalidDiscriminant(val)) =>
+                err_ub!(InvalidDiscriminant(val)) =>
                     throw_validation_failure!(
                         val, self.path, "a valid enum discriminant"
                     ),
diff --git a/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs b/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs
new file mode 100644
index 0000000000000..0a5ca97e2d971
--- /dev/null
+++ b/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs
@@ -0,0 +1,29 @@
+// run-pass
+// ignore-wasm
+
+#![allow(dead_code)]
+
+enum Empty { }
+enum Test1 {
+    A(u8),
+    B(Empty),
+}
+enum Test2 {
+    A(u8),
+    B(Empty),
+    C,
+}
+
+fn bar() -> Option<Empty> {
+    std::process::exit(0)
+}
+
+fn main() {
+    if let Some(x) = bar() {
+        Test1::B(x);
+    }
+
+    if let Some(x) = bar() {
+        Test2::B(x);
+    }
+}

From 10236f1cee5d08e1f74d270fa37cd20fca6b4077 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 15 Oct 2019 13:52:49 +0200
Subject: [PATCH 10/18] Add long error explanation for E0577

---
 src/librustc_resolve/error_codes.rs | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 1e65cbada069d..7c7cd9ec24a0c 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1661,6 +1661,33 @@ match eco {
 ```
 "##,
 
+E0577: r##"
+Something other than a module was found in visibility scope.
+
+Erroneous code example:
+
+```compile_fail,E0577,edition2018
+pub struct Sea;
+
+pub (in crate::Sea) struct Shark; // error!
+
+fn main() {}
+```
+
+`Sea` is not a module, therefore, it is invalid. To fix this error, we need to
+replace `Sea` with a module.
+
+Please note that the visibility scope can only be applied on ancestors!
+
+```edition2018
+pub mod Sea {
+    pub (in crate::Sea) struct Shark; // ok!
+}
+
+fn main() {}
+```
+"##,
+
 E0603: r##"
 A private item was used outside its scope.
 
@@ -1791,6 +1818,5 @@ struct Foo<X = Box<Self>> {
     E0573,
     E0575,
     E0576,
-    E0577,
     E0578,
 }

From 3d88f2cbd0068d386edd32553f24908e3237b3ef Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 15 Oct 2019 13:52:57 +0200
Subject: [PATCH 11/18] Update ui tests

---
 src/test/ui/resolve/resolve-bad-visibility.stderr | 3 ++-
 src/test/ui/span/visibility-ty-params.stderr      | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/test/ui/resolve/resolve-bad-visibility.stderr b/src/test/ui/resolve/resolve-bad-visibility.stderr
index d2fb7c7a9e69d..be59edffe7f59 100644
--- a/src/test/ui/resolve/resolve-bad-visibility.stderr
+++ b/src/test/ui/resolve/resolve-bad-visibility.stderr
@@ -30,4 +30,5 @@ LL | pub(in too_soon) struct H;
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0433`.
+Some errors have detailed explanations: E0433, E0577.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr
index c2f0711b0c866..d3fa1d7732e72 100644
--- a/src/test/ui/span/visibility-ty-params.stderr
+++ b/src/test/ui/span/visibility-ty-params.stderr
@@ -18,3 +18,4 @@ LL |     m!{ m<> }
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0577`.

From 91239077211ad25ab1e86241493ac4c3e8a35909 Mon Sep 17 00:00:00 2001
From: Wesley Wiser <wwiser@gmail.com>
Date: Sun, 13 Oct 2019 13:48:26 -0400
Subject: [PATCH 12/18] Improve comments and structure of
 `ConstProp::const_prop()`

Per code review feedback
---
 src/librustc_mir/transform/const_prop.rs | 82 +++++++++++++++---------
 1 file changed, 50 insertions(+), 32 deletions(-)

diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index abb880fd62419..f0c0e57344388 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -434,26 +434,32 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     ) -> Option<Const<'tcx>> {
         let span = source_info.span;
 
-        // perform any special checking for specific Rvalue types
+        let overflow_check = self.tcx.sess.overflow_checks();
+
+        // Perform any special handling for specific Rvalue types.
+        // Generally, checks here fall into one of two categories:
+        //   1. Additional checking to provide useful lints to the user
+        //        - In this case, we will do some validation and then fall through to the
+        //          end of the function which evals the assignment.
+        //   2. Working around bugs in other parts of the compiler
+        //        - In this case, we'll return `None` from this function to stop evaluation.
         match rvalue {
-            Rvalue::UnaryOp(UnOp::Neg, arg) => {
+            // Additional checking: if overflow checks are disabled (which is usually the case in
+            // release mode), then we need to do additional checking here to give lints to the user
+            // if an overflow would occur.
+            Rvalue::UnaryOp(UnOp::Neg, arg) if !overflow_check => {
                 trace!("checking UnaryOp(op = Neg, arg = {:?})", arg);
-                let overflow_check = self.tcx.sess.overflow_checks();
 
                 self.use_ecx(source_info, |this| {
-                    // We check overflow in debug mode already
-                    // so should only check in release mode.
-                    if !overflow_check {
-                        let ty = arg.ty(&this.local_decls, this.tcx);
-
-                        if ty.is_integral() {
-                            let arg = this.ecx.eval_operand(arg, None)?;
-                            let prim = this.ecx.read_immediate(arg)?;
-                            // Need to do overflow check here: For actual CTFE, MIR
-                            // generation emits code that does this before calling the op.
-                            if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
-                                throw_panic!(OverflowNeg)
-                            }
+                    let ty = arg.ty(&this.local_decls, this.tcx);
+
+                    if ty.is_integral() {
+                        let arg = this.ecx.eval_operand(arg, None)?;
+                        let prim = this.ecx.read_immediate(arg)?;
+                        // Need to do overflow check here: For actual CTFE, MIR
+                        // generation emits code that does this before calling the op.
+                        if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
+                            throw_panic!(OverflowNeg)
                         }
                     }
 
@@ -461,6 +467,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 })?;
             }
 
+            // Additional checking: check for overflows on integer binary operations and report
+            // them to the user as lints.
             Rvalue::BinaryOp(op, left, right) => {
                 trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
 
@@ -490,25 +498,34 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         return None;
                     }
                 }
-                self.use_ecx(source_info, |this| {
-                    let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
-                    let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
-
-                    // We check overflow in debug mode already
-                    // so should only check in release mode.
-                    if !this.tcx.sess.overflow_checks() && overflow {
-                        let err = err_panic!(Overflow(*op)).into();
-                        return Err(err);
-                    }
 
-                    Ok(())
-                })?;
+                // If overflow checking is enabled (like in debug mode by default),
+                // then we'll already catch overflow when we evaluate the `Assert` statement
+                // in MIR. However, if overflow checking is disabled, then there won't be any
+                // `Assert` statement and so we have to do additional checking here.
+                if !overflow_check {
+                    self.use_ecx(source_info, |this| {
+                        let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
+                        let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
+
+                        if overflow {
+                            let err = err_panic!(Overflow(*op)).into();
+                            return Err(err);
+                        }
+
+                        Ok(())
+                    })?;
+                }
             }
 
+            // Work around: avoid ICE in miri.
+            // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
+            // from a function argument that hasn't been assigned to in this function. The main
+            // issue is if an arg is a fat-pointer, miri `expects()` to be able to read the value
+            // of that pointer to get size info. However, since this is `ConstProp`, that argument
+            // doesn't actually have a backing value and so this causes an ICE.
             Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => {
                 trace!("checking Ref({:?})", place);
-                // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
-                // from a function argument that hasn't been assigned to in this function.
                 let alive =
                     if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
                         true
@@ -520,9 +537,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 }
             }
 
+            // Work around: avoid extra unnecessary locals.
+            // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
+            // `SimplifyLocals` doesn't know it can remove.
             Rvalue::Aggregate(_, operands) if operands.len() == 0 => {
-                // FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
-                // `SimplifyLocals` doesn't know it can remove.
                 return None;
             }
 

From 83e97c6ac1b722c1b55fdf9d6378f87d9e0cdbdd Mon Sep 17 00:00:00 2001
From: Trevor Spiteri <tspiteri@ieee.org>
Date: Thu, 17 Oct 2019 13:53:57 +0200
Subject: [PATCH 13/18] properly document panics in div_euclid and rem_euclid

---
 src/libcore/num/mod.rs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 998c8f8165204..8f4ade377e312 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1864,7 +1864,7 @@ if `self < 0`, this is equal to round towards +/- infinity.
 
 # Panics
 
-This function will panic if `rhs` is 0.
+This function will panic if `rhs` is 0 or the division results in overflow.
 
 # Examples
 
@@ -1903,7 +1903,7 @@ This is done as if by the Euclidean division algorithm -- given
 
 # Panics
 
-This function will panic if `rhs` is 0.
+This function will panic if `rhs` is 0 or the division results in overflow.
 
 # Examples
 
@@ -3694,6 +3694,10 @@ Since, for the positive integers, all common
 definitions of division are equal, this
 is exactly equal to `self / rhs`.
 
+# Panics
+
+This function will panic if `rhs` is 0.
+
 # Examples
 
 Basic usage:
@@ -3719,6 +3723,10 @@ Since, for the positive integers, all common
 definitions of division are equal, this
 is exactly equal to `self % rhs`.
 
+# Panics
+
+This function will panic if `rhs` is 0.
+
 # Examples
 
 Basic usage:

From e4171802e29d77c1ead4a6816c8a6a78843f6834 Mon Sep 17 00:00:00 2001
From: Dylan DPC <dylan.dpc@gmail.com>
Date: Thu, 17 Oct 2019 17:33:38 +0200
Subject: [PATCH 14/18] Update error_codes.rs

---
 src/librustc_resolve/error_codes.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 7c7cd9ec24a0c..23bea5196d711 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -26,7 +26,7 @@ struct Foo<U = (), T = U> {
 }
 ```
 
-Please also verify that this wasn't because of a name-clash and rename the type
+Please also verify \hat this wasn't because of a name-clash and rename the type
 parameter if so.
 "##,
 
@@ -1674,8 +1674,8 @@ pub (in crate::Sea) struct Shark; // error!
 fn main() {}
 ```
 
-`Sea` is not a module, therefore, it is invalid. To fix this error, we need to
-replace `Sea` with a module.
+`Sea` is not a module, therefore it is invalid to use it in a visibility path.
+To fix this error we need to ensure `Sea` is a module.
 
 Please note that the visibility scope can only be applied on ancestors!
 

From a4d94925c737b1fee1dc8e90225a71b47ed77042 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Thu, 17 Oct 2019 14:15:59 -0400
Subject: [PATCH 15/18] add option to ping llvm ice-breakers to triagebot

---
 triagebot.toml | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/triagebot.toml b/triagebot.toml
index d87c5b64c21c2..b39c95f683618 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -8,3 +8,14 @@ allow-unauthenticated = [
 ]
 
 [assign]
+
+[ping.icebreaker-llvm]
+message = """\
+Hey LLVM ICE-breakers! This bug has been identified as a good
+"LLVM ICE-breaking candidate". In case it's useful, here are some
+[instructions] for tackling these sorts of bugs. Maybe take a look?
+Thanks! <3
+
+[instructions]: https://rust-lang.github.io/rustc-guide/ice-breaker/llvm.html
+"""
+label = "ICEBreaker-LLVM"

From 4e6efe48110a5e09ee87b0aa8cea31d511bb5708 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 17 Oct 2019 21:22:46 +0200
Subject: [PATCH 16/18] reorder fmt docs for more clarity

---
 src/liballoc/fmt.rs | 103 ++++++++++++++++++++++++++------------------
 1 file changed, 61 insertions(+), 42 deletions(-)

diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index 1e39b7f822e99..4d3523da7fc09 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -86,18 +86,53 @@
 //! parameters (corresponding to `format_spec` in the syntax above). These
 //! parameters affect the string representation of what's being formatted.
 //!
+//! ## Width
+//!
+//! ```
+//! // All of these print "Hello x    !"
+//! println!("Hello {:5}!", "x");
+//! println!("Hello {:1$}!", "x", 5);
+//! println!("Hello {1:0$}!", 5, "x");
+//! println!("Hello {:width$}!", "x", width = 5);
+//! ```
+//!
+//! This is a parameter for the "minimum width" that the format should take up.
+//! If the value's string does not fill up this many characters, then the
+//! padding specified by fill/alignment will be used to take up the required
+//! space (see below).
+//!
+//! The value for the width can also be provided as a [`usize`] in the list of
+//! parameters by adding a postfix `$`, indicating that the second argument is
+//! a [`usize`] specifying the width.
+//!
+//! Referring to an argument with the dollar syntax does not affect the "next
+//! argument" counter, so it's usually a good idea to refer to arguments by
+//! position, or use named arguments.
+//!
 //! ## Fill/Alignment
 //!
-//! The fill character is provided normally in conjunction with the
-//! [`width`](#width)
-//! parameter. This indicates that if the value being formatted is smaller than
-//! `width` some extra characters will be printed around it. The extra
-//! characters are specified by `fill`, and the alignment can be one of the
-//! following options:
+//! ```
+//! assert_eq!(format!("Hello {:<5}!", "x"),  "Hello x    !");
+//! assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!");
+//! assert_eq!(format!("Hello {:^5}!", "x"),  "Hello   x  !");
+//! assert_eq!(format!("Hello {:>5}!", "x"),  "Hello     x!");
+//! ```
+//!
+//! The optional fill character and alignment is provided normally in conjunction with the
+//! [`width`](#width) parameter. It must be defined before `width`, right after the `:`.
+//! This indicates that if the value being formatted is smaller than
+//! `width` some extra characters will be printed around it.
+//! Filling comes in the following variants for different alignments:
 //!
-//! * `<` - the argument is left-aligned in `width` columns
-//! * `^` - the argument is center-aligned in `width` columns
-//! * `>` - the argument is right-aligned in `width` columns
+//! * `[fill]<` - the argument is left-aligned in `width` columns
+//! * `[fill]^` - the argument is center-aligned in `width` columns
+//! * `[fill]>` - the argument is right-aligned in `width` columns
+//!
+//! The default [fill/alignment](#fillalignment) for non-numerics is a space and
+//! left-aligned. The
+//! defaults for numeric formatters is also a space but with right-alignment. If
+//! the `0` flag (see below) is specified for numerics, then the implicit fill character is
+//! `0`.
 //!
 //! Note that alignment may not be implemented by some types. In particular, it
 //! is not generally implemented for the `Debug` trait.  A good way to ensure
@@ -106,7 +141,15 @@
 //!
 //! ## Sign/`#`/`0`
 //!
-//! These can all be interpreted as flags for a particular formatter.
+//! ```
+//! assert_eq!(format!("Hello {:+}!", 5), "Hello +5!");
+//! assert_eq!(format!("{:#x}!", 27), "0x1b!");
+//! assert_eq!(format!("Hello {:05}!", 5),  "Hello 00005!");
+//! assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!");
+//! assert_eq!(format!("{:#010x}!", 27), "0x0000001b!");
+//! ```
+//!
+//! These are all flags altering the behavior of the formatter.
 //!
 //! * `+` - This is intended for numeric types and indicates that the sign
 //!         should always be printed. Positive signs are never printed by
@@ -121,7 +164,7 @@
 //!     * `#X` - precedes the argument with a `0x`
 //!     * `#b` - precedes the argument with a `0b`
 //!     * `#o` - precedes the argument with a `0o`
-//! * `0` - This is used to indicate for integer formats that the padding should
+//! * `0` - This is used to indicate for integer formats that the padding to `width` should
 //!         both be done with a `0` character as well as be sign-aware. A format
 //!         like `{:08}` would yield `00000001` for the integer `1`, while the
 //!         same format would yield `-0000001` for the integer `-1`. Notice that
@@ -129,36 +172,7 @@
 //!         Note that padding zeroes are always placed after the sign (if any)
 //!         and before the digits. When used together with the `#` flag, a similar
 //!         rule applies: padding zeroes are inserted after the prefix but before
-//!         the digits.
-//!
-//! ## Width
-//!
-//! This is a parameter for the "minimum width" that the format should take up.
-//! If the value's string does not fill up this many characters, then the
-//! padding specified by fill/alignment will be used to take up the required
-//! space.
-//!
-//! The default [fill/alignment](#fillalignment) for non-numerics is a space and
-//! left-aligned. The
-//! defaults for numeric formatters is also a space but with right-alignment. If
-//! the `0` flag is specified for numerics, then the implicit fill character is
-//! `0`.
-//!
-//! The value for the width can also be provided as a [`usize`] in the list of
-//! parameters by using the dollar syntax indicating that the second argument is
-//! a [`usize`] specifying the width, for example:
-//!
-//! ```
-//! // All of these print "Hello x    !"
-//! println!("Hello {:5}!", "x");
-//! println!("Hello {:1$}!", "x", 5);
-//! println!("Hello {1:0$}!", 5, "x");
-//! println!("Hello {:width$}!", "x", width = 5);
-//! ```
-//!
-//! Referring to an argument with the dollar syntax does not affect the "next
-//! argument" counter, so it's usually a good idea to refer to arguments by
-//! position, or use named arguments.
+//!         the digits. The prefix is included in the total width.
 //!
 //! ## Precision
 //!
@@ -235,9 +249,14 @@
 //! them with the same character. For example, the `{` character is escaped with
 //! `{{` and the `}` character is escaped with `}}`.
 //!
+//! ```
+//! assert_eq!(format!("Hello {{}}"), "Hello {}");
+//! assert_eq!(format!("{{ Hello"), "{ Hello");
+//! ```
+//!
 //! # Syntax
 //!
-//! To summarize, you can find the full grammar of format strings.
+//! To summarize, here you can find the full grammar of format strings.
 //! The syntax for the formatting language used is drawn from other languages,
 //! so it should not be too alien. Arguments are formatted with Python-like
 //! syntax, meaning that arguments are surrounded by `{}` instead of the C-like

From 54879949f18ed44dc4db4b9c450d6c09551a2e0d Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Thu, 17 Oct 2019 16:53:47 -0400
Subject: [PATCH 17/18] Update triagebot.toml

Co-Authored-By: Mark Rousskov <mark.simulacrum@gmail.com>
---
 triagebot.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/triagebot.toml b/triagebot.toml
index b39c95f683618..f0e3a99037b02 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -9,7 +9,7 @@ allow-unauthenticated = [
 
 [assign]
 
-[ping.icebreaker-llvm]
+[ping.icebreakers-llvm]
 message = """\
 Hey LLVM ICE-breakers! This bug has been identified as a good
 "LLVM ICE-breaking candidate". In case it's useful, here are some

From c0b7e769a0f76a76fc5d239d886e5b8a69648b10 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 17 Oct 2019 23:00:46 +0200
Subject: [PATCH 18/18] example for padding any format

---
 src/liballoc/fmt.rs | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index 4d3523da7fc09..cbfc55233a1e0 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -136,8 +136,12 @@
 //!
 //! Note that alignment may not be implemented by some types. In particular, it
 //! is not generally implemented for the `Debug` trait.  A good way to ensure
-//! padding is applied is to format your input, then use this resulting string
-//! to pad your output.
+//! padding is applied is to format your input, then pad this resulting string
+//! to obtain your output:
+//!
+//! ```
+//! println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello   Some("hi")   !"
+//! ```
 //!
 //! ## Sign/`#`/`0`
 //!