]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/build/expr/as_rvalue.rs
Auto merge of #52046 - cramertj:fix-generator-mir, r=eddyb
[rust.git] / src / librustc_mir / build / expr / as_rvalue.rs
index 4115dbe6274930681f7242deb644d9ec507d2438..7bd9a241a534ef3eaa72b58000e894f18dc5f4f0 100644 (file)
@@ -102,7 +102,9 @@ fn expr_as_rvalue(&mut self,
                 });
                 if let Some(scope) = scope {
                     // schedule a shallow free of that memory, lest we unwind:
-                    this.schedule_drop(expr_span, scope, &Place::Local(result), value.ty);
+                    this.schedule_drop_storage_and_value(
+                        expr_span, scope, &Place::Local(result), value.ty,
+                    );
                 }
 
                 // malloc some memory of suitable type (thus far, uninitialized):
@@ -186,10 +188,29 @@ fn expr_as_rvalue(&mut self,
             }
             ExprKind::Closure { closure_id, substs, upvars, movability } => {
                 // see (*) above
-                let mut operands: Vec<_> =
-                    upvars.into_iter()
-                          .map(|upvar| unpack!(block = this.as_operand(block, scope, upvar)))
-                          .collect();
+                let mut operands: Vec<_> = upvars
+                    .into_iter()
+                    .map(|upvar| {
+                        let upvar = this.hir.mirror(upvar);
+                        match Category::of(&upvar.kind) {
+                            // Use as_place to avoid creating a temporary when
+                            // moving a variable into a closure, so that
+                            // borrowck knows which variables to mark as being
+                            // used as mut. This is OK here because the upvar
+                            // expressions have no side effects and act on
+                            // disjoint places.
+                            // This occurs when capturing by copy/move, while
+                            // by reference captures use as_operand
+                            Some(Category::Place) => {
+                                let place = unpack!(block = this.as_place(block, upvar));
+                                this.consume_by_copy_or_move(place)
+                            }
+                            _ => {
+                                unpack!(block = this.as_operand(block, scope, upvar))
+                            }
+                        }
+                    })
+                    .collect();
                 let result = match substs {
                     UpvarSubsts::Generator(substs) => {
                         let movability = movability.unwrap();
@@ -202,7 +223,7 @@ fn expr_as_rvalue(&mut self,
                                 value: ty::Const::from_bits(
                                     this.hir.tcx(),
                                     0,
-                                    this.hir.tcx().types.u32),
+                                    ty::ParamEnv::empty().and(this.hir.tcx().types.u32)),
                             },
                         }));
                         box AggregateKind::Generator(closure_id, substs, movability)
@@ -374,10 +395,11 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
 
     // Helper to get a `-1` value of the appropriate type
     fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
-        let bits = self.hir.integer_bit_width(ty);
+        let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap());
+        let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits();
         let n = (!0u128) >> (128 - bits);
         let literal = Literal::Value {
-            value: ty::Const::from_bits(self.hir.tcx(), n, ty)
+            value: ty::Const::from_bits(self.hir.tcx(), n, param_ty)
         };
 
         self.literal_operand(span, ty, literal)
@@ -386,10 +408,11 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
     // Helper to get the minimum value of the appropriate type
     fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         assert!(ty.is_signed());
-        let bits = self.hir.integer_bit_width(ty);
+        let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap());
+        let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits();
         let n = 1 << (bits - 1);
         let literal = Literal::Value {
-            value: ty::Const::from_bits(self.hir.tcx(), n, ty)
+            value: ty::Const::from_bits(self.hir.tcx(), n, param_ty)
         };
 
         self.literal_operand(span, ty, literal)