Code change:
self.as_operand(block, local_scope, expr) } <ins> /// Returns an operand suitable for use until the end of the current scope expression and /// suitable also to be passed as function arguments. /// /// The operand returned from this function will *not be valid* after an ExprKind::Scope is /// passed, so please do *not* return it from functions to avoid bad miscompiles.  Returns an /// operand suitable for use as a call argument. This is almost always equivalent to /// `as_operand`, except for the particular case of passing values of (potentially) unsized /// types "by value" (see details below). /// /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. /// /// # Parameters of unsized types /// /// We tweak the handling of parameters of unsized type slightly to avoid the need to create a /// local variable of unsized type. For example, consider this program: /// /// ```rust /// fn foo(p: dyn Debug) { ... } /// /// fn bar(box_p: Box<dyn Debug>) { foo(*p); } /// ``` /// /// Ordinarily, for sized types, we would compile the call `foo(*p)` like so: /// /// ```rust /// let tmp0 = *box_p; // tmp0 would be the operand returned by this function call /// foo(tmp0) /// ``` /// /// But because the parameter to `foo` is of the unsized type `dyn Debug`, and because it is /// being moved the deref of a box, we compile it slightly differently. The temporary `tmp0` /// that we create *stores the entire box*, and the parameter to the call itself will be /// `*tmp0`: /// /// ```rust /// let tmp0 = box_p; call foo(*tmp0) /// ``` /// /// This way, the temporary `tmp0` that we create has type `Box<dyn Debug>`, which is sized. /// The value passed to the call (`*tmp0`) still has the `dyn Debug` type -- but the way that /// calls are compiled means that this parameter will be passed "by reference", meaning that we /// will actually provide a pointer to the interior of the box, and not move the `dyn Debug` /// value to the stack. /// /// See #68034 for more details. crate fn as_local_call_operand<M>( &mut self, block: BasicBlock, expr: M, ) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>, { let local_scope = self.local_scope(); self.as_call_operand(block, local_scope, expr) } </ins> /// Compile `expr` into a value that can be used as an operand. /// If `expr` is a place like `x`, this will introduce a /// temporary `tmp = x`, so that we capture the value of `x` at

Related discussion:
text: In particular, the IR for under your proposal, if I understood, would be But the access to that (I believe) we wish to prevent takes place in the "evaluate remaining arguments" part of things. So I think we'd have to add some sort of "pseudo-move" that tells borrowck that should not be assignable from that point forward, right? Well, it depends on your perspective. It's true that, given the need to permit reinitialization, the check is now specific to unsized values -- i.e., MIR construction will be different depending on whether we know the type to be sized or not. That's unfortunate. However, I think we still maintain a degree of congruence, from an end-user perspective. In particular, users could not have reinitialized a anyhow. However, under my proposal, users can write things like and the code works as expected (versus either having an unexpected result or getting an error). In any case, it seems like we're sort of "narrowing in" on a proposal here: when we see a function call with a parameter that is , and the value being passed is a deref, we want to modify the IR to not introduce a temporary and instead pass that parameter directly from its location, either we do some sort of "no more assignments" lock, or we move the pointer and introduce a temporary (and then pass in a deref of that temporary) Does that sound right so far?
If it's easier to do the more flexible approach (by moving the pointer) than the "locking" approach (which is a bit like borrowing the pointer until all arguments are evaluated, then releasing the borrow and doing a move instead), I don't mind it, I was only arguing with the "uniformity" aspect. Something important here: your approach is stabilizable, while mine is meant more for that one in the standard library, and not much else.
Yes, I was kind of shooting for something that we could conceivably stabilize.
Removing nomination, this was already discussed in triage meeting and it's under control.
So should we maybe try out the approach I proposed and see how well it works?
yes, going to try that out.
For the record, the "new plan" is this.