diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0159a198bc647..f5a3c1989cf83 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -650,7 +650,9 @@ pub enum TerminatorKind<'tcx> { Call { /// The function that’s being called func: Operand<'tcx>, - /// Arguments the function is called with + /// Arguments the function is called with. These are owned by the callee, which is free to + /// modify them. This is important as "by-value" arguments might be passed by-reference at + /// the ABI level. args: Vec>, /// Destination for the return value. If some, the call is converging. destination: Option<(Lvalue<'tcx>, BasicBlock)>, diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 3d7abefd284e0..280e1c8196636 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -249,6 +249,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { args.into_iter() .map(|arg| { let scope = this.local_scope(); + // Function arguments are owned by the callee, so we need as_temp() + // instead of as_operand() to enforce copies let operand = unpack!(block = this.as_temp(block, scope, arg)); Operand::Consume(Lvalue::Local(operand)) })