From 333e1ca319636d23983de1f8ea2c102aae731c54 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Thu, 30 May 2019 16:46:53 -0500 Subject: [PATCH 01/15] Add Bound::cloned() --- src/libcore/ops/range.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index a707f0cc0627a..39bf80281c576 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -696,6 +696,28 @@ pub enum Bound { Unbounded, } +impl Bound<&T> { + /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. + /// + /// # Examples + /// + /// ``` + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((1..12).start_bound(), Included(&1)); + /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// ``` + #[unstable(feature = "bound_cloned", issue = 61356)] + fn cloned(&self) -> Bound { + match self { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(x) => Bound::Included(x.clone()), + Bound::Excluded(x) => Bound::Excluded(x.clone()), + } + } +} + #[stable(feature = "collections_range", since = "1.28.0")] /// `RangeBounds` is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. From 867c4a5fdac44d683035d8eaaf69f43adffcc5ca Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Thu, 30 May 2019 21:52:52 -0500 Subject: [PATCH 02/15] Fix compilation errors --- src/libcore/ops/range.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 39bf80281c576..a04c1bc033929 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -708,9 +708,9 @@ impl Bound<&T> { /// assert_eq!((1..12).start_bound(), Included(&1)); /// assert_eq!((1..12).start_bound().cloned(), Included(1)); /// ``` - #[unstable(feature = "bound_cloned", issue = 61356)] + #[unstable(feature = "bound_cloned", issue = "61356")] fn cloned(&self) -> Bound { - match self { + match *self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(x.clone()), Bound::Excluded(x) => Bound::Excluded(x.clone()), From 0772f9a92082c3f5a734e1fae198f817bbf2f61f Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 31 May 2019 11:36:28 -0500 Subject: [PATCH 03/15] Make Bound::cloned public --- src/libcore/ops/range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index a04c1bc033929..e9c5f1d4a8bfa 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -709,7 +709,7 @@ impl Bound<&T> { /// assert_eq!((1..12).start_bound().cloned(), Included(1)); /// ``` #[unstable(feature = "bound_cloned", issue = "61356")] - fn cloned(&self) -> Bound { + pub fn cloned(&self) -> Bound { match *self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(x.clone()), From df845784ee74cee760caf38064d39e14a23ef791 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 31 May 2019 11:36:37 -0500 Subject: [PATCH 04/15] Add Bound tests --- src/libcore/tests/ops.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs index 78cf07119e729..3f6d63fc8a151 100644 --- a/src/libcore/tests/ops.rs +++ b/src/libcore/tests/ops.rs @@ -82,3 +82,18 @@ fn test_range_is_empty() { assert!( (NAN ..= EPSILON).is_empty()); assert!( (NAN ..= NAN).is_empty()); } + +#[test] +fn test_bound_cloned_unbounded() { + assert_eq!(Bound::<&u32>::Unbounded.cloned(), Bound::Unbounded); +} + +#[test] +fn test_bound_cloned_included() { + assert_eq!(Bound::Included(&3).cloned(), Bound::Included(3)); +} + +#[test] +fn test_bound_cloned_excluded() { + assert_eq!(Bound::Excluded(&3).cloned(), Bound::Excluded(3)); +} From a21a0e0268a2121339148b97ed31bffedf860021 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 31 May 2019 16:56:26 -0500 Subject: [PATCH 05/15] Import Bound in tests --- src/libcore/tests/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs index 3f6d63fc8a151..48755ae4c1641 100644 --- a/src/libcore/tests/ops.rs +++ b/src/libcore/tests/ops.rs @@ -1,4 +1,4 @@ -use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive}; +use core::ops::{Bound, Range, RangeFull, RangeFrom, RangeTo, RangeInclusive}; // Test the Range structs without the syntactic sugar. From c3824919fd29c936f07806733c463e73172c60a2 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Fri, 31 May 2019 21:17:32 -0500 Subject: [PATCH 06/15] Enable feature bound_cloned --- src/libcore/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4a70329b64bc9..64d70b5de21dd 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -70,6 +70,7 @@ #![feature(arbitrary_self_types)] #![feature(asm)] #![feature(associated_type_defaults)] +#![feature(bound_cloned)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] #![feature(const_fn)] From c478efbe6a2e324910f2f82db7d03a6476215ca2 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Sat, 1 Jun 2019 22:39:13 -0700 Subject: [PATCH 07/15] Enable feature bound_cloned for tests --- src/libcore/ops/range.rs | 1 + src/libcore/tests/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index e9c5f1d4a8bfa..ddcf3addf398f 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -702,6 +702,7 @@ impl Bound<&T> { /// # Examples /// /// ``` + /// #![feature(bound_cloned)] /// use std::ops::Bound::*; /// use std::ops::RangeBounds; /// diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index c617596aba801..7465ef4a44e24 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -1,3 +1,4 @@ +#![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] #![feature(core_private_bignum)] From e2e7949b5338e487f8759c7680ac117c2e80df57 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Wed, 5 Jun 2019 12:56:08 +0200 Subject: [PATCH 08/15] Update stdsimd. --- src/stdsimd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdsimd b/src/stdsimd index 4bf456c35e85f..87d19d212ef17 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 4bf456c35e85fcca5cf95008401af8ab25abf850 +Subproject commit 87d19d212ef172a6cfbb3a330ac1c33da16cced6 From d8b2e85661592ab4645787d8ebf62611eac4ef7b Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Thu, 6 Jun 2019 01:18:24 +0200 Subject: [PATCH 09/15] Add f16 and rtm target feature features --- src/libcore/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index ad35204804755..5c5ebff6594d9 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -115,6 +115,8 @@ #![feature(wasm_target_feature)] #![feature(avx512_target_feature)] #![feature(cmpxchg16b_target_feature)] +#![feature(f16c_target_feature)] +#![feature(rtm_target_feature)] #![feature(const_slice_len)] #![feature(const_str_as_bytes)] #![feature(const_str_len)] From 2bdaccbbcf02e4c14028ab15478e09a16d3e3d05 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 5 Jun 2019 21:01:17 +0200 Subject: [PATCH 10/15] Make UnsafetyChecker visitor iterate instead of recurse --- src/librustc_mir/transform/check_unsafety.rs | 79 ++++++++++---------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 8ec8a8fa12eec..4e8cc124e5040 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -199,11 +199,39 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, - location: Location) { - match place { - &Place::Projection(box Projection { - ref base, ref elem - }) => { + _location: Location) { + place.iterate(|place_base, place_projections| { + match place_base { + PlaceBase::Local(..) => { + // Locals are safe. + } + PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { + bug!("unsafety checking should happen before promotion") + } + PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { + if self.tcx.is_mutable_static(*def_id) { + self.require_unsafe("use of mutable static", + "mutable statics can be mutated by multiple threads: aliasing \ + violations or data races will cause undefined behavior", + UnsafetyViolationKind::General); + } else if self.tcx.is_foreign_item(*def_id) { + let source_info = self.source_info; + let lint_root = + self.source_scope_local_data[source_info.scope].lint_root; + self.register_violations(&[UnsafetyViolation { + source_info, + description: InternedString::intern("use of extern static"), + details: InternedString::intern( + "extern statics are not controlled by the Rust type system: \ + invalid data, aliasing violations or data races will cause \ + undefined behavior"), + kind: UnsafetyViolationKind::ExternStatic(lint_root) + }], &[]); + } + } + } + + for proj in place_projections { if context.is_borrow() { if util::is_disaligned(self.tcx, self.mir, self.param_env, place) { let source_info = self.source_info; @@ -220,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { }], &[]); } } - let is_borrow_of_interior_mut = context.is_borrow() && !base + let is_borrow_of_interior_mut = context.is_borrow() && !proj.base .ty(self.mir, self.tcx) .ty .is_freeze(self.tcx, self.param_env, self.source_info.span); @@ -236,7 +264,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { ); } let old_source_info = self.source_info; - if let &Place::Base(PlaceBase::Local(local)) = base { + if let Place::Base(PlaceBase::Local(local)) = proj.base { if self.mir.local_decls[local].internal { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the @@ -244,7 +272,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_info = self.mir.local_decls[local].source_info; } } - let base_ty = base.ty(self.mir, self.tcx).ty; + let base_ty = proj.base.ty(self.mir, self.tcx).ty; match base_ty.sty { ty::RawPtr(..) => { self.require_unsafe("dereference of raw pointer", @@ -260,8 +288,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { MutatingUseContext::AsmOutput ) { - let elem_ty = match elem { - &ProjectionElem::Field(_, ty) => ty, + let elem_ty = match proj.elem { + ProjectionElem::Field(_, ty) => ty, _ => span_bug!( self.source_info.span, "non-field projection {:?} from union?", @@ -292,36 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } self.source_info = old_source_info; } - &Place::Base(PlaceBase::Local(..)) => { - // locals are safe - } - &Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => { - bug!("unsafety checking should happen before promotion") - } - &Place::Base( - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) - ) => { - if self.tcx.is_mutable_static(def_id) { - self.require_unsafe("use of mutable static", - "mutable statics can be mutated by multiple threads: aliasing violations \ - or data races will cause undefined behavior", - UnsafetyViolationKind::General); - } else if self.tcx.is_foreign_item(def_id) { - let source_info = self.source_info; - let lint_root = - self.source_scope_local_data[source_info.scope].lint_root; - self.register_violations(&[UnsafetyViolation { - source_info, - description: InternedString::intern("use of extern static"), - details: InternedString::intern( - "extern statics are not controlled by the Rust type system: invalid \ - data, aliasing violations or data races will cause undefined behavior"), - kind: UnsafetyViolationKind::ExternStatic(lint_root) - }], &[]); - } - } - }; - self.super_place(place, context, location); + }); } } From 0cfaa28bc5edda198571fca9410cbc9f71b8d17a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 5 Jun 2019 21:25:09 +0200 Subject: [PATCH 11/15] Make LocalAnalizer visitor iterate instead of recurse --- src/librustc_codegen_ssa/mir/analyze.rs | 85 ++++++++++++++----------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index bb6a13ed15a52..549608bf7ee5f 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> context: PlaceContext, location: Location) { debug!("visit_place(place={:?}, context={:?})", place, context); + let mut context = context; let cx = self.fx.cx; - if let mir::Place::Projection(ref proj) = *place { - // Allow uses of projections that are ZSTs or from scalar fields. - let is_consume = match context { - PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true, - _ => false - }; - if is_consume { - let base_ty = proj.base.ty(self.fx.mir, cx.tcx()); - let base_ty = self.fx.monomorphize(&base_ty); - - // ZSTs don't require any actual memory access. - let elem_ty = base_ty - .projection_ty(cx.tcx(), &proj.elem) - .ty; - let elem_ty = self.fx.monomorphize(&elem_ty); - if cx.layout_of(elem_ty).is_zst() { - return; - } - - if let mir::ProjectionElem::Field(..) = proj.elem { - let layout = cx.layout_of(base_ty.ty); - if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) { - // Recurse with the same context, instead of `Projection`, - // potentially stopping at non-operand projections, - // which would trigger `not_ssa` on locals. - self.visit_place(&proj.base, context, location); + place.iterate(|place_base, place_projections| { + for proj in place_projections { + // Allow uses of projections that are ZSTs or from scalar fields. + let is_consume = match context { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true, + _ => false + }; + if is_consume { + let base_ty = proj.base.ty(self.fx.mir, cx.tcx()); + let base_ty = self.fx.monomorphize(&base_ty); + + // ZSTs don't require any actual memory access. + let elem_ty = base_ty + .projection_ty(cx.tcx(), &proj.elem) + .ty; + let elem_ty = self.fx.monomorphize(&elem_ty); + if cx.layout_of(elem_ty).is_zst() { return; } + + if let mir::ProjectionElem::Field(..) = proj.elem { + let layout = cx.layout_of(base_ty.ty); + if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) { + // Recurse with the same context, instead of `Projection`, + // potentially stopping at non-operand projections, + // which would trigger `not_ssa` on locals. + continue; + } + } } - } - // A deref projection only reads the pointer, never needs the place. - if let mir::ProjectionElem::Deref = proj.elem { - return self.visit_place( - &proj.base, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), - location - ); + // A deref projection only reads the pointer, never needs the place. + if let mir::ProjectionElem::Deref = proj.elem { + return self.visit_place( + &proj.base, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); + } + + context = if context.is_mutating_use() { + PlaceContext::MutatingUse(MutatingUseContext::Projection) + } else { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) + }; } - } - self.super_place(place, context, location); + // Default base visit behavior + if let mir::PlaceBase::Local(local) = place_base { + self.visit_local(local, context, location); + } + }); } fn visit_local(&mut self, From 4a88614c4f46e1786a5bf2ce650631cc250a6edb Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Wed, 5 Jun 2019 21:11:02 -0700 Subject: [PATCH 12/15] Take self by value (Self is Copy here) --- src/libcore/ops/range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index ddcf3addf398f..763020c478fba 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -710,7 +710,7 @@ impl Bound<&T> { /// assert_eq!((1..12).start_bound().cloned(), Included(1)); /// ``` #[unstable(feature = "bound_cloned", issue = "61356")] - pub fn cloned(&self) -> Bound { + pub fn cloned(self) -> Bound { match *self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(x.clone()), From c1bc8f11cb36cade87422b91a0bdec1fe8b5af41 Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Wed, 5 Jun 2019 21:23:45 -0700 Subject: [PATCH 13/15] Remove dereference Co-Authored-By: Steven Fackler --- src/libcore/ops/range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 763020c478fba..1b4c4218cc15b 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -711,7 +711,7 @@ impl Bound<&T> { /// ``` #[unstable(feature = "bound_cloned", issue = "61356")] pub fn cloned(self) -> Bound { - match *self { + match self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(x.clone()), Bound::Excluded(x) => Bound::Excluded(x.clone()), From 2bcdee3f1e02b9f6cb8109095ae9790a4b2b7459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 6 Jun 2019 16:37:23 +0300 Subject: [PATCH 14/15] Update .mailmap with my name --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 679aa55d31458..1bb0aed4a6a62 100644 --- a/.mailmap +++ b/.mailmap @@ -139,6 +139,7 @@ Kang Seonghoon Keegan McAllister Kevin Butler Kyeongwoon Lee +Laurențiu Nicola Lee Jeffery Lee Jeffery Lee Wondong Lennart Kudling From 6ba6183b1d9f121a09a66a59d19b40778fc859b5 Mon Sep 17 00:00:00 2001 From: Christian Poveda <31802960+christianpoveda@users.noreply.github.com> Date: Thu, 6 Jun 2019 11:52:07 -0500 Subject: [PATCH 15/15] Update .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 679aa55d31458..4a68d490e34ef 100644 --- a/.mailmap +++ b/.mailmap @@ -56,6 +56,7 @@ Chris Thorn Chris Thorn Chris Vittal Christopher Vittal Christian Poveda Christian Poveda +Christian Poveda Clark Gaebel Clinton Ryan Corey Richardson Elaine "See More" Nemo