fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
        &mut self,
        src_val: Value,
        write_dest: F,
        old_dest_val: Value,
        dest_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx> {
        // FIXME: this should be a layout check, not underlying value
        if let Value::ByRef(dest_ptr, align) = old_dest_val {
            // If the value is already `ByRef` (that is, backed by an `Allocation`),
            // then we must write the new value into this allocation, because there may be
            // other pointers into the allocation. These other pointers are logically
            // pointers into the local variable, and must be able to observe the change.
            //
            // Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
            // knew for certain that there were no outstanding pointers to this allocation.
            self.write_value_to_ptr(src_val, dest_ptr, align, dest_ty)?;
        } else if let Value::ByRef(src_ptr, align) = src_val {
            // If the value is not `ByRef`, then we know there are no pointers to it
            // and we can simply overwrite the `Value` in the locals array directly.
            //
            // In this specific case, where the source value is `ByRef`, we must duplicate
            // the allocation, because this is a by-value operation. It would be incorrect
            // if they referred to the same allocation, since then a change to one would
            // implicitly change the other.
            //
            // It is a valid optimization to attempt reading a primitive value out of the
            // source and write that into the destination without making an allocation, so
            // we do so here.
            if let Ok(Some(src_val)) = self.try_read_value(src_ptr, align, dest_ty) {
                write_dest(self, src_val)?;
            } else {
                let layout = self.layout_of(dest_ty)?;
                let dest_ptr = self.alloc_ptr(layout)?.into();
                self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size, false)?;
                write_dest(self, Value::ByRef(dest_ptr, layout.align))?;
            }
        } else {
            // Finally, we have the simple case where neither source nor destination are
            // `ByRef`. We may simply copy the source value over the the destintion.
            write_dest(self, src_val)?;
        }
        Ok(())
    }
// The cases here can be a bit subtle. Read carefully!
The cases here can be a bit subtle. Read carefully!
The cases here can be a bit subtle . Read carefully!
fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
        &mut self,
        src_val: Value,
        write_dest: F,
        old_dest_val: Value,
        dest_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx> {
        // FIXME: this should be a layout check, not underlying value
        if let Value::ByRef(dest_ptr, align) = old_dest_val {
            // If the value is already `ByRef` (that is, backed by an `Allocation`),
            // then we must write the new value into this allocation, because there may be
            // other pointers into the allocation. These other pointers are logically
            // pointers into the local variable, and must be able to observe the change.
            //
            // Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
            // knew for certain that there were no outstanding pointers to this allocation.
            self.write_value_to_ptr(src_val, dest_ptr, align, dest_ty)?;
        } else if let Value::ByRef(src_ptr, align) = src_val {
            // If the value is not `ByRef`, then we know there are no pointers to it
            // and we can simply overwrite the `Value` in the locals array directly.
            //
            // In this specific case, where the source value is `ByRef`, we must duplicate
            // the allocation, because this is a by-value operation. It would be incorrect
            // if they referred to the same allocation, since then a change to one would
            // implicitly change the other.
            //
            // It is a valid optimization to attempt reading a primitive value out of the
            // source and write that into the destination without making an allocation, so
            // we do so here.
            if let Ok(Some(src_val)) = self.try_read_value(src_ptr, align, dest_ty) {
                write_dest(self, src_val)?;
            } else {
                let layout = self.layout_of(dest_ty)?;
                let dest_ptr = self.alloc_ptr(layout)?.into();
                self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size, false)?;
                write_dest(self, Value::ByRef(dest_ptr, layout.align))?;
            }
        } else {
            // Finally, we have the simple case where neither source nor destination are
            // `ByRef`. We may simply copy the source value over the the destintion.
            write_dest(self, src_val)?;
        }
        Ok(())
    }
fn write_value_possibly_by_val < F : FnOnce ( & mut Self , Value ) -> EvalResult < ' tcx > > ( & mut self , src_val : Value , write_dest : F , old_dest_val : Value , dest_ty : Ty < ' tcx > , ) -> EvalResult < ' tcx > { // FIXME: this should be a layout check, not underlying value if let Value :: ByRef ( dest_ptr , align ) = old_dest_val { // If the value is already `ByRef` (that is, backed by an `Allocation`), // then we must write the new value into this allocation, because there may be // other pointers into the allocation. These other pointers are logically // pointers into the local variable, and must be able to observe the change. // // Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we // knew for certain that there were no outstanding pointers to this allocation. self . write_value_to_ptr ( src_val , dest_ptr , align , dest_ty ) ? ; } else if let Value :: ByRef ( src_ptr , align ) = src_val { // If the value is not `ByRef`, then we know there are no pointers to it // and we can simply overwrite the `Value` in the locals array directly. // // In this specific case, where the source value is `ByRef`, we must duplicate // the allocation, because this is a by-value operation. It would be incorrect // if they referred to the same allocation, since then a change to one would // implicitly change the other. // // It is a valid optimization to attempt reading a primitive value out of the // source and write that into the destination without making an allocation, so // we do so here. if let Ok ( Some ( src_val ) ) = self . try_read_value ( src_ptr , align , dest_ty ) { write_dest ( self , src_val ) ? ; } else { let layout = self . layout_of ( dest_ty ) ? ; let dest_ptr = self . alloc_ptr ( layout ) ? . into ( ) ; self . memory . copy ( src_ptr , align . min ( layout . align ) , dest_ptr , layout . align , layout . size , false ) ? ; write_dest ( self , Value :: ByRef ( dest_ptr , layout . align ) ) ? ; } } else { // Finally, we have the simple case where neither source nor destination are // `ByRef`. We may simply copy the source value over the the destintion. write_dest ( self , src_val ) ? ; } Ok ( ( ) ) }
The cases here can be a bit subtle.
The cases here can be a bit subtle .
&mut self
src_val
Value
write_dest
F
old_dest_val
Value
dest_ty
Ty<'tcx>
&mut self
src_val
Value
write_dest
F
old_dest_val
Value
dest_ty
Ty<'tcx>