about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.mailmap2
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/ops/range.rs23
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/ops.rs17
-rw-r--r--src/librustc/mir/visit.rs58
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs85
-rw-r--r--src/librustc_mir/monomorphize/collector.rs25
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs79
9 files changed, 174 insertions, 117 deletions
diff --git a/.mailmap b/.mailmap
index 679aa55d314..5673cc5cfbc 100644
--- a/.mailmap
+++ b/.mailmap
@@ -56,6 +56,7 @@ Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
 Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
 Christian Poveda <christianpoveda@protonmail.com> <cn.poveda.ruiz@gmail.com>
 Christian Poveda <christianpoveda@protonmail.com> <z1mvader@protonmail.com>
+Christian Poveda <christianpoveda@protonmail.com> <cpovedar@fnal.gov>
 Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
 Clinton Ryan <clint.ryan3@gmail.com>
 Corey Richardson <corey@octayn.net> Elaine "See More" Nemo <corey@octayn.net>
@@ -139,6 +140,7 @@ Kang Seonghoon <kang.seonghoon@mearie.org> <public+git@mearie.org>
 Keegan McAllister <mcallister.keegan@gmail.com> <kmcallister@mozilla.com>
 Kevin Butler <haqkrs@gmail.com>
 Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
+Laurențiu Nicola <lnicola@dend.ro>
 Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <lee@leejeffery.co.uk>
 Lee Wondong <wdlee91@gmail.com>
 Lennart Kudling <github@kudling.de>
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index ad352048047..af24cbe1c5c 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)]
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index a707f0cc062..1b4c4218cc1 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -696,6 +696,29 @@ pub enum Bound<T> {
     Unbounded,
 }
 
+impl<T: Clone> Bound<&T> {
+    /// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(bound_cloned)]
+    /// 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")]
+    pub fn cloned(self) -> Bound<T> {
+        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`.
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 5050842e409..928bdd7a760 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)]
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
index 78cf07119e7..48755ae4c16 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.
 
@@ -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));
+}
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index dd33fae0d61..2f19f591830 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -151,17 +151,17 @@ macro_rules! make_mir_visitor {
                 self.super_place(place, context, location);
             }
 
-            fn visit_projection(&mut self,
-                                place: & $($mutability)? Projection<'tcx>,
+            fn visit_place_base(&mut self,
+                                place_base: & $($mutability)? PlaceBase<'tcx>,
                                 context: PlaceContext,
                                 location: Location) {
-                self.super_projection(place, context, location);
+                self.super_place_base(place_base, context, location);
             }
 
-            fn visit_projection_elem(&mut self,
-                                     place: & $($mutability)? PlaceElem<'tcx>,
-                                     location: Location) {
-                self.super_projection_elem(place, location);
+            fn visit_projection(&mut self,
+                                place: & $($mutability)? Projection<'tcx>,
+                                location: Location) {
+                self.super_projection(place, location);
             }
 
             fn visit_constant(&mut self,
@@ -676,36 +676,40 @@ macro_rules! make_mir_visitor {
                             context: PlaceContext,
                             location: Location) {
                 match place {
-                    Place::Base(PlaceBase::Local(local)) => {
-                        self.visit_local(local, context, location);
-                    }
-                    Place::Base(PlaceBase::Static(box Static { kind: _, ty })) => {
-                        self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
+                    Place::Base(place_base) => {
+                        self.visit_place_base(place_base, context, location);
                     }
                     Place::Projection(proj) => {
-                        self.visit_projection(proj, context, location);
+                        let context = if context.is_mutating_use() {
+                            PlaceContext::MutatingUse(MutatingUseContext::Projection)
+                        } else {
+                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
+                        };
+
+                        self.visit_place(& $($mutability)? proj.base, context, location);
+                        self.visit_projection(proj, location);
                     }
                 }
             }
 
-            fn super_projection(&mut self,
-                                proj: & $($mutability)? Projection<'tcx>,
+            fn super_place_base(&mut self,
+                                place_base: & $($mutability)? PlaceBase<'tcx>,
                                 context: PlaceContext,
                                 location: Location) {
-                let Projection { base, elem } = proj;
-                let context = if context.is_mutating_use() {
-                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
-                } else {
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
-                };
-                self.visit_place(base, context, location);
-                self.visit_projection_elem(elem, location);
+                match place_base {
+                    PlaceBase::Local(local) => {
+                        self.visit_local(local, context, location);
+                    }
+                    PlaceBase::Static(box Static { kind: _, ty }) => {
+                        self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
+                    }
+                }
             }
 
-            fn super_projection_elem(&mut self,
-                                     proj: & $($mutability)? PlaceElem<'tcx>,
-                                     location: Location) {
-                match proj {
+            fn super_projection(&mut self,
+                                proj: & $($mutability)? Projection<'tcx>,
+                                location: Location) {
+                match & $($mutability)? proj.elem {
                     ProjectionElem::Deref => {
                     }
                     ProjectionElem::Subslice { from: _, to: _ } => {
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index bb6a13ed15a..549608bf7ee 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,
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index eed051449e1..91b4af9655a 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -185,7 +185,7 @@ use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance};
 use rustc::ty::print::obsolete::DefPathBasedNames;
 use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc::session::config::EntryFnType;
-use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind};
+use rustc::mir::{self, Location, PlaceBase, Promoted, Static, StaticKind};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::{MonoItem, InstantiationMode};
 use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
@@ -655,14 +655,12 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
         self.super_terminator_kind(kind, location);
     }
 
-    fn visit_place(&mut self,
-                    place: &mir::Place<'tcx>,
-                    context: mir::visit::PlaceContext,
-                    location: Location) {
-        match place {
-            Place::Base(
-                PlaceBase::Static(box Static{ kind:StaticKind::Static(def_id), .. })
-            ) => {
+    fn visit_place_base(&mut self,
+                        place_base: &mir::PlaceBase<'tcx>,
+                        _context: mir::visit::PlaceContext,
+                        location: Location) {
+        match place_base {
+            PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => {
                 debug!("visiting static {:?} @ {:?}", def_id, location);
 
                 let tcx = self.tcx;
@@ -671,10 +669,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                     self.output.push(MonoItem::Static(*def_id));
                 }
             }
-            _ => {}
+            PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => {
+                // FIXME: should we handle promoteds here instead of eagerly in collect_neighbours?
+            }
+            PlaceBase::Local(_) => {
+                // Locals have no relevance for collector
+            }
         }
-
-        self.super_place(place, context, location);
     }
 }
 
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 8ec8a8fa12e..4e8cc124e50 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);
+        });
     }
 }