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: if we keep setting as the default alignment we can skip the overallocating and offset dance for types with an alignment below that.
My idea was that rustc would prohibit coercing overaligned types to a dyn trait that takes by value. So:
The alignment is dynamically determined though, not sure if saving 15 bytes of stack space is worth the conditional branch?
Oh right. Yea that's probably not helpful.
Since , this would be backwards incompatible (at latest) once trait object upcasting is finally implemented: and trait objects would have to have the same alignment restriction (because you can upcast to ), but today you can freely create such objects with any alignment.
I was under the impression that calling didn't require dynamic , is that related to missing MIR optimizations, meaning we have unnecessary moves which end up duplicating the data on the stack using a dynamic ?
Correctness shouldn't rely on optimizations to fire...
Sure, I was just hoping we weren't relying on "unsized locals", only unsized parameters (i.e. ), for what we're exposing as stable. And I was hoping an optimization wouldn't need to be involved to get there. I wonder if it would even be possible to restrict "unsized locals" to the subset where we can handle it entirely through ABI, and not actually have dynamic s anywhere, since that would make me far more comfortable with 's implementation or even stabilization. Ironically, if that works, it's also the subset we could've implemented years earlier than we did, since most of the complexity, unknowns (and apparently bugs) are around dynamic s, not calling trait object methods on a dereference of .
That should be possible. I think everything that is necessary is performing the deref of the box as argument () instead of moving the box contents to a local first () That would also make it possible to call in cg_clif. Cranelift doesn't have alloca support, so the current MIR is untranslatable.
Hmm, but that's not trivially sound because it could lead to MIR calls where argument and return places overlap, which is UB. We'd potentially have to special-case it to derefs, but even then what's to stop someone from doing ? Maybe we could introduce a temporary for the return value instead, for these kinds of virtual calls? That should remove any potential overlap while allowing the call.