]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_typeck/src/expr_use_visitor.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / expr_use_visitor.rs
index f17494127948414f1c363abde40bf5878701c439..806f1a2711c012b9d52d7830d5d40efd755a5b7a 100644 (file)
@@ -2,8 +2,6 @@
 //! normal visitor, which just walks the entire body in one shot, the
 //! `ExprUseVisitor` determines how expressions are being used.
 
-pub use self::ConsumeMode::*;
-
 // Export these here so that Clippy can use them.
 pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
 
@@ -28,19 +26,20 @@ use crate::mem_categorization as mc;
 /// This trait defines the callbacks you can expect to receive when
 /// employing the ExprUseVisitor.
 pub trait Delegate<'tcx> {
-    // The value found at `place` is either copied or moved, depending
+    // The value found at `place` is moved, depending
     // on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
     //
+    // Use of a `Copy` type in a ByValue context is considered a use
+    // by `ImmBorrow` and `borrow` is called instead. This is because
+    // a shared borrow is the "minimum access" that would be needed
+    // to perform a copy.
+    //
+    //
     // The parameter `diag_expr_id` indicates the HIR id that ought to be used for
     // diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
     // id will be the id of the expression `expr` but the place itself will have
     // the id of the binding in the pattern `pat`.
-    fn consume(
-        &mut self,
-        place_with_id: &PlaceWithHirId<'tcx>,
-        diag_expr_id: hir::HirId,
-        mode: ConsumeMode,
-    );
+    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
 
     // The value found at `place` is being borrowed with kind `bk`.
     // `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
@@ -60,7 +59,7 @@ pub trait Delegate<'tcx> {
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
-pub enum ConsumeMode {
+enum ConsumeMode {
     Copy, // reference to x where x has a type that copies
     Move, // reference to x where x has a type that moves
 }
@@ -141,10 +140,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     }
 
     fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
-        debug!("delegate_consume(place_with_id={:?})", place_with_id);
-
-        let mode = copy_or_move(&self.mc, place_with_id);
-        self.delegate.consume(place_with_id, diag_expr_id, mode);
+        delegate_consume(&self.mc, self.delegate, place_with_id, diag_expr_id)
     }
 
     fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) {
@@ -256,12 +252,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             | PatKind::Path(..)
                             | PatKind::Struct(..)
                             | PatKind::Tuple(..) => {
-                                // If the PatKind is a TupleStruct, Struct or Tuple then we want to check
+                                // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check
                                 // whether the Variant is a MultiVariant or a SingleVariant. We only want
                                 // to borrow discr if it is a MultiVariant.
                                 // If it is a SingleVariant and creates a binding we will handle that when
                                 // this callback gets called again.
-                                if let ty::Adt(def, _) = place.place.base_ty.kind() {
+
+                                // Get the type of the Place after all projections have been applied
+                                let place_ty = place.place.ty();
+
+                                if let ty::Adt(def, _) = place_ty.kind() {
                                     if def.variants.len() > 1 {
                                         needs_to_be_read = true;
                                     }
@@ -653,9 +653,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             delegate.borrow(place, discr_place.hir_id, bk);
                         }
                         ty::BindByValue(..) => {
-                            let mode = copy_or_move(mc, &place);
                             debug!("walk_pat binding consuming pat");
-                            delegate.consume(place, discr_place.hir_id, mode);
+                            delegate_consume(mc, *delegate, place, discr_place.hir_id);
                         }
                     }
                 }
@@ -773,8 +772,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
                     match capture_info.capture_kind {
                         ty::UpvarCapture::ByValue(_) => {
-                            let mode = copy_or_move(&self.mc, &place_with_id);
-                            self.delegate.consume(&place_with_id, place_with_id.hir_id, mode);
+                            self.delegate_consume(&place_with_id, place_with_id.hir_id);
                         }
                         ty::UpvarCapture::ByRef(upvar_borrow) => {
                             self.delegate.borrow(
@@ -798,8 +796,28 @@ fn copy_or_move<'a, 'tcx>(
         place_with_id.place.ty(),
         mc.tcx().hir().span(place_with_id.hir_id),
     ) {
-        Move
+        ConsumeMode::Move
     } else {
-        Copy
+        ConsumeMode::Copy
+    }
+}
+
+// - If a place is used in a `ByValue` context then move it if it's not a `Copy` type.
+// - If the place that is a `Copy` type consider it a `ImmBorrow`.
+fn delegate_consume<'a, 'tcx>(
+    mc: &mc::MemCategorizationContext<'a, 'tcx>,
+    delegate: &mut (dyn Delegate<'tcx> + 'a),
+    place_with_id: &PlaceWithHirId<'tcx>,
+    diag_expr_id: hir::HirId,
+) {
+    debug!("delegate_consume(place_with_id={:?})", place_with_id);
+
+    let mode = copy_or_move(&mc, place_with_id);
+
+    match mode {
+        ConsumeMode::Move => delegate.consume(place_with_id, diag_expr_id),
+        ConsumeMode::Copy => {
+            delegate.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow)
+        }
     }
 }