I would expect rough equivalence from a COW struct update vs initializing a new struct with existing values plus some new value.
Regardless, my primary complaint isn't that it's expensive during runtime, but that it's expensive during development for the developer.
If I have a struct with 14 values that could be mutated but are marked as immutable, then the developer basically needs to create 14 different copy/initialization/update functions to move the existing values and apply the new one.
Add a new value to the struct and we need to create one more (and probably go back and revise the original 14).
IOW, you spend a lot of time writing totally unnecessary boilerplate code.
Why unnecessary?
This article came about largely because like you I once thought such things were needed and proposed on Swift Evolution a mechanism for making such "best practice" immutable struct changes easier to accomplish... and was pretty firmly informed that iin Swift it wasn't really a best practice at all and that Swift's COW semantics provided the protection that was lacking in other languages.
https://forums.swift.org/t/prepitch-implementing-the-buildable-pattern-for-structs/21282