I think probably the best way to go about this is to prove that the input is linearly typed and replace copy_ with a functional op that creates a copy of the tensor and then writes to it. This is basically how other functional tensor languages handle writes - like jax and numlin 1. You need to prove that the input is linearly typed (there are no other aliases to it) so that you don’t change the semantics of the program.
I maintain a pass 1 that does this logic for many inplace ops but does not yet handle copy_. I would accept a PR that adds a new operator similar to jax.ops.index_update and replaces copy_ with it when that can be proved safe.
Looking at apply_deltas 1, we initialize the tensor and then write to it so we would successively be able to remove copy_ from this function.