From 809a1a86e04d03619642ab9074b9c95a24cbf82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= 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 689d456d41246..a8b8b44413e13 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" 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 --- 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 a8b8b44413e13..9e724f117ff6e 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?= 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 9e724f117ff6e..e58320ebf569e 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 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 98d2fb1e2d039..c41df3209c8ff 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 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 d3a55c59ff69c..456f7cd5e2ff1 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -435,6 +435,27 @@ impl Rc { } } + /// Consumes the `Rc`, returning the wrapped pointer as `NonNull`. + /// + /// # 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 { + // 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 390a079165054..5cffa93db11d4 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -413,6 +413,27 @@ impl Arc { } } + /// Consumes the `Arc`, returning the wrapped pointer as `NonNull`. + /// + /// # 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 { + // 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 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 ac7f95d4eae80..9b46c2180d9a2 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 5ace7fb3368b6..d23fa9a9ec6f9 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 { @@ -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 { - self.init().write(buf) + fn write(&mut self, src: &[u8]) -> io::Result { + 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 58903761ebe40..4e889c172ef38 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 7f8550490a199..f2593c35bed14 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 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 55897e5a3e906..7bd1854d86f40 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -71,6 +71,10 @@ accomplishing various tasks. +## 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_ 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 65572102c5981..514b2952c5036 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 9df881e8e26d9..8099c3c0584fc 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, Vec) = genomes.iter().cloned() - | -----^---- help: try adding parentheses: `(women, men)` + | ^ +help: try adding parentheses to match on a tuple.. + | +LL | let (women, men): (Vec, Vec) = genomes.iter().cloned() + | ^^^^^^^^^^^^ +help: ..or a vertical bar to match on multiple alternatives + | +LL | let women | men: (Vec, Vec) = genomes.iter().cloned() + | ^^^^^^^^^^^ error: aborting due to 6 previous errors From 7cfb05fd23b5ecc6a13f4629844ff81ac758497c Mon Sep 17 00:00:00 2001 From: Oliver Scherer 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 34443bb353e0e..d2cabde986345 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`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>, - pub local_layouts: IndexVec>>>, + pub locals: IndexVec>, //////////////////////////////////////////////////////////////////////////////// // 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, + /// Don't modify if `Some`, this is only used to prevent computing the layout twice + pub layout: Cell>>, +} + +/// State of a local variable #[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub enum LocalValue { +pub enum LocalState { 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 { Live(Operand), } -impl<'tcx, Tag> LocalValue { +impl<'tcx, Tag> LocalValue<'tcx, Tag> { pub fn access(&self) -> EvalResult<'tcx, &Operand> { - 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> { - 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> { + ) -> EvalResult<'tcx, LocalState> { 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 { + pub fn storage_dead(&mut self, local: mir::Local) -> LocalState { 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, + local: LocalState, ) -> 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 e3ab90a602040..6ee7d3309f464 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 53105266b3928..0b5dc9446921a 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>>, - locals: IndexVec>>, + locals: IndexVec>>, 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> for LocalValue<'gcx> { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { + 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 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 d2cabde986345..d890e2fbe46da 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>, ) -> 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 e4bee24c88cfa..a7e92d5679409 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>, 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>, ) -> 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>, ) -> 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 f3a948a6ca3e7..ffb8ec899a07d 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 951e9fabe5932..7e823524c180c 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::>() ); @@ -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 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 a7e92d5679409..37e421c2e7339 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 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 d890e2fbe46da..bb4f5c131d628 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 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 ffb8ec899a07d..ba1960300a85c 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 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 bb4f5c131d628..3382288b99a25 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 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 3382288b99a25..4bf84cb465f77 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 ba1960300a85c..9ca7f9d8e27ff 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 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 4bf84cb465f77..4e66d21214b29 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>, ) -> 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> { From a3f0af2e672055cddef1e87b56caff763322e6d9 Mon Sep 17 00:00:00 2001 From: Jethro Beekman 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 e2d0e558d3b78..b46e6ef84b98b 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 ade84faae8dbd..393f3066c62e3 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 2820924824697..9dd17b420aa44 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 30fb534dbb591..84300301b7629 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 8dfb4f65f98c4..24141d0064fb0 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 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 0b5dc9446921a..c9fe673c847d1 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> for LocalValue<'gcx> { - fn hash_stable( - &self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher, - ) { - 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 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 4ac84bcfd1903..1328a1aeeab96 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 4e66d21214b29..1b976d822ebff 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`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>, + pub locals: IndexVec>, //////////////////////////////////////////////////////////////////////////////// // 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, +pub struct LocalState<'tcx, Tag=(), Id=AllocId> { + pub state: LocalValue, /// Don't modify if `Some`, this is only used to prevent computing the layout twice pub layout: Cell>>, } /// State of a local variable #[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub enum LocalState { +pub enum LocalValue { 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 { Live(Operand), } -impl<'tcx, Tag> LocalValue<'tcx, Tag> { +impl<'tcx, Tag> LocalState<'tcx, Tag> { pub fn access(&self) -> EvalResult<'tcx, &Operand> { 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> { 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> { + ) -> EvalResult<'tcx, LocalValue> { 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 { + pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue { 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, + local: LocalValue, ) -> 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 6ee7d3309f464..d2ab3fcb7a30a 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 c9fe673c847d1..c4b56f571db9c 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>>, - locals: IndexVec>>, + locals: IndexVec>>, 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 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 ac92018563654..a47ea8d2a4609 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 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 ade84faae8dbd..120467cbd13a0 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 ¶m.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 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 c4b56f571db9c..5fae461bdc203 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?= 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 141b8222b1f33..4203c71a00a41 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 0000000000000..1fb5fefa7596d --- /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 0000000000000..c65e3e2777fae --- /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 `::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 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 0ceff4aa04898..72218e29cfd20 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 0000000000000..4f21cca97cc09 --- /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 0000000000000..4561c99096f14 --- /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`.