From 809a1a86e04d03619642ab9074b9c95a24cbf82b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Mon, 24 Dec 2018 21:43:51 +0100
Subject: [PATCH 01/24] mark str::string::String.trim.* functions as
 #[must_use].

The functions return a reference to a new object and do not modify in-place
as the following code shows:
````
let s = String::from("   hello   ");
s.trim();
assert_eq!(s, "   hello   ");
````

The new reference should be bound to a variable as now indicated by #[must_use].
---
 src/libcore/str/mod.rs | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 689d456d412..a8b8b44413e 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3544,6 +3544,8 @@ impl str {
     ///
     /// assert_eq!("Hello\tworld", s.trim());
     /// ```
+    #[must_use = "this returns the trimmed string as a new allocation, \
+                  without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim(&self) -> &str {
         self.trim_matches(|c: char| c.is_whitespace())
@@ -3579,6 +3581,8 @@ impl str {
     /// let s = "  עברית  ";
     /// assert!(Some('ע') == s.trim_start().chars().next());
     /// ```
+    #[must_use = "this returns the trimmed string as a new allocation, \
+                  without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_start(&self) -> &str {
         self.trim_start_matches(|c: char| c.is_whitespace())
@@ -3614,6 +3618,8 @@ impl str {
     /// let s = "  עברית  ";
     /// assert!(Some('ת') == s.trim_end().chars().rev().next());
     /// ```
+    #[must_use = "this returns the trimmed string as a new allocation, \
+                  without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_end(&self) -> &str {
         self.trim_end_matches(|c: char| c.is_whitespace())
@@ -3716,6 +3722,8 @@ impl str {
     /// ```
     /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
     /// ```
+    #[must_use = "this returns the trimmed string as a new allocation, \
+                  without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
         where P::Searcher: DoubleEndedSearcher<'a>
@@ -3761,6 +3769,8 @@ impl str {
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12");
     /// ```
+    #[must_use = "this returns the trimmed string as a new allocation, \
+                  without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
         let mut i = self.len();
@@ -3804,6 +3814,8 @@ impl str {
     /// ```
     /// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo");
     /// ```
+    #[must_use = "this returns the trimmed string as a new allocation, \
+                  without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
         where P::Searcher: ReverseSearcher<'a>

From e7ce868f8e7ba2df728451bcbeafe387d393a1bc Mon Sep 17 00:00:00 2001
From: "Zack M. Davis" <main@zackmdavis.net>
Date: Tue, 25 Dec 2018 20:28:20 +0100
Subject: [PATCH 02/24] Update src/libcore/str/mod.rs, tweak must_use message

trimmed string is returned as a slice instead of a new allocation

Co-Authored-By: matthiaskrgr <matthias.krueger@famsik.de>
---
 src/libcore/str/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index a8b8b44413e..9e724f117ff 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3544,7 +3544,7 @@ impl str {
     ///
     /// assert_eq!("Hello\tworld", s.trim());
     /// ```
-    #[must_use = "this returns the trimmed string as a new allocation, \
+    #[must_use = "this returns the trimmed string as a slice, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim(&self) -> &str {

From 74e9057905c3c24303245a4a2c5671d80a9503b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Wed, 26 Dec 2018 22:03:04 +0100
Subject: [PATCH 03/24] modify remaining #[must_use[ messages

---
 src/libcore/str/mod.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 9e724f117ff..e58320ebf56 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3581,7 +3581,7 @@ impl str {
     /// let s = "  עברית  ";
     /// assert!(Some('ע') == s.trim_start().chars().next());
     /// ```
-    #[must_use = "this returns the trimmed string as a new allocation, \
+    #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_start(&self) -> &str {
@@ -3618,7 +3618,7 @@ impl str {
     /// let s = "  עברית  ";
     /// assert!(Some('ת') == s.trim_end().chars().rev().next());
     /// ```
-    #[must_use = "this returns the trimmed string as a new allocation, \
+    #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_end(&self) -> &str {
@@ -3722,7 +3722,7 @@ impl str {
     /// ```
     /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
     /// ```
-    #[must_use = "this returns the trimmed string as a new allocation, \
+    #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
@@ -3769,7 +3769,7 @@ impl str {
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12");
     /// ```
-    #[must_use = "this returns the trimmed string as a new allocation, \
+    #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
@@ -3814,7 +3814,7 @@ impl str {
     /// ```
     /// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo");
     /// ```
-    #[must_use = "this returns the trimmed string as a new allocation, \
+    #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
     #[stable(feature = "trim_direction", since = "1.30.0")]
     pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str

From 8db66ca53e9521f5ff52541e5793652688c3c367 Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Sat, 26 Jan 2019 12:54:09 -0500
Subject: [PATCH 04/24] use `SOURCE_DATE_EPOCH` for man page time if set

---
 src/bootstrap/dist.rs | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 98d2fb1e2d0..c41df3209c8 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -23,7 +23,7 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::compile;
 use crate::tool::{self, Tool};
 use crate::cache::{INTERNER, Interned};
-use time;
+use time::{self, Timespec};
 
 pub fn pkgname(builder: &Builder, component: &str) -> String {
     if component == "cargo" {
@@ -528,7 +528,19 @@ impl Step for Rustc {
             t!(fs::create_dir_all(image.join("share/man/man1")));
             let man_src = builder.src.join("src/doc/man");
             let man_dst = image.join("share/man/man1");
-            let month_year = t!(time::strftime("%B %Y", &time::now()));
+
+            // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time.
+            let time = env::var("SOURCE_DATE_EPOCH")
+                .map(|timestamp| {
+                    let epoch = timestamp.parse().map_err(|err| {
+                        format!("could not parse SOURCE_DATE_EPOCH: {}", err)
+                    }).unwrap();
+
+                    time::at(Timespec::new(epoch, 0))
+                })
+                .unwrap_or_else(|_| time::now());
+
+            let month_year = t!(time::strftime("%B %Y", &time));
             // don't use our `bootstrap::util::{copy, cp_r}`, because those try
             // to hardlink, and we don't want to edit the source templates
             for file_entry in builder.read_dir(&man_src) {

From 1e577269da046b5e2b862830b72210c855fca123 Mon Sep 17 00:00:00 2001
From: Dale Wijnand <dale.wijnand@gmail.com>
Date: Sun, 27 Jan 2019 17:03:03 +0000
Subject: [PATCH 05/24] Introduce into_raw_non_null on Rc and Arc

---
 src/liballoc/rc.rs   | 21 +++++++++++++++++++++
 src/liballoc/sync.rs | 21 +++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index d3a55c59ff6..456f7cd5e2f 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -435,6 +435,27 @@ impl<T: ?Sized> Rc<T> {
         }
     }
 
+    /// Consumes the `Rc`, returning the wrapped pointer as `NonNull<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(rc_into_raw_non_null)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let x = Rc::new(10);
+    /// let ptr = Rc::into_raw_non_null(x);
+    /// let deref = unsafe { *ptr.as_ref() };
+    /// assert_eq!(deref, 10);
+    /// ```
+    #[unstable(feature = "rc_into_raw_non_null", issue = "47336")]
+    #[inline]
+    pub fn into_raw_non_null(this: Self) -> NonNull<T> {
+        // safe because Rc guarantees its pointer is non-null
+        unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) }
+    }
+
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///
     /// [weak]: struct.Weak.html
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 390a0791650..5cffa93db11 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -413,6 +413,27 @@ impl<T: ?Sized> Arc<T> {
         }
     }
 
+    /// Consumes the `Arc`, returning the wrapped pointer as `NonNull<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(rc_into_raw_non_null)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let x = Arc::new(10);
+    /// let ptr = Arc::into_raw_non_null(x);
+    /// let deref = unsafe { *ptr.as_ref() };
+    /// assert_eq!(deref, 10);
+    /// ```
+    #[unstable(feature = "rc_into_raw_non_null", issue = "47336")]
+    #[inline]
+    pub fn into_raw_non_null(this: Self) -> NonNull<T> {
+        // safe because Arc guarantees its pointer is non-null
+        unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) }
+    }
+
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///
     /// [weak]: struct.Weak.html

From a75ae00c63ad2859351e9682026462048f1cf83e Mon Sep 17 00:00:00 2001
From: Jethro Beekman <jethro@fortanix.com>
Date: Tue, 29 Jan 2019 17:10:22 +0530
Subject: [PATCH 06/24] SGX target: improve panic & exit handling

---
 src/libstd/sys/sgx/abi/entry.S          | 20 ++++++++---------
 src/libstd/sys/sgx/abi/panic.rs         | 30 ++++++++++++++++---------
 src/libstd/sys/sgx/abi/usercalls/mod.rs |  2 +-
 src/libstd/sys/sgx/mod.rs               |  2 +-
 4 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S
index ac7f95d4eae..9b46c2180d9 100644
--- a/src/libstd/sys/sgx/abi/entry.S
+++ b/src/libstd/sys/sgx/abi/entry.S
@@ -66,7 +66,7 @@ IMAGE_BASE:
     globvar EH_FRM_HDR_SIZE 8
 
 .Lreentry_panic_msg:
-    .asciz "Re-entered panicked enclave!"
+    .asciz "Re-entered aborted enclave!"
 .Lreentry_panic_msg_end:
 
 .Lusercall_panic_msg:
@@ -80,7 +80,7 @@ IMAGE_BASE:
     .org .+48 /*  reserved bits */
 
 .data
-.Lpanicked:
+.Laborted:
     .byte 0
 
 /*  TCS local storage section */
@@ -134,6 +134,9 @@ sgx_entry:
     jz .Lskip_debug_init
     mov %r10,%gs:tcsls_debug_panic_buf_ptr
 .Lskip_debug_init:
+/*  check for abort */
+    bt $0,.Laborted(%rip)
+    jc .Lreentry_panic
 /*  check if returning from usercall */
     mov %gs:tcsls_last_rsp,%r11
     test %r11,%r11
@@ -164,9 +167,6 @@ sgx_entry:
     mov %r14,%r8
     mov %r15,%r9
 .Lskip_init:
-/*  check for panic */
-    bt $0,.Lpanicked(%rip)
-    jc .Lreentry_panic
 /*  call into main entry point */
     load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */
     call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */
@@ -237,18 +237,18 @@ sgx_entry:
     stmxcsr (%rsp)
 .endm
 
-.global panic_exit
-panic_exit:
+.global usercall_exit
+usercall_exit:
 /* save registers in DEBUG mode, so that debugger can reconstruct the stack */
     testb $0xff,DEBUG(%rip)
     jz .Lskip_save_registers
     push_callee_saved_registers
     movq %rsp,%gs:tcsls_panic_last_rsp
 .Lskip_save_registers:
-/* set panicked bit */
-    movb $1,.Lpanicked(%rip)
+/* set aborted bit */
+    movb $1,.Laborted(%rip)
 /* call usercall exit(true) */
-    mov $1,%esi   /*  RSI = usercall() argument: panic = true */
+    /* NOP: mov %rsi,%rsi */ /*  RSI = usercall() argument: panic */
     xor %rdx,%rdx /*  RDX cleared */
     movq $usercall_nr_exit,%rdi /*  RDI = usercall exit */
     jmp .Lexit
diff --git a/src/libstd/sys/sgx/abi/panic.rs b/src/libstd/sys/sgx/abi/panic.rs
index 5ace7fb3368..d23fa9a9ec6 100644
--- a/src/libstd/sys/sgx/abi/panic.rs
+++ b/src/libstd/sys/sgx/abi/panic.rs
@@ -1,12 +1,18 @@
+use super::usercalls::alloc::UserRef;
+use cmp;
 use io::{self, Write};
-use slice::from_raw_parts_mut;
+use mem;
 
 extern "C" {
     fn take_debug_panic_buf_ptr() -> *mut u8;
     static DEBUG: u8;
 }
 
-pub(crate) struct SgxPanicOutput(Option<&'static mut [u8]>);
+pub(crate) struct SgxPanicOutput(Option<&'static mut UserRef<[u8]>>);
+
+fn empty_user_slice() -> &'static mut UserRef<[u8]> {
+    unsafe { UserRef::from_raw_parts_mut(1 as *mut u8, 0) }
+}
 
 impl SgxPanicOutput {
     pub(crate) fn new() -> Option<Self> {
@@ -17,32 +23,36 @@ impl SgxPanicOutput {
         }
     }
 
-    fn init(&mut self) -> &mut &'static mut [u8] {
+    fn init(&mut self) -> &mut &'static mut UserRef<[u8]> {
         self.0.get_or_insert_with(|| unsafe {
             let ptr = take_debug_panic_buf_ptr();
             if ptr.is_null() {
-                &mut []
+                empty_user_slice()
             } else {
-                from_raw_parts_mut(ptr, 1024)
+                UserRef::from_raw_parts_mut(ptr, 1024)
             }
         })
     }
 }
 
 impl Write for SgxPanicOutput {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.init().write(buf)
+    fn write(&mut self, src: &[u8]) -> io::Result<usize> {
+        let dst = mem::replace(self.init(), empty_user_slice());
+        let written = cmp::min(src.len(), dst.len());
+        dst[..written].copy_from_enclave(&src[..written]);
+        self.0 = Some(&mut dst[written..]);
+        Ok(written)
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        self.init().flush()
+        Ok(())
     }
 }
 
 #[no_mangle]
 pub extern "C" fn panic_msg(msg: &str) -> ! {
     let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
-    unsafe { panic_exit(); }
+    unsafe { usercall_exit(true); }
 }
 
-extern "C" { pub fn panic_exit() -> !; }
+extern "C" { pub fn usercall_exit(panic: bool) -> !; }
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs
index 58903761ebe..4e889c172ef 100644
--- a/src/libstd/sys/sgx/abi/usercalls/mod.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs
@@ -119,7 +119,7 @@ pub unsafe fn launch_thread() -> IoResult<()> {
 /// Usercall `exit`. See the ABI documentation for more information.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn exit(panic: bool) -> ! {
-    unsafe { raw::exit(panic) }
+    unsafe { super::panic::usercall_exit(panic) }
 }
 
 /// Usercall `wait`. See the ABI documentation for more information.
diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs
index 7f8550490a1..f2593c35bed 100644
--- a/src/libstd/sys/sgx/mod.rs
+++ b/src/libstd/sys/sgx/mod.rs
@@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
 }
 
 pub unsafe fn abort_internal() -> ! {
-    abi::panic::panic_exit()
+    abi::panic::usercall_exit(true)
 }
 
 pub fn hashmap_random_keys() -> (u64, u64) {

From 84a89aa666db1a144f7bd44e535f19ac81dfaae5 Mon Sep 17 00:00:00 2001
From: Siddhartha Sahu <git@siddharthasahu.in>
Date: Tue, 29 Jan 2019 17:30:49 -0500
Subject: [PATCH 07/24] Add link to the edition guide.

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

diff --git a/src/doc/index.md b/src/doc/index.md
index 55897e5a3e9..7bd1854d86f 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -71,6 +71,10 @@ accomplishing various tasks.
   </form>
 </div>
 
+## The Edition Guide
+
+[The Edition Guide](edition-guide/index.html) describes the Rust editions.
+
 ## The Rustc Book
 
 [The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.

From 62867b499291a69f5df16a60228c6bcedc5e4225 Mon Sep 17 00:00:00 2001
From: Knium_ <hi.im.knium@gmail.com>
Date: Wed, 30 Jan 2019 13:50:44 +0900
Subject: [PATCH 08/24] Suggest to add each of `|` and `()` when unexpected `,`
 is found in pattern

---
 src/libsyntax/parse/parser.rs                 |  7 ++-
 ...92-tuple-destructure-missing-parens.stderr | 60 +++++++++++++++++--
 2 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 65572102c59..514b2952c50 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4381,9 +4381,14 @@ impl<'a> Parser<'a> {
             if let Ok(seq_snippet) = self.sess.source_map().span_to_snippet(seq_span) {
                 err.span_suggestion(
                     seq_span,
-                    "try adding parentheses",
+                    "try adding parentheses to match on a tuple..",
                     format!("({})", seq_snippet),
                     Applicability::MachineApplicable
+                ).span_suggestion(
+                    seq_span,
+                    "..or a vertical bar to match on multiple alternatives",
+                    format!("{}", seq_snippet.replace(",", " |")),
+                    Applicability::MachineApplicable
                 );
             }
             return Err(err);
diff --git a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
index 9df881e8e26..8099c3c0584 100644
--- a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
+++ b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
@@ -2,37 +2,85 @@ error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:38:17
    |
 LL |     while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") {
-   |               --^------- help: try adding parentheses: `(b1, b2, b3)`
+   |                 ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") {
+   |               ^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     while let b1 | b2 | b3 = reading_frame.next().expect("there should be a start codon") {
+   |               ^^^^^^^^^^^^
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:49:14
    |
 LL |     if let b1, b2, b3 = reading_frame.next().unwrap() {
-   |            --^------- help: try adding parentheses: `(b1, b2, b3)`
+   |              ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     if let (b1, b2, b3) = reading_frame.next().unwrap() {
+   |            ^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     if let b1 | b2 | b3 = reading_frame.next().unwrap() {
+   |            ^^^^^^^^^^^^
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:59:28
    |
 LL |         Nucleotide::Adenine, Nucleotide::Cytosine, _ => true
-   |         -------------------^------------------------ help: try adding parentheses: `(Nucleotide::Adenine, Nucleotide::Cytosine, _)`
+   |                            ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |         (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |         Nucleotide::Adenine | Nucleotide::Cytosine | _ => true
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:67:10
    |
 LL |     for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
-   |         -^----------- help: try adding parentheses: `(x, _barr_body)`
+   |          ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     for x | _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10
    |
 LL |     for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
-   |         -^------------------- help: try adding parentheses: `(x, y @ Allosome::Y(_))`
+   |          ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     for x | y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14
    |
 LL |     let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
-   |         -----^---- help: try adding parentheses: `(women, men)`
+   |              ^
+help: try adding parentheses to match on a tuple..
+   |
+LL |     let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
+   |         ^^^^^^^^^^^^
+help: ..or a vertical bar to match on multiple alternatives
+   |
+LL |     let women | men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
+   |         ^^^^^^^^^^^
 
 error: aborting due to 6 previous errors
 

From 7cfb05fd23b5ecc6a13f4629844ff81ac758497c Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 14:16:18 +0100
Subject: [PATCH 09/24] Merge `locals` and `local_layouts` fields

---
 src/librustc_mir/interpret/eval_context.rs | 70 ++++++++++++----------
 src/librustc_mir/interpret/mod.rs          |  2 +-
 src/librustc_mir/interpret/snapshot.rs     | 35 ++++++++---
 3 files changed, 68 insertions(+), 39 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 34443bb353e..d2cabde9863 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -76,8 +76,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
     /// The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
-    pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
-    pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
+    pub locals: IndexVec<mir::Local, LocalValue<'tcx, Tag>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -106,9 +105,17 @@ pub enum StackPopCleanup {
     None { cleanup: bool },
 }
 
-// State of a local variable
+/// State of a local variable including a memoized layout
+#[derive(Clone, PartialEq, Eq)]
+pub struct LocalValue<'tcx, Tag=(), Id=AllocId> {
+    pub state: LocalState<Tag, Id>,
+    /// Don't modify if `Some`, this is only used to prevent computing the layout twice
+    pub layout: Cell<Option<TyLayout<'tcx>>>,
+}
+
+/// State of a local variable
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalValue<Tag=(), Id=AllocId> {
+pub enum LocalState<Tag=(), Id=AllocId> {
     Dead,
     // Mostly for convenience, we re-use the `Operand` type here.
     // This is an optimization over just always having a pointer here;
@@ -117,18 +124,18 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
     Live(Operand<Tag, Id>),
 }
 
-impl<'tcx, Tag> LocalValue<Tag> {
+impl<'tcx, Tag> LocalValue<'tcx, Tag> {
     pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
-        match self {
-            LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref val) => Ok(val),
+        match self.state {
+            LocalState::Dead => err!(DeadLocal),
+            LocalState::Live(ref val) => Ok(val),
         }
     }
 
     pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
-        match self {
-            LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref mut val) => Ok(val),
+        match self.state {
+            LocalState::Dead => err!(DeadLocal),
+            LocalState::Live(ref mut val) => Ok(val),
         }
     }
 }
@@ -312,7 +319,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local
     ) -> EvalResult<'tcx, TyLayout<'tcx>> {
-        let cell = &frame.local_layouts[local];
+        let cell = &frame.locals[local].layout;
         if cell.get().is_none() {
             let local_ty = frame.mir.local_decls[local].ty;
             let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
@@ -454,7 +461,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             // empty local array, we fill it in below, after we are inside the stack frame and
             // all methods actually know about the frame
             locals: IndexVec::new(),
-            local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
             span,
             instance,
             stmt: 0,
@@ -464,14 +470,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         // don't allocate at all for trivial constants
         if mir.local_decls.len() > 1 {
             // We put some marker immediate into the locals that we later want to initialize.
-            // This can be anything except for LocalValue::Dead -- because *that* is the
+            // This can be anything except for LocalState::Dead -- because *that* is the
             // value we use for things that we know are initially dead.
-            let dummy =
-                LocalValue::Live(Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef)));
+            let dummy = LocalValue {
+                state: LocalState::Live(Operand::Immediate(Immediate::Scalar(
+                    ScalarMaybeUndef::Undef,
+                ))),
+                layout: Cell::new(None),
+            };
             let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
             // Return place is handled specially by the `eval_place` functions, and the
             // entry in `locals` should never be used. Make it dead, to be sure.
-            locals[mir::RETURN_PLACE] = LocalValue::Dead;
+            locals[mir::RETURN_PLACE].state = LocalState::Dead;
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
@@ -484,7 +494,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
                             match stmt.kind {
                                 StorageLive(local) |
                                 StorageDead(local) => {
-                                    locals[local] = LocalValue::Dead;
+                                    locals[local].state = LocalState::Dead;
                                 }
                                 _ => {}
                             }
@@ -494,13 +504,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             }
             // Finally, properly initialize all those that still have the dummy value
             for (idx, local) in locals.iter_enumerated_mut() {
-                match *local {
-                    LocalValue::Live(_) => {
+                match local.state {
+                    LocalState::Live(_) => {
                         // This needs to be peoperly initialized.
                         let layout = self.layout_of_local(self.frame(), idx)?;
-                        *local = LocalValue::Live(self.uninit_operand(layout)?);
+                        local.state = LocalState::Live(self.uninit_operand(layout)?);
                     }
-                    LocalValue::Dead => {
+                    LocalState::Dead => {
                         // Nothing to do
                     }
                 }
@@ -543,7 +553,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         }
         // Deallocate all locals that are backed by an allocation.
         for local in frame.locals {
-            self.deallocate_local(local)?;
+            self.deallocate_local(local.state)?;
         }
         // Validate the return value. Do this after deallocating so that we catch dangling
         // references.
@@ -587,31 +597,31 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
     pub fn storage_live(
         &mut self,
         local: mir::Local
-    ) -> EvalResult<'tcx, LocalValue<M::PointerTag>> {
+    ) -> EvalResult<'tcx, LocalState<M::PointerTag>> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
         let layout = self.layout_of_local(self.frame(), local)?;
-        let init = LocalValue::Live(self.uninit_operand(layout)?);
+        let init = LocalState::Live(self.uninit_operand(layout)?);
         // StorageLive *always* kills the value that's currently stored
-        Ok(mem::replace(&mut self.frame_mut().locals[local], init))
+        Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
     }
 
     /// Returns the old value of the local.
     /// Remember to deallocate that!
-    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalState<M::PointerTag> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
 
-        mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
+        mem::replace(&mut self.frame_mut().locals[local].state, LocalState::Dead)
     }
 
     pub(super) fn deallocate_local(
         &mut self,
-        local: LocalValue<M::PointerTag>,
+        local: LocalState<M::PointerTag>,
     ) -> EvalResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
-        if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
+        if let LocalState::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             trace!("deallocating local");
             let ptr = ptr.to_ptr()?;
             self.memory.dump_alloc(ptr.alloc_id);
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index e3ab90a6020..6ee7d3309f4 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -18,7 +18,7 @@ mod visitor;
 pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
 
 pub use self::eval_context::{
-    EvalContext, Frame, StackPopCleanup, LocalValue,
+    EvalContext, Frame, StackPopCleanup, LocalValue, LocalState,
 };
 
 pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 53105266b39..0b5dc944692 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -7,7 +7,7 @@
 
 use std::hash::{Hash, Hasher};
 
-use rustc::ich::StableHashingContextProvider;
+use rustc::ich::{StableHashingContextProvider, StableHashingContext};
 use rustc::mir;
 use rustc::mir::interpret::{
     AllocId, Pointer, Scalar,
@@ -19,12 +19,12 @@ use rustc::ty::{self, TyCtxt};
 use rustc::ty::layout::Align;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 use syntax::ast::Mutability;
 use syntax::source_map::Span;
 
 use super::eval_context::{LocalValue, StackPopCleanup};
-use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef};
+use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalState};
 use const_eval::CompileTimeInterpreter;
 
 #[derive(Default)]
@@ -250,11 +250,11 @@ impl_snapshot_for!(enum Operand {
     Indirect(m),
 });
 
-impl_stable_hash_for!(enum ::interpret::LocalValue {
+impl_stable_hash_for!(enum ::interpret::LocalState {
     Dead,
     Live(x),
 });
-impl_snapshot_for!(enum LocalValue {
+impl_snapshot_for!(enum LocalState {
     Live(v),
     Dead,
 });
@@ -309,7 +309,7 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
     span: &'a Span,
     return_to_block: &'a StackPopCleanup,
     return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
-    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
+    locals: IndexVec<mir::Local, LocalState<(), AllocIdSnapshot<'a>>>,
     block: &'a mir::BasicBlock,
     stmt: usize,
 }
@@ -321,7 +321,6 @@ impl_stable_hash_for!(impl<'mir, 'tcx: 'mir> for struct Frame<'mir, 'tcx> {
     return_to_block,
     return_place -> (return_place.as_ref().map(|r| &**r)),
     locals,
-    local_layouts -> _,
     block,
     stmt,
     extra,
@@ -340,7 +339,6 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
             return_to_block,
             return_place,
             locals,
-            local_layouts: _,
             block,
             stmt,
             extra: _,
@@ -358,6 +356,27 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
     }
 }
 
+impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalValue<'tcx>
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = LocalState<(), AllocIdSnapshot<'a>>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        self.state.snapshot(ctx)
+    }
+}
+
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LocalValue<'gcx> {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        self.state.hash_stable(hcx, hasher);
+    }
+}
+
 impl<'a, 'b, 'mir, 'tcx: 'a+'mir> SnapshotContext<'b>
     for Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
 {

From bc528d93ec27758af5e61c21c3e05d8da077a9ce Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 14:55:31 +0100
Subject: [PATCH 10/24] Allow `layout_of_local` to also use cached layouts

---
 src/librustc_mir/interpret/eval_context.rs | 11 +++++++----
 src/librustc_mir/interpret/operand.rs      | 12 +++++++-----
 src/librustc_mir/interpret/place.rs        |  6 +++---
 src/librustc_mir/interpret/terminator.rs   |  4 ++--
 4 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index d2cabde9863..d890e2fbe46 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -317,13 +317,16 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
     pub fn layout_of_local(
         &self,
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
-        local: mir::Local
+        local: mir::Local,
+        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, TyLayout<'tcx>> {
         let cell = &frame.locals[local].layout;
         if cell.get().is_none() {
+            let layout = ::interpret::operand::from_known_layout(layout, || {
             let local_ty = frame.mir.local_decls[local].ty;
             let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
-            let layout = self.layout_of(local_ty)?;
+                self.layout_of(local_ty)
+            })?;
             cell.set(Some(layout));
         }
 
@@ -507,7 +510,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
                 match local.state {
                     LocalState::Live(_) => {
                         // This needs to be peoperly initialized.
-                        let layout = self.layout_of_local(self.frame(), idx)?;
+                        let layout = self.layout_of_local(self.frame(), idx, None)?;
                         local.state = LocalState::Live(self.uninit_operand(layout)?);
                     }
                     LocalState::Dead => {
@@ -601,7 +604,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
-        let layout = self.layout_of_local(self.frame(), local)?;
+        let layout = self.layout_of_local(self.frame(), local, None)?;
         let init = LocalState::Live(self.uninit_operand(layout)?);
         // StorageLive *always* kills the value that's currently stored
         Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index e4bee24c88c..a7e92d56794 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -227,7 +227,7 @@ impl<'tcx, Tag> OpTy<'tcx, Tag>
 // Use the existing layout if given (but sanity check in debug mode),
 // or compute the layout.
 #[inline(always)]
-fn from_known_layout<'tcx>(
+pub(super) fn from_known_layout<'tcx>(
     layout: Option<TyLayout<'tcx>>,
     compute: impl FnOnce() -> EvalResult<'tcx, TyLayout<'tcx>>
 ) -> EvalResult<'tcx, TyLayout<'tcx>> {
@@ -461,10 +461,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         &self,
         frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local,
+        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         assert_ne!(local, mir::RETURN_PLACE);
         let op = *frame.locals[local].access()?;
-        let layout = self.layout_of_local(frame, local)?;
+        let layout = self.layout_of_local(frame, local, layout)?;
         Ok(OpTy { op, layout })
     }
 
@@ -473,14 +474,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     fn eval_place_to_op(
         &self,
         mir_place: &mir::Place<'tcx>,
+        layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         let op = match *mir_place {
             Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
-            Local(local) => self.access_local(self.frame(), local)?,
+            Local(local) => self.access_local(self.frame(), local, layout)?,
 
             Projection(ref proj) => {
-                let op = self.eval_place_to_op(&proj.base)?;
+                let op = self.eval_place_to_op(&proj.base, None)?;
                 self.operand_projection(op, &proj.elem)?
             }
 
@@ -504,7 +506,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             // FIXME: do some more logic on `move` to invalidate the old location
             Copy(ref place) |
             Move(ref place) =>
-                self.eval_place_to_op(place)?,
+                self.eval_place_to_op(place, layout)?,
 
             Constant(ref constant) => {
                 let layout = from_known_layout(layout, || {
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index f3a948a6ca3..ffb8ec899a0 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -624,7 +624,7 @@ where
                     // their layout on return.
                     PlaceTy {
                         place: *return_place,
-                        layout: self.layout_of_local(self.frame(), mir::RETURN_PLACE)?,
+                        layout: self.layout_of_local(self.frame(), mir::RETURN_PLACE, None)?,
                     },
                 None => return err!(InvalidNullPointerUsage),
             },
@@ -633,7 +633,7 @@ where
                     frame: self.cur_frame(),
                     local,
                 },
-                layout: self.layout_of_local(self.frame(), local)?,
+                layout: self.layout_of_local(self.frame(), local, None)?,
             },
 
             Projection(ref proj) => {
@@ -901,7 +901,7 @@ where
                         // We need the layout of the local.  We can NOT use the layout we got,
                         // that might e.g., be an inner field of a struct with `Scalar` layout,
                         // that has different alignment than the outer field.
-                        let local_layout = self.layout_of_local(&self.stack[frame], local)?;
+                        let local_layout = self.layout_of_local(&self.stack[frame], local, None)?;
                         let ptr = self.allocate(local_layout, MemoryKind::Stack);
                         // We don't have to validate as we can assume the local
                         // was already valid for its type.
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 951e9fabe59..7e823524c18 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -309,7 +309,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                         mir.spread_arg,
                         mir.args_iter()
                             .map(|local|
-                                (local, self.layout_of_local(self.frame(), local).unwrap().ty)
+                                (local, self.layout_of_local(self.frame(), local, None).unwrap().ty)
                             )
                             .collect::<Vec<_>>()
                     );
@@ -383,7 +383,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                         }
                     } else {
                         let callee_layout =
-                            self.layout_of_local(self.frame(), mir::RETURN_PLACE)?;
+                            self.layout_of_local(self.frame(), mir::RETURN_PLACE, None)?;
                         if !callee_layout.abi.is_uninhabited() {
                             return err!(FunctionRetMismatch(
                                 self.tcx.types.never, callee_layout.ty

From 154c54c875fe8892cacc2d8bc0275ecc27b4baaf Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 15:01:42 +0100
Subject: [PATCH 11/24] Make priroda happy again

---
 src/librustc_mir/interpret/operand.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index a7e92d56794..37e421c2e73 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -457,7 +457,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     }
 
     /// This is used by [priroda](https://github.com/oli-obk/priroda) to get an OpTy from a local
-    fn access_local(
+    pub fn access_local(
         &self,
         frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local,

From 4165c890ed573cc801a27483935ccdbc01fcd75b Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 15:05:50 +0100
Subject: [PATCH 12/24] Can't use `layout_of_local` for the frame currently
 being created

---
 src/librustc_mir/interpret/eval_context.rs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index d890e2fbe46..bb4f5c131d6 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -509,9 +509,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             for (idx, local) in locals.iter_enumerated_mut() {
                 match local.state {
                     LocalState::Live(_) => {
-                        // This needs to be peoperly initialized.
-                        let layout = self.layout_of_local(self.frame(), idx, None)?;
+                        // This needs to be properly initialized.
+                        let layout = self.layout_of(mir.local_decls[idx].ty)?;
                         local.state = LocalState::Live(self.uninit_operand(layout)?);
+                        local.layout = Cell::new(Some(layout));
                     }
                     LocalState::Dead => {
                         // Nothing to do

From ab708f5c6f7077ccf0b30baeb9395d372f5dbcce Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 15:08:59 +0100
Subject: [PATCH 13/24] The return place's layout is only used once per frame,
 so caching doesn't help

---
 src/librustc_mir/interpret/place.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index ffb8ec899a0..ba1960300a8 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -624,7 +624,7 @@ where
                     // their layout on return.
                     PlaceTy {
                         place: *return_place,
-                        layout: self.layout_of_local(self.frame(), mir::RETURN_PLACE, None)?,
+                        layout: self.layout_of(self.frame().mir.return_ty())?,
                     },
                 None => return err!(InvalidNullPointerUsage),
             },

From 7017927aaf5ba14cec6c28b1079a93abfc715985 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 15:24:41 +0100
Subject: [PATCH 14/24] Indent fixup

---
 src/librustc_mir/interpret/eval_context.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index bb4f5c131d6..3382288b99a 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -323,8 +323,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         let cell = &frame.locals[local].layout;
         if cell.get().is_none() {
             let layout = ::interpret::operand::from_known_layout(layout, || {
-            let local_ty = frame.mir.local_decls[local].ty;
-            let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
+                let local_ty = frame.mir.local_decls[local].ty;
+                let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
                 self.layout_of(local_ty)
             })?;
             cell.set(Some(layout));

From 4e0af1fee19c2ff056e20a55464c233dc30e5c92 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 15:42:00 +0100
Subject: [PATCH 15/24] Monomorphize types when not going through
 `layout_of_local`

---
 src/librustc_mir/interpret/eval_context.rs | 3 ++-
 src/librustc_mir/interpret/place.rs        | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 3382288b99a..4bf84cb465f 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -510,7 +510,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
                 match local.state {
                     LocalState::Live(_) => {
                         // This needs to be properly initialized.
-                        let layout = self.layout_of(mir.local_decls[idx].ty)?;
+                        let ty = self.monomorphize(mir.local_decls[idx].ty)?;
+                        let layout = self.layout_of(ty)?;
                         local.state = LocalState::Live(self.uninit_operand(layout)?);
                         local.layout = Cell::new(Some(layout));
                     }
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index ba1960300a8..9ca7f9d8e27 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -624,7 +624,7 @@ where
                     // their layout on return.
                     PlaceTy {
                         place: *return_place,
-                        layout: self.layout_of(self.frame().mir.return_ty())?,
+                        layout: self.layout_of(self.monomorphize(self.frame().mir.return_ty())?)?,
                     },
                 None => return err!(InvalidNullPointerUsage),
             },

From 5aa713e1c39b0e84ae9c96f99514f4981d3cea30 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 15:51:20 +0100
Subject: [PATCH 16/24] Eliminate an unwrap

---
 src/librustc_mir/interpret/eval_context.rs | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4bf84cb465f..4e66d21214b 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -320,17 +320,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         local: mir::Local,
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, TyLayout<'tcx>> {
-        let cell = &frame.locals[local].layout;
-        if cell.get().is_none() {
-            let layout = ::interpret::operand::from_known_layout(layout, || {
-                let local_ty = frame.mir.local_decls[local].ty;
-                let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
-                self.layout_of(local_ty)
-            })?;
-            cell.set(Some(layout));
+        match frame.locals[local].layout.get() {
+            None => {
+                let layout = ::interpret::operand::from_known_layout(layout, || {
+                    let local_ty = frame.mir.local_decls[local].ty;
+                    let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
+                    self.layout_of(local_ty)
+                })?;
+                frame.locals[local].layout.set(Some(layout));
+                Ok(layout)
+            }
+            Some(layout) => Ok(layout),
         }
-
-        Ok(cell.get().unwrap())
     }
 
     pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {

From a3f0af2e672055cddef1e87b56caff763322e6d9 Mon Sep 17 00:00:00 2001
From: Jethro Beekman <jethro@fortanix.com>
Date: Wed, 30 Jan 2019 18:57:55 +0530
Subject: [PATCH 17/24] Add MOVBE feature

---
 src/librustc_codegen_llvm/llvm_util.rs | 1 +
 src/librustc_typeck/collect.rs         | 1 +
 src/libsyntax/feature_gate.rs          | 1 +
 src/test/ui/target-feature-gate.rs     | 1 +
 src/test/ui/target-feature-gate.stderr | 2 +-
 5 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index e2d0e558d3b..b46e6ef84b9 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -147,6 +147,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[
     ("fxsr", None),
     ("lzcnt", None),
     ("mmx", Some("mmx_target_feature")),
+    ("movbe", Some("movbe_target_feature")),
     ("pclmulqdq", None),
     ("popcnt", None),
     ("rdrand", None),
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index ade84faae8d..393f3066c62 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2205,6 +2205,7 @@ fn from_target_feature(
                 Some("wasm_target_feature") => rust_features.wasm_target_feature,
                 Some("cmpxchg16b_target_feature") => rust_features.cmpxchg16b_target_feature,
                 Some("adx_target_feature") => rust_features.adx_target_feature,
+                Some("movbe_target_feature") => rust_features.movbe_target_feature,
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 28209248246..9dd17b420aa 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -394,6 +394,7 @@ declare_features! (
     (active, wasm_target_feature, "1.30.0", Some(44839), None),
     (active, adx_target_feature, "1.32.0", Some(44839), None),
     (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
+    (active, movbe_target_feature, "1.34.0", Some(44839), None),
 
     // Allows macro invocations on modules expressions and statements and
     // procedural macros to expand to non-items.
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
index 30fb534dbb5..84300301b76 100644
--- a/src/test/ui/target-feature-gate.rs
+++ b/src/test/ui/target-feature-gate.rs
@@ -22,6 +22,7 @@
 // gate-test-wasm_target_feature
 // gate-test-adx_target_feature
 // gate-test-cmpxchg16b_target_feature
+// gate-test-movbe_target_feature
 // min-llvm-version 6.0
 
 #[target_feature(enable = "avx512bw")]
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
index 8dfb4f65f98..24141d0064f 100644
--- a/src/test/ui/target-feature-gate.stderr
+++ b/src/test/ui/target-feature-gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
-  --> $DIR/target-feature-gate.rs:27:18
+  --> $DIR/target-feature-gate.rs:28:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^

From a7a5cb620feab14defb633af4ebf8d0671c22441 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 17:50:46 +0100
Subject: [PATCH 18/24] Prefer macro over manual implementation

---
 src/librustc_mir/interpret/snapshot.rs | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 0b5dc944692..c9fe673c847 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -7,7 +7,7 @@
 
 use std::hash::{Hash, Hasher};
 
-use rustc::ich::{StableHashingContextProvider, StableHashingContext};
+use rustc::ich::StableHashingContextProvider;
 use rustc::mir;
 use rustc::mir::interpret::{
     AllocId, Pointer, Scalar,
@@ -19,7 +19,7 @@ use rustc::ty::{self, TyCtxt};
 use rustc::ty::layout::Align;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use syntax::ast::Mutability;
 use syntax::source_map::Span;
 
@@ -366,16 +366,10 @@ impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalValue<'tcx>
     }
 }
 
-
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LocalValue<'gcx> {
-    fn hash_stable<W: StableHasherResult>(
-        &self,
-        hcx: &mut StableHashingContext<'a>,
-        hasher: &mut StableHasher<W>,
-    ) {
-        self.state.hash_stable(hcx, hasher);
-    }
-}
+impl_stable_hash_for!(struct LocalValue<'tcx> {
+    state,
+    layout -> _,
+});
 
 impl<'a, 'b, 'mir, 'tcx: 'a+'mir> SnapshotContext<'b>
     for Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>

From 765fa81a6e8d063db60be20e710e51d8ca995fbd Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 17:51:59 +0100
Subject: [PATCH 19/24] Swap the names of `LocalValue` and `LocalState`

---
 src/librustc/mir/interpret/value.rs        |  2 +-
 src/librustc_mir/interpret/eval_context.rs | 46 +++++++++++-----------
 src/librustc_mir/interpret/mod.rs          |  2 +-
 src/librustc_mir/interpret/snapshot.rs     | 16 ++++----
 4 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 4ac84bcfd19..1328a1aeeab 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -14,7 +14,7 @@ pub struct RawConst<'tcx> {
 }
 
 /// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
-/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
+/// matches the LocalState optimizations for easy conversions between Value and ConstValue.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
 pub enum ConstValue<'tcx> {
     /// Used only for types with layout::abi::Scalar ABI and ZSTs
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4e66d21214b..1b976d822eb 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -76,7 +76,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
     /// The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
-    pub locals: IndexVec<mir::Local, LocalValue<'tcx, Tag>>,
+    pub locals: IndexVec<mir::Local, LocalState<'tcx, Tag>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -107,15 +107,15 @@ pub enum StackPopCleanup {
 
 /// State of a local variable including a memoized layout
 #[derive(Clone, PartialEq, Eq)]
-pub struct LocalValue<'tcx, Tag=(), Id=AllocId> {
-    pub state: LocalState<Tag, Id>,
+pub struct LocalState<'tcx, Tag=(), Id=AllocId> {
+    pub state: LocalValue<Tag, Id>,
     /// Don't modify if `Some`, this is only used to prevent computing the layout twice
     pub layout: Cell<Option<TyLayout<'tcx>>>,
 }
 
 /// State of a local variable
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalState<Tag=(), Id=AllocId> {
+pub enum LocalValue<Tag=(), Id=AllocId> {
     Dead,
     // Mostly for convenience, we re-use the `Operand` type here.
     // This is an optimization over just always having a pointer here;
@@ -124,18 +124,18 @@ pub enum LocalState<Tag=(), Id=AllocId> {
     Live(Operand<Tag, Id>),
 }
 
-impl<'tcx, Tag> LocalValue<'tcx, Tag> {
+impl<'tcx, Tag> LocalState<'tcx, Tag> {
     pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
         match self.state {
-            LocalState::Dead => err!(DeadLocal),
-            LocalState::Live(ref val) => Ok(val),
+            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Live(ref val) => Ok(val),
         }
     }
 
     pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
         match self.state {
-            LocalState::Dead => err!(DeadLocal),
-            LocalState::Live(ref mut val) => Ok(val),
+            LocalValue::Dead => err!(DeadLocal),
+            LocalValue::Live(ref mut val) => Ok(val),
         }
     }
 }
@@ -474,10 +474,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
         // don't allocate at all for trivial constants
         if mir.local_decls.len() > 1 {
             // We put some marker immediate into the locals that we later want to initialize.
-            // This can be anything except for LocalState::Dead -- because *that* is the
+            // This can be anything except for LocalValue::Dead -- because *that* is the
             // value we use for things that we know are initially dead.
-            let dummy = LocalValue {
-                state: LocalState::Live(Operand::Immediate(Immediate::Scalar(
+            let dummy = LocalState {
+                state: LocalValue::Live(Operand::Immediate(Immediate::Scalar(
                     ScalarMaybeUndef::Undef,
                 ))),
                 layout: Cell::new(None),
@@ -485,7 +485,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
             // Return place is handled specially by the `eval_place` functions, and the
             // entry in `locals` should never be used. Make it dead, to be sure.
-            locals[mir::RETURN_PLACE].state = LocalState::Dead;
+            locals[mir::RETURN_PLACE].state = LocalValue::Dead;
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
@@ -498,7 +498,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
                             match stmt.kind {
                                 StorageLive(local) |
                                 StorageDead(local) => {
-                                    locals[local].state = LocalState::Dead;
+                                    locals[local].state = LocalValue::Dead;
                                 }
                                 _ => {}
                             }
@@ -509,14 +509,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             // Finally, properly initialize all those that still have the dummy value
             for (idx, local) in locals.iter_enumerated_mut() {
                 match local.state {
-                    LocalState::Live(_) => {
+                    LocalValue::Live(_) => {
                         // This needs to be properly initialized.
                         let ty = self.monomorphize(mir.local_decls[idx].ty)?;
                         let layout = self.layout_of(ty)?;
-                        local.state = LocalState::Live(self.uninit_operand(layout)?);
+                        local.state = LocalValue::Live(self.uninit_operand(layout)?);
                         local.layout = Cell::new(Some(layout));
                     }
-                    LocalState::Dead => {
+                    LocalValue::Dead => {
                         // Nothing to do
                     }
                 }
@@ -603,31 +603,31 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
     pub fn storage_live(
         &mut self,
         local: mir::Local
-    ) -> EvalResult<'tcx, LocalState<M::PointerTag>> {
+    ) -> EvalResult<'tcx, LocalValue<M::PointerTag>> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
         let layout = self.layout_of_local(self.frame(), local, None)?;
-        let init = LocalState::Live(self.uninit_operand(layout)?);
+        let init = LocalValue::Live(self.uninit_operand(layout)?);
         // StorageLive *always* kills the value that's currently stored
         Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
     }
 
     /// Returns the old value of the local.
     /// Remember to deallocate that!
-    pub fn storage_dead(&mut self, local: mir::Local) -> LocalState<M::PointerTag> {
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
 
-        mem::replace(&mut self.frame_mut().locals[local].state, LocalState::Dead)
+        mem::replace(&mut self.frame_mut().locals[local].state, LocalValue::Dead)
     }
 
     pub(super) fn deallocate_local(
         &mut self,
-        local: LocalState<M::PointerTag>,
+        local: LocalValue<M::PointerTag>,
     ) -> EvalResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
-        if let LocalState::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
+        if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             trace!("deallocating local");
             let ptr = ptr.to_ptr()?;
             self.memory.dump_alloc(ptr.alloc_id);
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 6ee7d3309f4..d2ab3fcb7a3 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -18,7 +18,7 @@ mod visitor;
 pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
 
 pub use self::eval_context::{
-    EvalContext, Frame, StackPopCleanup, LocalValue, LocalState,
+    EvalContext, Frame, StackPopCleanup, LocalState, LocalValue,
 };
 
 pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index c9fe673c847..c4b56f571db 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -23,8 +23,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use syntax::ast::Mutability;
 use syntax::source_map::Span;
 
-use super::eval_context::{LocalValue, StackPopCleanup};
-use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalState};
+use super::eval_context::{LocalState, StackPopCleanup};
+use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalValue};
 use const_eval::CompileTimeInterpreter;
 
 #[derive(Default)]
@@ -250,11 +250,11 @@ impl_snapshot_for!(enum Operand {
     Indirect(m),
 });
 
-impl_stable_hash_for!(enum ::interpret::LocalState {
+impl_stable_hash_for!(enum ::interpret::LocalValue {
     Dead,
     Live(x),
 });
-impl_snapshot_for!(enum LocalState {
+impl_snapshot_for!(enum LocalValue {
     Live(v),
     Dead,
 });
@@ -309,7 +309,7 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
     span: &'a Span,
     return_to_block: &'a StackPopCleanup,
     return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
-    locals: IndexVec<mir::Local, LocalState<(), AllocIdSnapshot<'a>>>,
+    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
     block: &'a mir::BasicBlock,
     stmt: usize,
 }
@@ -356,17 +356,17 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
     }
 }
 
-impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalValue<'tcx>
+impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx>
     where Ctx: SnapshotContext<'a>,
 {
-    type Item = LocalState<(), AllocIdSnapshot<'a>>;
+    type Item = LocalValue<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
         self.state.snapshot(ctx)
     }
 }
 
-impl_stable_hash_for!(struct LocalValue<'tcx> {
+impl_stable_hash_for!(struct LocalState<'tcx> {
     state,
     layout -> _,
 });

From 4a3caca978042b3d1f6700a5dce757414992a714 Mon Sep 17 00:00:00 2001
From: Rett Berg <rett@google.com>
Date: Wed, 30 Jan 2019 09:14:28 -0800
Subject: [PATCH 20/24] fix #57686: update docs for fix_start/end_matches

---
 src/libcore/str/mod.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index ac920185636..a47ea8d2a46 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3774,10 +3774,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
+    /// A string is a sequence of bytes. `start` in this context means the first
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be left side; and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the right side.
     ///
     /// # Examples
     ///
@@ -3806,10 +3806,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
+    /// A string is a sequence of bytes. `end` in this context means the last
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be right side; and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the left side.
     ///
     /// # Examples
     ///

From 037fdb8213da90f3fe26f78b1e415b86f59b0185 Mon Sep 17 00:00:00 2001
From: Philipp Hansch <dev@phansch.net>
Date: Wed, 30 Jan 2019 07:30:39 +0100
Subject: [PATCH 21/24] Improve bug message in check_ty

This branch was hit in Clippy and I think it would be nice to
show the thing that was unexpected in the bug message.

It's also in line with the other `bug!` messages in `check_ty`.
---
 src/librustc_typeck/collect.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index ade84faae8d..120467cbd13 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1303,12 +1303,12 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             }
         },
 
-        Node::GenericParam(param) => match param.kind {
+        Node::GenericParam(param) => match &param.kind {
             hir::GenericParamKind::Type {
                 default: Some(ref ty),
                 ..
             } => icx.to_ty(ty),
-            _ => bug!("unexpected non-type NodeGenericParam"),
+            x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
         },
 
         x => {

From 8c26c590b4b22066f4ae5ac245dfa7c2e5ae4044 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Wed, 30 Jan 2019 19:29:10 +0100
Subject: [PATCH 22/24] Failure resistent trait implementing

---
 src/librustc_mir/interpret/snapshot.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index c4b56f571db..5fae461bdc2 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -362,7 +362,8 @@ impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx>
     type Item = LocalValue<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
-        self.state.snapshot(ctx)
+        let LocalState { state, layout: _ } = self;
+        state.snapshot(ctx)
     }
 }
 

From 74675fed682d02282419e840b88a501bc0b909e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 30 Jan 2019 11:39:56 -0800
Subject: [PATCH 23/24] Don't panic when accessing enum variant ctor using
 `Self` in match

---
 src/librustc_typeck/check/_match.rs   |  3 ++-
 src/test/ui/issues/issue-58006.rs     | 15 +++++++++++++++
 src/test/ui/issues/issue-58006.stderr |  9 +++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/issues/issue-58006.rs
 create mode 100644 src/test/ui/issues/issue-58006.stderr

diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 141b8222b1f..4203c71a00a 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -784,7 +784,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
                 return tcx.types.err;
             }
-            Def::VariantCtor(_, CtorKind::Fictive) => {
+            Def::VariantCtor(_, CtorKind::Fictive) |
+            Def::VariantCtor(_, CtorKind::Fn) => {
                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
                 return tcx.types.err;
             }
diff --git a/src/test/ui/issues/issue-58006.rs b/src/test/ui/issues/issue-58006.rs
new file mode 100644
index 00000000000..1fb5fefa759
--- /dev/null
+++ b/src/test/ui/issues/issue-58006.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_enum_variants)]
+pub enum Enum {
+    A(usize),
+}
+
+impl Enum {
+    fn foo(&self) -> () {
+        match self {
+            Self::A => (),
+            //~^ ERROR expected unit struct/variant or constant, found tuple variant
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58006.stderr b/src/test/ui/issues/issue-58006.stderr
new file mode 100644
index 00000000000..c65e3e2777f
--- /dev/null
+++ b/src/test/ui/issues/issue-58006.stderr
@@ -0,0 +1,9 @@
+error[E0533]: expected unit struct/variant or constant, found tuple variant `<Self>::A`
+  --> $DIR/issue-58006.rs:9:13
+   |
+LL |             Self::A => (),
+   |             ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0533`.

From 6fe370c7ceef08dbbaed6a502b0dde0ee0614db9 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Wed, 30 Jan 2019 19:49:31 +0000
Subject: [PATCH 24/24] Pass correct arguments to places_conflict

The borrow place *must* be a place that we track borrows for, otherwise
we will likely ICE.
---
 src/librustc_mir/dataflow/impls/borrows.rs |  2 +-
 src/test/ui/nll/issue-57989.rs             | 12 +++++++++++
 src/test/ui/nll/issue-57989.stderr         | 24 ++++++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/nll/issue-57989.rs
 create mode 100644 src/test/ui/nll/issue-57989.stderr

diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 0ceff4aa048..72218e29cfd 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -215,8 +215,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             if places_conflict::places_conflict(
                 self.tcx,
                 self.mir,
-                place,
                 &borrow_data.borrowed_place,
+                place,
                 places_conflict::PlaceConflictBias::NoOverlap,
             ) {
                 debug!(
diff --git a/src/test/ui/nll/issue-57989.rs b/src/test/ui/nll/issue-57989.rs
new file mode 100644
index 00000000000..4f21cca97cc
--- /dev/null
+++ b/src/test/ui/nll/issue-57989.rs
@@ -0,0 +1,12 @@
+// Test for ICE from issue 57989
+
+#![feature(nll)]
+
+fn f(x: &i32) {
+    let g = &x;
+    *x = 0;     //~ ERROR cannot assign to `*x` which is behind a `&` reference
+                //~| ERROR cannot assign to `*x` because it is borrowed
+    g;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-57989.stderr b/src/test/ui/nll/issue-57989.stderr
new file mode 100644
index 00000000000..4561c99096f
--- /dev/null
+++ b/src/test/ui/nll/issue-57989.stderr
@@ -0,0 +1,24 @@
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/issue-57989.rs:7:5
+   |
+LL | fn f(x: &i32) {
+   |         ---- help: consider changing this to be a mutable reference: `&mut i32`
+LL |     let g = &x;
+LL |     *x = 0;     //~ ERROR cannot assign to `*x` which is behind a `&` reference
+   |     ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0506]: cannot assign to `*x` because it is borrowed
+  --> $DIR/issue-57989.rs:7:5
+   |
+LL |     let g = &x;
+   |             -- borrow of `*x` occurs here
+LL |     *x = 0;     //~ ERROR cannot assign to `*x` which is behind a `&` reference
+   |     ^^^^^^ assignment to borrowed `*x` occurs here
+LL |                 //~| ERROR cannot assign to `*x` because it is borrowed
+LL |     g;
+   |     - borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0506, E0594.
+For more information about an error, try `rustc --explain E0506`.