From 1bdd6cad02470c268a8af21fbb07443e9d5647ac Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 15 Dec 2018 12:53:41 +0800 Subject: [PATCH 01/32] retrieve ty info from place_ty --- .../borrow_check/error_reporting.rs | 74 +++++++------------ 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 598c2f810beb7..2d790c2a361ce 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -191,38 +191,36 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - if let Some(ty) = self.retrieve_type_for_place(used_place) { - let needs_note = match ty.sty { - ty::Closure(id, _) => { - let tables = self.infcx.tcx.typeck_tables_of(id); - let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); - let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - - tables.closure_kind_origins().get(hir_id).is_none() - } - _ => true, - }; + let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let needs_note = match ty.sty { + ty::Closure(id, _) => { + let tables = self.infcx.tcx.typeck_tables_of(id); + let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); + let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - if needs_note { - let mpi = self.move_data.moves[move_out_indices[0]].path; - let place = &self.move_data.move_paths[mpi].place; - - if let Some(ty) = self.retrieve_type_for_place(place) { - let note_msg = match self.describe_place_with_options( - place, - IncludingDowncast(true), - ) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); - } + tables.closure_kind_origins().get(hir_id).is_none() } + _ => true, + }; + + if needs_note { + let mpi = self.move_data.moves[move_out_indices[0]].path; + let place = &self.move_data.move_paths[mpi].place; + + let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let note_msg = match self.describe_place_with_options( + place, + IncludingDowncast(true), + ) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); } if let Some((_, mut old_err)) = self.move_error_reported @@ -1673,22 +1671,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - /// Retrieve type of a place for the current MIR representation - fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { - match place { - Place::Local(local) => { - let local = &self.mir.local_decls[*local]; - Some(local.ty) - } - Place::Promoted(ref prom) => Some(prom.1), - Place::Static(ref st) => Some(st.ty), - Place::Projection(ref proj) => match proj.elem { - ProjectionElem::Field(_, ty) => Some(ty), - _ => None, - }, - } - } - /// Check if a place is a thread-local static. pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool { if let Place::Static(statik) = place { From 7f9883d79e517741dd3531688d026b1fa4a2a0ad Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Dec 2018 02:34:10 -0800 Subject: [PATCH 02/32] Add unstable VecDeque::rotate_{left|right} --- src/liballoc/collections/vec_deque.rs | 102 ++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 0c5926fbaf1dc..954a1c8becf15 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1927,6 +1927,108 @@ impl VecDeque { self.truncate(new_len); } } + + /// Rotates the double-ended queue `mid` places to the left. + /// + /// Equivalently, + /// - Rotates item `mid` into the first position. + /// - Pops the first `mid` items and pushes them to the end. + /// - Rotates `len() - mid` places to the right. + /// + /// # Panics + /// + /// If `mid` is greater than `len()`. Note that `mid == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `O(min(mid, len() - mid))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_rotate)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_left(3); + /// assert_eq!(buf, [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]); + /// + /// for i in 1..10 { + /// assert_eq!(i * 3 % 10, buf[0]); + /// buf.rotate_left(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[unstable(feature = "vecdeque_rotate", issue = "56686")] + pub fn rotate_left(&mut self, mid: usize) { + assert!(mid <= self.len()); + let k = self.len() - mid; + if mid <= k { + unsafe { self.rotate_left_inner(mid) } + } else { + unsafe { self.rotate_right_inner(k) } + } + } + + /// Rotates the double-ended queue `k` places to the right. + /// + /// Equivalently, + /// - Rotates the first item into position `k`. + /// - Pops the last `k` items and pushes them to the front. + /// - Rotates `len() - k` places to the left. + /// + /// # Panics + /// + /// If `k` is greater than `len()`. Note that `k == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `O(min(k, len() - k))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_rotate)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_right(3); + /// assert_eq!(buf, [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]); + /// + /// for i in 1..10 { + /// assert_eq!(0, buf[i * 3 % 10]); + /// buf.rotate_right(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[unstable(feature = "vecdeque_rotate", issue = "56686")] + pub fn rotate_right(&mut self, k: usize) { + assert!(k <= self.len()); + let mid = self.len() - k; + if k <= mid { + unsafe { self.rotate_right_inner(k) } + } else { + unsafe { self.rotate_left_inner(mid) } + } + } + + unsafe fn rotate_left_inner(&mut self, mid: usize) { + self.wrap_copy(self.head, self.tail, mid); + self.head = self.wrap_add(self.head, mid); + self.tail = self.wrap_add(self.tail, mid); + } + + unsafe fn rotate_right_inner(&mut self, k: usize) { + self.head = self.wrap_sub(self.head, k); + self.tail = self.wrap_sub(self.tail, k); + self.wrap_copy(self.tail, self.head, k); + } } impl VecDeque { From 9ca2902a69711f32f13e0595784422398f81eac4 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 15 Dec 2018 19:00:04 +0800 Subject: [PATCH 03/32] update test --- .../ui/borrowck/borrowck-move-out-from-array.mir.stderr | 4 ++++ src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr | 4 ++++ .../issues/issue-27282-move-match-input-into-guard.stderr | 2 ++ src/test/ui/use/use-after-move-self.rs | 3 ++- src/test/ui/use/use-after-move-self.stderr | 6 +++--- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr index d67b63b5aa71a..d19c23dce5f5f 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr @@ -5,6 +5,8 @@ LL | let [_, _x] = a; | -- value moved here LL | let [.., _y] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array.rs:27:10 @@ -13,6 +15,8 @@ LL | let [_x, _] = a; | -- value moved here LL | let [_y..] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr index a272d2cf019a7..564783d3492f0 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr @@ -14,6 +14,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:86:11 @@ -43,6 +45,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> $DIR/two-phase-nonrecv-autoref.rs:139:27 diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr index 5f3b07bd1e8b8..fa05e85c464b0 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr @@ -8,6 +8,8 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); LL | false } => { }, LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move + | + = note: move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self.rs b/src/test/ui/use/use-after-move-self.rs index e9ffb26aba5b7..d762c74283229 100644 --- a/src/test/ui/use/use-after-move-self.rs +++ b/src/test/ui/use/use-after-move-self.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//compile-flags: -Z borrowck=mir #![feature(box_syntax)] struct S { @@ -17,7 +18,7 @@ struct S { impl S { pub fn foo(self) -> isize { self.bar(); - return *self.x; //~ ERROR use of moved value: `*self.x` + return *self.x; //~ ERROR use of moved value: `self` } pub fn bar(self) {} diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr index 7273602aadc4b..1902dd9c06ce7 100644 --- a/src/test/ui/use/use-after-move-self.stderr +++ b/src/test/ui/use/use-after-move-self.stderr @@ -1,9 +1,9 @@ -error[E0382]: use of moved value: `*self.x` - --> $DIR/use-after-move-self.rs:20:16 +error[E0382]: use of moved value: `self` + --> $DIR/use-after-move-self.rs:21:16 | LL | self.bar(); | ---- value moved here -LL | return *self.x; //~ ERROR use of moved value: `*self.x` +LL | return *self.x; //~ ERROR use of moved value: `self` | ^^^^^^^ value used here after move | = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait From c4fa1d2c4739acf03a0df991d1c28f725c2ba20f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 15 Dec 2018 23:45:37 +0200 Subject: [PATCH 04/32] stop treating trait objects from #[fundamental] traits as fundamental Fixes #56503. --- src/librustc/traits/coherence.rs | 7 +++---- .../auxiliary/coherence_fundamental_trait_lib.rs | 7 +++++++ .../coherence-fundamental-trait-objects.rs | 15 +++++++++++++++ .../coherence-fundamental-trait-objects.stderr | 12 ++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs create mode 100644 src/test/ui/coherence/coherence-fundamental-trait-objects.rs create mode 100644 src/test/ui/coherence/coherence-fundamental-trait-objects.stderr diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index f10f523e2b487..0f8bc8518f2fe 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -393,7 +393,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec> { if ty_is_local_constructor(ty, in_crate) { vec![] - } else if fundamental_ty(tcx, ty) { + } else if fundamental_ty(ty) { ty.walk_shallow() .flat_map(|t| uncovered_tys(tcx, t, in_crate)) .collect() @@ -411,14 +411,13 @@ fn is_possibly_remote_type(ty: Ty<'_>, _in_crate: InCrate) -> bool { fn ty_is_local(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>, in_crate: InCrate) -> bool { ty_is_local_constructor(ty, in_crate) || - fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) + fundamental_ty(ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) } -fn fundamental_ty(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool { +fn fundamental_ty(ty: Ty<'_>) -> bool { match ty.sty { ty::Ref(..) => true, ty::Adt(def, _) => def.is_fundamental(), - ty::Dynamic(ref data, ..) => tcx.has_attr(data.principal().def_id(), "fundamental"), _ => false } } diff --git a/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs new file mode 100644 index 0000000000000..21aaea479631c --- /dev/null +++ b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] +#![feature(fundamental)] + +pub trait Misc {} + +#[fundamental] +pub trait Fundamental {} diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.rs b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs new file mode 100644 index 0000000000000..dd127bf7f4bff --- /dev/null +++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs @@ -0,0 +1,15 @@ +// Check that trait objects from #[fundamental] traits are not +// treated as #[fundamental] types - the 2 meanings of #[fundamental] +// are distinct. + +// aux-build:coherence_fundamental_trait_lib.rs + +extern crate coherence_fundamental_trait_lib; + +use coherence_fundamental_trait_lib::{Fundamental, Misc}; + +pub struct Local; +impl Misc for dyn Fundamental {} +//~^ ERROR E0117 + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr b/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr new file mode 100644 index 0000000000000..cefcac2c51795 --- /dev/null +++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -0,0 +1,12 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-fundamental-trait-objects.rs:12:1 + | +LL | impl Misc for dyn Fundamental {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. From 08155314889e9c9b4cb0e35c117cc4ba93c29388 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Dec 2018 16:33:23 -0800 Subject: [PATCH 05/32] Add a note about why the unsafe is sound --- src/liballoc/collections/vec_deque.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 954a1c8becf15..5171ca254e486 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2018,13 +2018,23 @@ impl VecDeque { } } + // Safety: the following two methods require that the rotation amount + // be less than half the length of the deque. + // + // `wrap_copy` requres that `min(x, cap() - x) + copy_len <= cap()`, + // but than `min` is never more than half the capacity, regardless of x, + // so it's sound to call here because we're calling with something + // less than half the length, which is never above half the capacity. + unsafe fn rotate_left_inner(&mut self, mid: usize) { + debug_assert!(mid * 2 <= self.len()); self.wrap_copy(self.head, self.tail, mid); self.head = self.wrap_add(self.head, mid); self.tail = self.wrap_add(self.tail, mid); } unsafe fn rotate_right_inner(&mut self, k: usize) { + debug_assert!(k * 2 <= self.len()); self.head = self.wrap_sub(self.head, k); self.tail = self.wrap_sub(self.tail, k); self.wrap_copy(self.tail, self.head, k); From bf4a98463d2717ba590492b3161ce0ac926cdd0a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Dec 2018 02:35:39 +0100 Subject: [PATCH 06/32] Reduce search-index.js size --- Cargo.lock | 12 ++++++------ src/librustdoc/Cargo.toml | 2 +- src/librustdoc/html/render.rs | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d22a91073394a..cecaa4fc60e4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1334,7 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "minifier" -version = "0.0.20" +version = "0.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1813,7 +1813,7 @@ name = "rand_chacha" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1835,7 +1835,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1860,7 +1860,7 @@ name = "rand_xorshift" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2682,7 +2682,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3497,7 +3497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474" +"checksum minifier 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "9707d0ff1b828cba09c4bb27d5c3dceb6f49bd46f700042343bea350a131bf4f" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 8bac007b748ac..bc6447d74f1b2 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,6 +9,6 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } -minifier = "0.0.20" +minifier = "0.0.21" tempfile = "3" parking_lot = "0.6.4" diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c9f3aa011a1d4..2ad9292fb8442 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1221,7 +1221,10 @@ fn write_minify_replacer(dst: &mut W, -> io::Result<()> { if enable_minification { writeln!(dst, "{}", - minifier::js::minify_and_replace_keywords(contents, keywords_to_replace)) + minifier::js::minify_and_replace_keywords(contents, keywords_to_replace) + .apply(minifier::js::clean_tokens) + .apply(minifier::js::aggregate_strings) + .to_string()) } else { writeln!(dst, "{}", contents) } From fba23d01d16db8b83b2415bc538d2a850fcf24da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 16 Dec 2018 19:59:42 +0100 Subject: [PATCH 07/32] Disable field reordering for repr(int). --- src/librustc/ty/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a1fc949137dde..634df0194b08f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2059,9 +2059,10 @@ impl ReprOptions { } /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with repr(C) or repr(packed(1)). + /// optimizations, such as with repr(C), repr(packed(1)), or repr(). pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1) + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 || + self.int.is_some() } /// Returns true if this `#[repr()]` should inhibit union abi optimisations From d84bdba72888a42a67c1771b0a62f8517c8964cb Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 7 Dec 2018 19:54:16 -0500 Subject: [PATCH 08/32] Add test to check order of repr(int) enum fields RFC #2195 specifies that a repr(int) enum such as: #[repr(u8)] enum MyEnum { B { x: u8, y: i16, z: u8 }, } has a layout that is equivalent to: #[repr(C)] enum MyEnumVariantB { tag: u8, x: u8, y: i16, z: u8 }, However this isn't actually implemented, with the actual layout being roughly equivalent to: union MyEnumPayload { B { x: u8, y: i16, z: u8 }, } #[repr(packed)] struct MyEnum { tag: u8, payload: MyEnumPayload, } Thus the variant payload is *not* subject to repr(C) ordering rules, and gets re-ordered as `{ x: u8, z: u8, z: i16 }` The existing tests added in pull-req #45688 fail to catch this as the repr(C) ordering just happens to match the current Rust ordering in this case; adding a third field reveals the problem. --- .../enum-non-c-like-repr-c-and-int.rs | 18 ++++++++++-------- .../structs-enums/enum-non-c-like-repr-c.rs | 18 ++++++++++-------- .../structs-enums/enum-non-c-like-repr-int.rs | 18 ++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs index 14eac687ecf96..f59f100653fbb 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(C, u8)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offsets of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[repr(C)] @@ -44,14 +45,14 @@ union MyEnumPayload { #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -63,7 +64,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.payload.B.x = read_u8(buf)?; dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs index 80c4339af9d6f..e88b91ab6c3f1 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[repr(C)] @@ -44,14 +45,14 @@ union MyEnumPayload { #[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -63,7 +64,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.payload.B.x = read_u8(buf)?; dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs index 4c1fe8db1cda5..d862c0c72c2d8 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[allow(non_snake_case)] @@ -39,7 +40,7 @@ union MyEnumRepr { #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration); @@ -47,7 +48,7 @@ union MyEnumRepr { fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -59,7 +60,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -108,6 +109,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.B.x = read_u8(buf)?; dest.B.y = read_u16_le(buf)? as i16; + dest.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ From bbce189046fa84c1fb3d310920ab6bd536562a47 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Dec 2018 12:11:19 -0800 Subject: [PATCH 09/32] rustc: Update Clang used to build LLVM on LInux This commit updates from LLVM 7.0.0 to git revisions of clang/llvm/lld to build LLVM on our dist builders for Linux. The goal of this is to fix #56849 by picking up a fix [1] in LLD. Closes #56849 [1]: https://github.com/llvm-mirror/lld/commit/3be4e82db78b46a8ca349b2b799dec620a6f159f --- .../docker/dist-x86_64-linux/build-clang.sh | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/ci/docker/dist-x86_64-linux/build-clang.sh b/src/ci/docker/dist-x86_64-linux/build-clang.sh index 2762f0bf7ec74..a7a8719b5357e 100755 --- a/src/ci/docker/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/dist-x86_64-linux/build-clang.sh @@ -13,31 +13,28 @@ set -ex source shared.sh -LLVM=7.0.0 +# Currently these commits are all tip-of-tree as of 2018-12-16, used to pick up +# a fix for rust-lang/rust#56849 +LLVM=032b00a5404865765cda7db3039f39d54964d8b0 +LLD=3e4aa4e8671523321af51449e0569f455ef3ad43 +CLANG=a6b9739069763243020f4ea6fe586bc135fde1f9 mkdir clang cd clang -curl https://releases.llvm.org/$LLVM/llvm-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - - -cd llvm-$LLVM.src +curl -L https://github.com/llvm-mirror/llvm/archive/$LLVM.tar.gz | \ + tar xzf - --strip-components=1 mkdir -p tools/clang - -curl https://releases.llvm.org/$LLVM/cfe-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - -C tools/clang --strip-components=1 +curl -L https://github.com/llvm-mirror/clang/archive/$CLANG.tar.gz | \ + tar xzf - --strip-components=1 -C tools/clang mkdir -p tools/lld +curl -L https://github.com/llvm-mirror/lld/archive/$LLD.tar.gz | \ + tar zxf - --strip-components=1 -C tools/lld -curl https://releases.llvm.org/$LLVM/lld-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - -C tools/lld --strip-components=1 - -mkdir ../clang-build -cd ../clang-build +mkdir clang-build +cd clang-build # For whatever reason the default set of include paths for clang is different # than that of gcc. As a result we need to manually include our sysroot's @@ -55,7 +52,7 @@ INC="$INC:/rustroot/lib/gcc/x86_64-unknown-linux-gnu/4.8.5/include-fixed" INC="$INC:/usr/include" hide_output \ - cmake ../llvm-$LLVM.src \ + cmake .. \ -DCMAKE_C_COMPILER=/rustroot/bin/gcc \ -DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \ -DCMAKE_BUILD_TYPE=Release \ From a2b6401b5abd15f118b9ed86189639198a2a4928 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Sun, 16 Dec 2018 17:01:57 -0800 Subject: [PATCH 10/32] Issue 56905 Adding a map to TypeckTables to get the list of all the Upvars given a closureID. This is help us get rid of the recurring pattern in the codebase of iterating over the free vars using with_freevars. --- src/librustc/ty/context.rs | 10 ++++++++++ src/librustc/ty/mod.rs | 2 ++ src/librustc_typeck/check/upvar.rs | 18 ++++++++++++------ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e27d7349877fc..18378a8b9d39f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -431,6 +431,12 @@ pub struct TypeckTables<'tcx> { /// All the existential types that are restricted to concrete types /// by this function pub concrete_existential_types: FxHashMap>, + + /// Given the closure ID this map provides the list of UpvarIDs used by it. + /// The upvarID contains the HIR node ID and it also contains the full path + /// leading to the member of the struct or tuple that is used instead of the + /// entire variable. + pub upvar_list: ty::UpvarListMap<'tcx>, } impl<'tcx> TypeckTables<'tcx> { @@ -456,6 +462,7 @@ impl<'tcx> TypeckTables<'tcx> { tainted_by_errors: false, free_region_map: Default::default(), concrete_existential_types: Default::default(), + upvar_list: Default::default(), } } @@ -765,6 +772,8 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { tainted_by_errors, ref free_region_map, ref concrete_existential_types, + ref upvar_list, + } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { @@ -808,6 +817,7 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { tainted_by_errors.hash_stable(hcx, hasher); free_region_map.hash_stable(hcx, hasher); concrete_existential_types.hash_stable(hcx, hasher); + upvar_list.hash_stable(hcx, hasher); }) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a1fc949137dde..b48b0ba0e917c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -598,6 +598,8 @@ impl<'a, 'gcx> HashStable> for ty::TyS<'gcx> { pub type Ty<'tcx> = &'tcx TyS<'tcx>; +pub type UpvarListMap<'tcx> = FxHashMap>; + impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 562022cefa806..b5647045fe925 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -132,14 +132,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; self.tcx.with_freevars(closure_node_id, |freevars| { + let mut freevar_list: Vec = Vec::new(); for freevar in freevars { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { - hir_id : self.tcx.hir().node_to_hir_id(freevar.var_id()), + hir_id: self.tcx.hir().node_to_hir_id(freevar.var_id()), }, closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; debug!("seed upvar_id {:?}", upvar_id); + freevar_list.push(upvar_id); let capture_kind = match capture_clause { hir::CaptureByValue => ty::UpvarCapture::ByValue, @@ -159,6 +161,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .upvar_capture_map .insert(upvar_id, capture_kind); } + self.tables + .borrow_mut() + .upvar_list + .insert(closure_def_id, freevar_list); }); let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); @@ -176,7 +182,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.param_env, region_scope_tree, &self.tables.borrow(), - ).consume_body(body); + ) + .consume_body(body); if let Some(closure_substs) = infer_kind { // Unify the (as yet unbound) type variable in the closure @@ -250,9 +257,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let var_hir_id = tcx.hir().node_to_hir_id(var_node_id); let freevar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { - var_path: ty::UpvarPath { - hir_id: var_hir_id, - }, + var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: LocalDefId::from_def_id(closure_def_index), }; let capture = self.tables.borrow().upvar_capture(upvar_id); @@ -272,7 +277,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, ), } - }).collect() + }) + .collect() }) } } From 37c356188147cbdfd36ed8077edcab97e0a6f1cf Mon Sep 17 00:00:00 2001 From: csmoe Date: Mon, 17 Dec 2018 19:41:48 +0800 Subject: [PATCH 11/32] describe index with accurate _ --- src/librustc_mir/borrow_check/error_reporting.rs | 2 +- .../borrowck/borrowck-describe-lvalue.mir.stderr | 2 +- src/test/ui/borrowck/borrowck-describe-lvalue.rs | 2 +- .../borrowck-vec-pattern-move-tail.cmp.stderr | 6 +++--- .../borrowck/borrowck-vec-pattern-move-tail.rs | 2 +- src/test/ui/issues/issue-46604.mir.stderr | 2 +- src/test/ui/nll/drop-no-may-dangle.rs | 4 ++-- src/test/ui/nll/drop-no-may-dangle.stderr | 16 ++++++++-------- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 2d790c2a361ce..9826b4dbe5f86 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1566,7 +1566,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { )?; buf.push_str("["); if self.append_local_to_string(index, buf).is_err() { - buf.push_str(".."); + buf.push_str("_"); } buf.push_str("]"); } diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr index 5721c52ba2172..606c0e0b5c2a3 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr @@ -316,7 +316,7 @@ LL | v[0].y; LL | drop(x); | - borrow later used here -error[E0503]: cannot use `v[..].y` because it was mutably borrowed +error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:271:9 | LL | let x = &mut v; diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index 649de888ab0a2..c73fd27f9ff2a 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -270,7 +270,7 @@ fn main() { let x = &mut v; v[0].y; //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed - //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[_].y` because it was mutably borrowed //[mir]~| ERROR cannot use `*v` because it was mutably borrowed drop(x); } diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr index a6aa9cd6d2a13..6192b1389bef6 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr @@ -7,14 +7,14 @@ LL | [1, 2, ref tail..] => tail, LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed | ^^^^^^^^ assignment to borrowed `a[..]` occurs here -error[E0506]: cannot assign to `a[..]` because it is borrowed (Mir) +error[E0506]: cannot assign to `a[_]` because it is borrowed (Mir) --> $DIR/borrowck-vec-pattern-move-tail.rs:24:5 | LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[..]` occurs here + | -------- borrow of `a[_]` occurs here ... LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed - | ^^^^^^^^ assignment to borrowed `a[..]` occurs here + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here ... LL | println!("t[0]: {}", t[0]); | ---- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs index 94877b27d5888..48b5af01705ae 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -23,7 +23,7 @@ fn main() { println!("t[0]: {}", t[0]); a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast) - //[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir) + //[cmp]~| ERROR cannot assign to `a[_]` because it is borrowed (Mir) println!("t[0]: {}", t[0]); t[0]; } diff --git a/src/test/ui/issues/issue-46604.mir.stderr b/src/test/ui/issues/issue-46604.mir.stderr index a4ee0d4e2a3a9..3ad0f256ed7e1 100644 --- a/src/test/ui/issues/issue-46604.mir.stderr +++ b/src/test/ui/issues/issue-46604.mir.stderr @@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017 | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:20:5 | LL | buf[0]=2; //[ast]~ ERROR E0389 diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index 513609316311a..fce4ad904f137 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -27,10 +27,10 @@ fn main() { use_x(*p.value); } else { use_x(22); - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } struct WrapMayNotDangle { diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr index 60862d0f22952..0c1d0b29d2c8b 100644 --- a/src/test/ui/nll/drop-no-may-dangle.stderr +++ b/src/test/ui/nll/drop-no-may-dangle.stderr @@ -1,23 +1,23 @@ -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:30:9 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here ... LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:33:5 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` From b31a1f74efd17521e11fee4685f7e27f9b9d192c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:20:42 +0100 Subject: [PATCH 12/32] Fix a recently introduces regression --- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../consts/static_mut_containing_mut_ref.rs | 7 +++++++ .../consts/static_mut_containing_mut_ref2.rs | 8 ++++++++ .../static_mut_containing_mut_ref2.stderr | 9 +++++++++ src/test/ui/write-to-static-mut-in-static.rs | 4 ++-- .../ui/write-to-static-mut-in-static.stderr | 20 ++++++++++++++++--- 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 5f08dee872859..f998bf1b1251e 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -518,7 +518,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { - if context.is_mutating_use() { + if self.mode == Mode::Static && context.is_mutating_use() { // this is not strictly necessary as miri will also bail out // For interior mutability we can't really catch this statically as that // goes through raw pointers and intermediate temporaries, so miri has diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs new file mode 100644 index 0000000000000..27e1a111163b1 --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs @@ -0,0 +1,7 @@ +// compile-pass + +static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; + +pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE }; + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs new file mode 100644 index 0000000000000..aa9bfb4aeab2d --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut STDERR_BUFFER_SPACE: u8 = 0; + +pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; +//~^ references in statics may only refer to immutable values + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr new file mode 100644 index 0000000000000..72923431c90ed --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -0,0 +1,9 @@ +error[E0017]: references in statics may only refer to immutable values + --> $DIR/static_mut_containing_mut_ref2.rs:5:46 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs index 191f09b54ee73..983b5d48e60fc 100644 --- a/src/test/ui/write-to-static-mut-in-static.rs +++ b/src/test/ui/write-to-static-mut-in-static.rs @@ -12,10 +12,10 @@ pub static mut A: u32 = 0; pub static mut B: () = unsafe { A = 1; }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR could not evaluate static initializer pub static mut C: u32 = unsafe { C = 1; 0 }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR cycle detected pub static D: u32 = D; diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index 673a71b4642f3..335f849fb2472 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -1,14 +1,28 @@ -error: cannot mutate statics in the initializer of another static +error[E0080]: could not evaluate static initializer --> $DIR/write-to-static-mut-in-static.rs:14:33 | LL | pub static mut B: () = unsafe { A = 1; }; - | ^^^^^ + | ^^^^^ tried to modify a static's initial value from another static's initializer -error: cannot mutate statics in the initializer of another static +error[E0391]: cycle detected when const-evaluating `C` --> $DIR/write-to-static-mut-in-static.rs:17:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ + | +note: ...which requires const-evaluating `C`... + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `C`, completing the cycle +note: cycle used when const-evaluating + checking `C` + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors +Some errors occurred: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. From 7e2e4892e27674e8a416602009cb91b5ca3682ce Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:36:10 +0100 Subject: [PATCH 13/32] Also test projections --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 2 +- src/test/ui/consts/static_mut_containing_mut_ref3.rs | 8 ++++++++ src/test/ui/consts/static_mut_containing_mut_ref3.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.stderr diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aa9bfb4aeab2d..aeb69b2652cbf 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -3,6 +3,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; -//~^ references in statics may only refer to immutable values +//~^ ERROR references in statics may only refer to immutable values fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.rs b/src/test/ui/consts/static_mut_containing_mut_ref3.rs new file mode 100644 index 0000000000000..0bc7faa9afdec --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut FOO: (u8, u8) = (42, 43); + +static mut BAR: () = unsafe { FOO.0 = 99; }; +//~^ ERROR could not evaluate static initializer + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr new file mode 100644 index 0000000000000..cae53c6fee9dd --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref3.rs:5:31 + | +LL | static mut BAR: () = unsafe { FOO.0 = 99; }; + | ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 3e7a4ca2f1d576a4a23e8c541cb5c0c420b108de Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 16:47:26 +0100 Subject: [PATCH 14/32] Remove a wrong multiplier on relocation offset computation --- src/librustc_mir/interpret/memory.rs | 8 ++++---- src/test/ui/consts/promoted_regression.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/consts/promoted_regression.rs diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 420fe26426321..65347a02be0c7 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| { - (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), - reloc) - }) + .map(|&(offset, reloc)| ( + offset + dest.offset - src.offset + (i * size), + reloc, + )) ); } diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs new file mode 100644 index 0000000000000..68b9a20ecf90b --- /dev/null +++ b/src/test/ui/consts/promoted_regression.rs @@ -0,0 +1,9 @@ +// compile-pass + +fn main() { + let _ = &[("", ""); 3]; +} + +const FOO: &[(&str, &str)] = &[("", ""); 3]; +const BAR: &[(&str, &str); 5] = &[("", ""); 5]; +const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11]; From e7e17f9d1b008a1f06ad8b4ef06c443b4b879bc4 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Mon, 17 Dec 2018 03:17:59 +0000 Subject: [PATCH 15/32] static eval: Do not ICE on layout size overflow Layout size overflow and typeck eval errors are reported. Trigger a bug only when the eval error is strictly labeled as TooGeneric. --- src/librustc_mir/const_eval.rs | 12 ++++++++---- src/test/ui/issues/issue-56762.rs | 18 ++++++++++++++++++ src/test/ui/issues/issue-56762.stderr | 4 ++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/issues/issue-56762.rs create mode 100644 src/test/ui/issues/issue-56762.stderr diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 248c5d2db4917..d5bc83aba7b99 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -692,12 +692,16 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let err = error_to_const_error(&ecx, error); // errors in statics are always emitted as fatal errors if tcx.is_static(def_id).is_some() { - let err = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); - // check that a static never produces `TooGeneric` + let reported_err = err.report_as_error(ecx.tcx, + "could not evaluate static initializer"); + // Ensure that if the above error was either `TooGeneric` or `Reported` + // an error must be reported. if tcx.sess.err_count() == 0 { - span_bug!(ecx.tcx.span, "static eval failure didn't emit an error: {:#?}", err); + tcx.sess.delay_span_bug(err.span, + &format!("static eval failure did not emit an error: {:#?}", + reported_err)); } - err + reported_err } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! match tcx.describe_def(def_id) { diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs new file mode 100644 index 0000000000000..97b66b2c7c923 --- /dev/null +++ b/src/test/ui/issues/issue-56762.rs @@ -0,0 +1,18 @@ +// only-x86_64 +const HUGE_SIZE: usize = !0usize / 8; + + +pub struct TooBigArray { + arr: [u8; HUGE_SIZE], +} + +impl TooBigArray { + pub const fn new() -> Self { + TooBigArray { arr: [0x00; HUGE_SIZE], } + } +} + +static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); +static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; + +fn main() { } diff --git a/src/test/ui/issues/issue-56762.stderr b/src/test/ui/issues/issue-56762.stderr new file mode 100644 index 0000000000000..83d5dc62e6161 --- /dev/null +++ b/src/test/ui/issues/issue-56762.stderr @@ -0,0 +1,4 @@ +error: the type `[u8; 2305843009213693951]` is too big for the current architecture + +error: aborting due to previous error + From 6130fc884bc1dff9bb835894a7bb2042c110b011 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Mon, 17 Dec 2018 17:16:39 -0500 Subject: [PATCH 16/32] Add --progress to git submodule commands --- src/bootstrap/bootstrap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d143dffb24be5..09c87fdd1a84c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -678,10 +678,10 @@ def update_submodule(self, module, checked_out, recorded_submodules): print("Updating submodule", module) - run(["git", "submodule", "-q", "sync", module], + run(["git", "submodule", "-q", "sync", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "update", - "--init", "--recursive", module], + "--init", "--recursive", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "reset", "-q", "--hard"], cwd=module_path, verbose=self.verbose) From 50eb5f6137719a7e8fdd270e90af0d734d002c5d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 18 Dec 2018 10:08:37 +0100 Subject: [PATCH 17/32] Explain the math --- src/librustc_mir/interpret/memory.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 65347a02be0c7..77a5f5d7b3a84 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| ( - offset + dest.offset - src.offset + (i * size), - reloc, - )) + .map(|&(offset, reloc)| { + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) + }) ); } From 170f068103dca16eb1fe169e67d27c532ec34e50 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 24 Oct 2018 23:34:54 +0200 Subject: [PATCH 18/32] Don't render const keyword on stable --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/test/rustdoc/const-display.rs | 43 +++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc/const-display.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 217345548c8c9..4bd3c6a84556d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -207,7 +207,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { let sig = cx.tcx.fn_sig(did); - let constness = if cx.tcx.is_const_fn(did) { + let constness = if cx.tcx.is_min_const_fn(did) { hir::Constness::Const } else { hir::Constness::NotConst diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e33ec8c37661..f08b594a8e490 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2009,7 +2009,7 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::TraitContainer(_) => self.defaultness.has_value() }; if provided { - let constness = if cx.tcx.is_const_fn(self.def_id) { + let constness = if cx.tcx.is_min_const_fn(self.def_id) { hir::Constness::Const } else { hir::Constness::NotConst diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs new file mode 100644 index 0000000000000..0b72719091380 --- /dev/null +++ b/src/test/rustdoc/const-display.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +#![unstable(feature = "humans", + reason = "who ever let humans program computers, we're apparently really bad at it", + issue = "0")] + +#![feature(rustc_const_unstable, const_fn, foo, foo2)] +#![feature(min_const_unsafe_fn)] +#![feature(staged_api)] + +// @has 'foo/fn.foo.html' '//pre' 'pub const unsafe fn foo() -> u32' +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo")] +pub const unsafe fn foo() -> u32 { 42 } + +// @has 'foo/fn.foo2.html' '//pre' 'pub const fn foo2() -> u32' +#[unstable(feature = "humans", issue="0")] +pub const fn foo2() -> u32 { 42 } + +// @has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32' +#[stable(feature = "rust1", since = "1.0.0")] +pub const fn bar2() -> u32 { 42 } + +// @has 'foo/fn.foo2_gated.html' '//pre' 'pub const unsafe fn foo2_gated() -> u32' +#[unstable(feature = "foo2", issue="0")] +pub const unsafe fn foo2_gated() -> u32 { 42 } + +// @has 'foo/fn.bar2_gated.html' '//pre' 'pub const unsafe fn bar2_gated() -> u32' +#[stable(feature = "rust1", since = "1.0.0")] +pub const unsafe fn bar2_gated() -> u32 { 42 } + +// @has 'foo/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32' +pub const unsafe fn bar_not_gated() -> u32 { 42 } From 00bd306e0d060fc737d670e9aacd2789d3103785 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 11:32:56 +1000 Subject: [PATCH 19/32] Extend documentation for mem uninit to discuss partial allocation of the values --- src/libcore/mem.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index afd9fcb1fba84..7e4e83999c1a3 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -530,6 +530,12 @@ pub unsafe fn zeroed() -> T { /// it goes out of scope (and therefore would be dropped). Note that this /// includes a `panic` occurring and unwinding the stack suddenly. /// +/// If you partially initialize an array, you may need to use +/// [`ptr::drop_in_place`][drop_in_place] to remove the set you have created +/// followed by [`mem::forget`][mem_forget] to prevent drop running on the +/// array. If a partially allocated array is dropped this may lead to +/// undefined behaviour. +/// /// # Examples /// /// Here's how to safely initialize an array of [`Vec`]s. @@ -583,11 +589,47 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// +/// This example shows how to handle partially allocated arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem; +/// use std::ptr; +/// +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// let mut data: [String; 1000]; +/// +/// unsafe { +/// data = mem::uninitialized(); +/// +/// for elem in &mut data[0..500] { +/// ptr::write(elem, String::from("hello")); +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for i in &mut data[0..data_len] { +/// ptr::drop_in_place(i); +/// } +/// } +/// // Forget the data. If this is allowed to drop, you may see a crash such as: +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object 0x7ff3b8402920: pointer being freed was not allocated' +/// mem::forget(data); +/// ``` +/// +/// An alternate strategy is to use [`mem::zeroed`][mem_zeroed] with ptr +/// comparison. This is a very error prone strategy and may only be relevant +/// for FFI. +/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html /// [ub]: ../../reference/behavior-considered-undefined.html /// [write]: ../ptr/fn.write.html +/// [drop_in_place]: ../ptr/fn.drop_in_place.html +/// [mem_zeroed]: fn.zeroed.html +/// [mem_forget]: fn.forget.html /// [copy]: ../intrinsics/fn.copy.html /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html From 0829d0c0e480a3729dcfe4f28f5969277dc8f646 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 12:40:57 +1000 Subject: [PATCH 20/32] Updates based on comment --- src/libcore/mem.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7e4e83999c1a3..7492cf4c5ed32 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -531,9 +531,9 @@ pub unsafe fn zeroed() -> T { /// includes a `panic` occurring and unwinding the stack suddenly. /// /// If you partially initialize an array, you may need to use -/// [`ptr::drop_in_place`][drop_in_place] to remove the set you have created -/// followed by [`mem::forget`][mem_forget] to prevent drop running on the -/// array. If a partially allocated array is dropped this may lead to +/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully +/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running +/// on the array. If a partially allocated array is dropped this will lead to /// undefined behaviour. /// /// # Examples @@ -589,7 +589,7 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// -/// This example shows how to handle partially allocated arrays, which could +/// This example shows how to handle partially initialized arrays, which could /// be found in low-level datastructures. /// /// ``` @@ -618,10 +618,6 @@ pub unsafe fn zeroed() -> T { /// mem::forget(data); /// ``` /// -/// An alternate strategy is to use [`mem::zeroed`][mem_zeroed] with ptr -/// comparison. This is a very error prone strategy and may only be relevant -/// for FFI. -/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html From d7519544694c1866ba4bf32cd307ed6f670e1267 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Tue, 18 Dec 2018 20:54:35 -0800 Subject: [PATCH 21/32] Creating the vector using with_capacity to avoid re-allocation later on (#56905) --- src/librustc_typeck/check/upvar.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index b5647045fe925..a603eb2575466 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -132,7 +132,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; self.tcx.with_freevars(closure_node_id, |freevars| { - let mut freevar_list: Vec = Vec::new(); + let mut freevar_list: Vec = Vec::with_capacity(freevars.len()); for freevar in freevars { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { @@ -141,6 +141,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; debug!("seed upvar_id {:?}", upvar_id); + // Adding the upvar Id to the list of Upvars, which will be added + // to the map for the closure at the end of the for loop. freevar_list.push(upvar_id); let capture_kind = match capture_clause { @@ -161,6 +163,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .upvar_capture_map .insert(upvar_id, capture_kind); } + // Add the vector of freevars to the map keyed with the closure id. + // This gives us an easier access to them without having to call + // with_freevars again.. self.tables .borrow_mut() .upvar_list From cbe9abb78cd6c1b8c74b78110b8c92c1f0984ba0 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 19 Dec 2018 00:38:15 -0800 Subject: [PATCH 22/32] Add more VecDeque::rotate_{left|right} tests --- src/liballoc/tests/lib.rs | 3 +- src/liballoc/tests/vec_deque.rs | 134 ++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index e514a8a69c020..146abd1b7508a 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -13,11 +13,12 @@ #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(pattern)] +#![feature(repeat_generic_slice)] #![feature(slice_sort_by_cached_key)] #![feature(str_escape)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(repeat_generic_slice)] +#![feature(vecdeque_rotate)] extern crate core; extern crate rand; diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 1f2a7211c657b..c8a6d86413ad6 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1309,3 +1309,137 @@ fn test_try_reserve_exact() { } } + +#[test] +fn test_rotate_nop() { + let mut v: VecDeque<_> = (0..10).collect(); + assert_unchanged(&v); + + v.rotate_left(0); + assert_unchanged(&v); + + v.rotate_left(10); + assert_unchanged(&v); + + v.rotate_right(0); + assert_unchanged(&v); + + v.rotate_right(10); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_right(3); + assert_unchanged(&v); + + v.rotate_right(3); + v.rotate_left(3); + assert_unchanged(&v); + + v.rotate_left(6); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_right(6); + v.rotate_left(6); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_left(7); + assert_unchanged(&v); + + v.rotate_right(4); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_left(1); + v.rotate_left(2); + v.rotate_left(3); + v.rotate_left(4); + assert_unchanged(&v); + + v.rotate_right(1); + v.rotate_right(2); + v.rotate_right(3); + v.rotate_right(4); + assert_unchanged(&v); + + fn assert_unchanged(v: &VecDeque) { + assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + } +} + +#[test] +fn test_rotate_left_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6, 7, 1][..], &[2][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[5, 6, 7, 1][..], &[2, 3, 4][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[7, 1][..], &[2, 3, 4, 5, 6][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7, 1][..], &[][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7, 1, 2][..], &[3][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[6, 7, 1, 2][..], &[3, 4, 5][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[1, 2][..], &[3, 4, 5, 6, 7][..])); +} + +#[test] +fn test_rotate_right_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[6, 7][..], &[1, 2, 3, 4, 5][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7][..], &[1, 2, 3][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7][..], &[1][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[7, 1, 2, 3, 4, 5, 6][..], &[][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[5, 6][..], &[7, 1, 2, 3, 4][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6][..], &[7, 1, 2][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[1, 2, 3, 4, 5, 6][..], &[7][..])); +} + +#[test] +fn test_rotate_left_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, + 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, + 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_left(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[i], (i + total_shift) % n); + } + } +} + +#[test] +fn test_rotate_right_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, + 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, + 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_right(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[(i + total_shift) % n], i); + } + } +} From a6943d9d66d6dc8b7be9db556e28dbc8125f7336 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 Dec 2018 22:24:20 +0100 Subject: [PATCH 23/32] Set constness correctly --- src/librustdoc/clean/mod.rs | 10 ++++++++-- src/test/rustdoc/const-display.rs | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f08b594a8e490..44ea3d1ac2d13 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1674,6 +1674,12 @@ impl Clean for doctree::Function { (self.generics.clean(cx), (&self.decl, self.body).clean(cx)) }); + let did = cx.tcx.hir().local_def_id(self.id); + let constness = if cx.tcx.is_min_const_fn(did) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -1681,11 +1687,11 @@ impl Clean for doctree::Function { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id), + def_id: did, inner: FunctionItem(Function { decl, generics, - header: self.header, + header: hir::FnHeader { constness, ..self.header }, }), } } diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index 0b72719091380..8ac0d07ceefe4 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -18,12 +18,12 @@ #![feature(min_const_unsafe_fn)] #![feature(staged_api)] -// @has 'foo/fn.foo.html' '//pre' 'pub const unsafe fn foo() -> u32' +// @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo")] pub const unsafe fn foo() -> u32 { 42 } -// @has 'foo/fn.foo2.html' '//pre' 'pub const fn foo2() -> u32' +// @has 'foo/fn.foo2.html' '//pre' 'pub fn foo2() -> u32' #[unstable(feature = "humans", issue="0")] pub const fn foo2() -> u32 { 42 } @@ -31,7 +31,7 @@ pub const fn foo2() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] pub const fn bar2() -> u32 { 42 } -// @has 'foo/fn.foo2_gated.html' '//pre' 'pub const unsafe fn foo2_gated() -> u32' +// @has 'foo/fn.foo2_gated.html' '//pre' 'pub unsafe fn foo2_gated() -> u32' #[unstable(feature = "foo2", issue="0")] pub const unsafe fn foo2_gated() -> u32 { 42 } @@ -39,5 +39,5 @@ pub const unsafe fn foo2_gated() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] pub const unsafe fn bar2_gated() -> u32 { 42 } -// @has 'foo/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32' +// @has 'foo/fn.bar_not_gated.html' '//pre' 'pub unsafe fn bar_not_gated() -> u32' pub const unsafe fn bar_not_gated() -> u32 { 42 } From b2d8040e6f89318c0ca7f5512ca31f8311b14a36 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 19:09:54 +1000 Subject: [PATCH 24/32] Fix tidy error --- src/libcore/mem.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7492cf4c5ed32..9d1f5ce403570 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -614,7 +614,8 @@ pub unsafe fn zeroed() -> T { /// } /// } /// // Forget the data. If this is allowed to drop, you may see a crash such as: -/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object 0x7ff3b8402920: pointer being freed was not allocated' +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object +/// // 0x7ff3b8402920: pointer being freed was not allocated' /// mem::forget(data); /// ``` /// From 202904b3f7a7d2563e6808b8d8d530768c949a99 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Dec 2018 10:10:39 +0100 Subject: [PATCH 25/32] make basic CTFE tracing available on release builds --- src/librustc_mir/interpret/eval_context.rs | 8 ++++---- src/librustc_mir/interpret/step.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d36d530fe78b2..8ae0345e07a34 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -422,7 +422,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); + info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation += 1; @@ -491,7 +491,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); + info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); } if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { @@ -503,7 +503,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); + info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect( @@ -557,7 +557,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); + info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); } Ok(()) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index a6835e4f16738..0b3f5b2678c7f 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -81,7 +81,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", stmt); + info!("{:?}", stmt); use rustc::mir::StatementKind::*; @@ -293,7 +293,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", terminator.kind); + info!("{:?}", terminator.kind); self.tcx.span = terminator.source_info.span; self.memory.tcx.span = terminator.source_info.span; @@ -303,7 +303,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if !self.stack.is_empty() { // This should change *something* debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); - debug!("// {:?}", self.frame().block); + info!("// {:?}", self.frame().block); } Ok(()) } From 885cf2a2afd6da270287cfc3bfa651ac737d0378 Mon Sep 17 00:00:00 2001 From: Vardhan Thigle Date: Fri, 14 Dec 2018 18:38:15 +0530 Subject: [PATCH 26/32] Adding unwinding support for x86_64_fortanix_unknown_sgx target. --- src/libpanic_unwind/lib.rs | 2 +- .../spec/x86_64_fortanix_unknown_sgx.rs | 46 +++--- src/libstd/sys/sgx/abi/entry.S | 8 + src/libstd/sys/sgx/rwlock.rs | 137 +++++++++++++++++- src/libunwind/lib.rs | 5 +- 5 files changed, 168 insertions(+), 30 deletions(-) diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 49f8a429126b7..cfe671c626bcf 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -62,7 +62,7 @@ cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] mod imp; - } else if #[cfg(any(target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(target_arch = "wasm32")] { #[path = "dummy.rs"] mod imp; } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index 5b6d8abc5ef3e..6a6aab2bea366 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -10,28 +10,29 @@ use std::iter; -use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy}; +use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Result { const PRE_LINK_ARGS: &[&str] = &[ "-Wl,--as-needed", "-Wl,-z,noexecstack", "-m64", - "-fuse-ld=gold", - "-nostdlib", - "-shared", - "-Wl,-e,sgx_entry", - "-Wl,-Bstatic", - "-Wl,--gc-sections", - "-Wl,-z,text", - "-Wl,-z,norelro", - "-Wl,--rosegment", - "-Wl,--no-undefined", - "-Wl,--error-unresolved-symbols", - "-Wl,--no-undefined-version", - "-Wl,-Bsymbolic", - "-Wl,--export-dynamic", + "-fuse-ld=gold", + "-nostdlib", + "-shared", + "-Wl,-e,sgx_entry", + "-Wl,-Bstatic", + "-Wl,--gc-sections", + "-Wl,-z,text", + "-Wl,-z,norelro", + "-Wl,--rosegment", + "-Wl,--no-undefined", + "-Wl,--error-unresolved-symbols", + "-Wl,--no-undefined-version", + "-Wl,-Bsymbolic", + "-Wl,--export-dynamic", ]; + const EXPORT_SYMBOLS: &[&str] = &[ "sgx_entry", "HEAP_BASE", @@ -41,19 +42,26 @@ pub fn target() -> Result { "ENCLAVE_SIZE", "CFGDATA_BASE", "DEBUG", + "EH_FRM_HDR_BASE", + "EH_FRM_HDR_SIZE", + "TEXT_BASE", + "TEXT_SIZE", ]; let opts = TargetOptions { dynamic_linking: false, executables: true, linker_is_gnu: true, max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Abort, + panic_strategy: PanicStrategy::Unwind, cpu: "x86-64".into(), features: "+rdrnd,+rdseed".into(), position_independent_executables: true, - pre_link_args: iter::once( - (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect()) - ).collect(), + pre_link_args: iter::once(( + LinkerFlavor::Gcc, + PRE_LINK_ARGS.iter().cloned().map(String::from).collect(), + )) + .collect(), + post_link_objects: vec!["libunwind.a".into()], override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()), ..Default::default() }; diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index 4d5cc02e11e2c..49ede0674ce42 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -56,6 +56,14 @@ IMAGE_BASE: globvar CFGDATA_BASE 8 /* Non-zero if debugging is enabled, zero otherwise */ globvar DEBUG 1 + /* The base address (relative to enclave start) of the enclave text section */ + globvar TEXT_BASE 8 + /* The size in bytes of enclacve text section */ + globvar TEXT_SIZE 8 + /* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */ + globvar EH_FRM_HDR_BASE 8 + /* The size in bytes of enclacve EH_FRM_HDR section */ + globvar EH_FRM_HDR_SIZE 8 .Lreentry_panic_msg: .asciz "Re-entered panicked enclave!" diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index a1551dbb53b2d..d1af98bd4f525 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -9,14 +9,25 @@ // except according to those terms. use num::NonZeroUsize; +use slice; +use str; -use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false}; +use super::waitqueue::{ + try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable, +}; +use mem; pub struct RWLock { readers: SpinMutex>>, writer: SpinMutex>, } +// Below is to check at compile time, that RWLock has size of 128 bytes. +#[allow(dead_code)] +unsafe fn rw_lock_size_assert(r: RWLock) { + mem::transmute::(r); +} + //unsafe impl Send for RWLock {} //unsafe impl Sync for RWLock {} // FIXME @@ -24,7 +35,7 @@ impl RWLock { pub const fn new() -> RWLock { RWLock { readers: SpinMutex::new(WaitVariable::new(None)), - writer: SpinMutex::new(WaitVariable::new(false)) + writer: SpinMutex::new(WaitVariable::new(false)), } } @@ -89,9 +100,11 @@ impl RWLock { } #[inline] - pub unsafe fn read_unlock(&self) { - let mut rguard = self.readers.lock(); - let wguard = self.writer.lock(); + unsafe fn __read_unlock( + &self, + mut rguard: SpinMutexGuard>>, + wguard: SpinMutexGuard>, + ) { *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1); if rguard.lock_var().is_some() { // There are other active readers @@ -107,9 +120,18 @@ impl RWLock { } #[inline] - pub unsafe fn write_unlock(&self) { + pub unsafe fn read_unlock(&self) { let rguard = self.readers.lock(); let wguard = self.writer.lock(); + self.__read_unlock(rguard, wguard); + } + + #[inline] + unsafe fn __write_unlock( + &self, + rguard: SpinMutexGuard>>, + wguard: SpinMutexGuard>, + ) { if let Err(mut wguard) = WaitQueue::notify_one(wguard) { // No writers waiting, release the write lock *wguard.lock_var_mut() = false; @@ -128,6 +150,109 @@ impl RWLock { } } + #[inline] + pub unsafe fn write_unlock(&self) { + let rguard = self.readers.lock(); + let wguard = self.writer.lock(); + self.__write_unlock(rguard, wguard); + } + + #[inline] + unsafe fn unlock(&self) { + let rguard = self.readers.lock(); + let wguard = self.writer.lock(); + if *wguard.lock_var() == true { + self.__write_unlock(rguard, wguard); + } else { + self.__read_unlock(rguard, wguard); + } + } + #[inline] pub unsafe fn destroy(&self) {} } + +const EINVAL: i32 = 22; + +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).read(); + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).write(); + return 0; +} +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).unlock(); + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) { + if s < 0 { + return; + } + let buf = slice::from_raw_parts(m as *const u8, s as _); + if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) { + eprint!("{}", s); + } +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_abort() { + ::sys::abort_internal(); +} + +#[cfg(test)] +mod tests { + + use super::*; + use core::array::FixedSizeArray; + use mem::MaybeUninit; + use {mem, ptr}; + + // The below test verifies that the bytes of initialized RWLock are the ones + // we use in libunwind. + // If they change we need to update src/UnwindRustSgx.h in libunwind. + #[test] + fn test_c_rwlock_initializer() { + const RWLOCK_INIT: &[u8] = &[ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut init = MaybeUninit::::zeroed(); + init.set(RWLock::new()); + assert_eq!( + mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(), + RWLOCK_INIT + ); + } +} diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index eb53332ab3302..954eb9d6d03ba 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -26,10 +26,7 @@ mod macros; cfg_if! { if #[cfg(target_env = "msvc")] { // no extra unwinder support needed - } else if #[cfg(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx" - ))] { + } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { // no unwinder on the system! } else { extern crate libc; From 818ed6935dc10f450f5c230b19465b1a323b07ea Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 19 Dec 2018 16:39:01 +0100 Subject: [PATCH 27/32] dropck: simplify common patterns --- src/librustc/traits/query/dropck_outlives.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b8bf0fcc15307..b993dd6080bb6 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -55,8 +55,8 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values); let span = self.cause.span; debug!("c_ty = {:?}", c_ty); - match &gcx.dropck_outlives(c_ty) { - Ok(result) if result.is_proven() => { + if let Ok(result) = &gcx.dropck_outlives(c_ty) { + if result.is_proven() { if let Ok(InferOk { value, obligations }) = self.infcx.instantiate_query_response_and_region_obligations( self.cause, @@ -72,8 +72,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { }; } } - - _ => { /* fallthrough to error-handling code below */ } } // Errors and ambiuity in dropck occur in two cases: @@ -82,10 +80,11 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { // Either of these should have created an error before. tcx.sess .delay_span_bug(span, "dtorck encountered internal error"); - return InferOk { + + InferOk { value: vec![], obligations: vec![], - }; + } } } @@ -102,7 +101,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> { span: Span, ty: Ty<'tcx>, ) { - for overflow_ty in self.overflows.iter().take(1) { + if let Some(overflow_ty) = self.overflows.iter().next() { let mut err = struct_span_err!( tcx.sess, span, From ae3f6b015ec3f76e2d784fe7cb23b8bbb91faa43 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 19 Dec 2018 16:41:15 +0100 Subject: [PATCH 28/32] dropck: remove unnecessary call to cloned() --- src/librustc/traits/query/dropck_outlives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b993dd6080bb6..f506c47371c92 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -227,7 +227,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(def_id, ref substs) => substs .upvar_tys(def_id, tcx) .all(|t| trivial_dropck_outlives(tcx, t)), From 7eb67c2503eb01079f41a5d176485d9a85a9bb2d Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 19 Dec 2018 17:52:27 +0100 Subject: [PATCH 29/32] test: Ignore ui/target-feature-gate on powerpc and powerpc64(le) --- src/test/ui/target-feature-gate.rs | 3 +++ src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 4207a3285c48c..9a82f2b05325f 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -14,6 +14,9 @@ // ignore-emscripten // ignore-mips // ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index 54589536010ae..d7c2eb8c5f0a7 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:31:18 + --> $DIR/target-feature-gate.rs:34:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From a153d485fe9fbd0dd4f16c0dfa29bf5d75cd63df Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 19 Dec 2018 17:53:03 +0100 Subject: [PATCH 30/32] test: Ignore ui/target-feature-gate on sparc and sparc64 --- src/test/ui/target-feature-gate.rs | 2 ++ src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 9a82f2b05325f..cb0938b861c05 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -17,6 +17,8 @@ // ignore-powerpc // ignore-powerpc64 // ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index d7c2eb8c5f0a7..d7154324d12fe 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:34:18 + --> $DIR/target-feature-gate.rs:36:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From 036ce5cdc4a2cd5c0bdfaa83ed3ce64644bbdcde Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 19 Dec 2018 19:41:22 +0100 Subject: [PATCH 31/32] Fix compiletest `trim` deprecation warnings --- src/tools/compiletest/src/header.rs | 10 +++++----- src/tools/compiletest/src/runtest.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 8b3023e63dfb4..4e25e3a77110a 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -205,7 +205,7 @@ impl EarlyProps { fn ignore_lldb(config: &Config, line: &str) -> bool { if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed lldb version directive"); @@ -228,7 +228,7 @@ impl EarlyProps { } if let Some(ref actual_version) = config.llvm_version { if line.starts_with("min-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -236,7 +236,7 @@ impl EarlyProps { // version &actual_version[..] < min_version } else if line.starts_with("min-system-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -573,14 +573,14 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) { None => false, }; if matches { - it(ln[(close_brace + 1)..].trim_left()); + it(ln[(close_brace + 1)..].trim_start()); } } else { panic!("malformed condition directive: expected `{}foo]`, found `{}`", comment_with_brace, ln) } } else if ln.starts_with(comment) { - it(ln[comment.len() ..].trim_left()); + it(ln[comment.len() ..].trim_start()); } } return; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 45527a7cce535..cddaf93b67132 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1079,7 +1079,7 @@ impl<'test> TestCx<'test> { match line { Ok(line) => { let line = if line.starts_with("//") { - line[2..].trim_left() + line[2..].trim_start() } else { line.as_str() }; @@ -2143,8 +2143,8 @@ impl<'test> TestCx<'test> { .lines() .enumerate() .filter_map(|(line_nb, line)| { - if (line.trim_left().starts_with("pub mod ") - || line.trim_left().starts_with("mod ")) + if (line.trim_start().starts_with("pub mod ") + || line.trim_start().starts_with("mod ")) && line.ends_with(';') { if let Some(ref mut other_files) = other_files { @@ -2153,7 +2153,7 @@ impl<'test> TestCx<'test> { None } else { let sline = line.split("///").last().unwrap_or(""); - let line = sline.trim_left(); + let line = sline.trim_start(); if line.starts_with("```") { if ignore { ignore = false; @@ -3284,7 +3284,7 @@ fn normalize_mir_line(line: &str) -> String { fn nocomment_mir_line(line: &str) -> &str { if let Some(idx) = line.find("//") { let (l, _) = line.split_at(idx); - l.trim_right() + l.trim_end() } else { line } From 3fa6672d600a39968ee30863b2231eec792f1eba Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 20 Dec 2018 12:09:09 +0100 Subject: [PATCH 32/32] Rollup merge of #56954 - hug-dev:armv8m-main-ci, r=alexcrichton Add dist builder for Armv8-M Mainline This commit adds the Armv8-M Mainline target in the list of targets that get their dist components built. It also update the build-manifest so that this target gets also its dist components uploaded. I took example on other pull requests doing the same thing for another target to make the changes. Please feel free to comment if things needs to be added or removed. Doing `./x.py dist --target thumbv8m.main-none-eabi` worked locally so I assume that this will also work on the CI. It will (I think) however need a new release of alexcrichton/cc-rs to include the pull request alexcrichton/cc-rs#363 @alexcrichton I hope to do the HardFloat version (`thumbv8m.main-none-eabihf`) and Baseline (`thumbv8m.base-none-eabi`) later, as fixes need to be done on compiler-builtins first to support those. --- src/ci/docker/dist-various-1/Dockerfile | 1 + src/tools/build-manifest/src/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 4f8a3c0240e1a..f36ab13d5fd1e 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -103,6 +103,7 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi ENV TARGETS=$TARGETS,thumbv7m-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabihf +ENV TARGETS=$TARGETS,thumbv8m.main-none-eabi ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf ENV TARGETS=$TARGETS,armebv7r-none-eabi diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index aba0472ae366e..7c0cd44b9a5b1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -100,6 +100,7 @@ static TARGETS: &'static [&'static str] = &[ "thumbv7em-none-eabi", "thumbv7em-none-eabihf", "thumbv7m-none-eabi", + "thumbv8m.main-none-eabi", "wasm32-unknown-emscripten", "wasm32-unknown-unknown", "x86_64-apple-darwin",