# Why can I \`deepcopy(nothing)\` but not \`copy(nothing)\`?

**URL:** https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429
**Category:** General Usage
**Tags:** copy, deepcopy
**Created:** [April 2, 2024, 4:28pm UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429 "2024-04-02T16:28:30Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [April 2, 2024, 4:28pm UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429/1 "2024-04-02T16:28:30Z")

</div>

I know it sounds silly but it is currently blocking an AD package of mine ^^

```julia
julia> deepcopy(nothing)

julia> copy(nothing)
ERROR: MethodError: no method matching copy(::Nothing)

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [April 2, 2024, 6:31pm UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429/2 "2024-04-02T18:31:01Z")

</div>

While we’re at it, one can’t `copy(missing)` either. While there isn’t a meaningful use of `copy` for these, it seems “harmless” to extend `copy` to them (like we already do for `Number`).

More broadly, there’s a philosophical question of whether an object that cannot alias _should_ have `copy` defined. Pragmatically, however, it’s darn convenient to be able to “`copy`” any object even when this is a no-op so that one can write generic code (I imagine this is your situation). `Number`s fit under this pragmatic case, just like we allow one to `getindex` them.

Going even more broadly, there’s a question of exactly what sense you want a copy. For example, what does it mean to `copy` an `IOStream`? Does `deepcopy` even do what you want?

Now back to non-esoteric cases. I guess one part of the reason many methods don’t exist is that this is pretty whack-a-mole. A generic fallback `copy` can’t exist because there’s no way to ensure it properly de-aliases instances in a semantically-correct way. It’s hard to anticipate every `Base` type one might try to `copy` so that a valid method can be added, and hard to ensure every package out there also defines a valid `copy` on its types. So when they fail, one can either replace `copy` (see below) or turn to piracy (never a durable solution).

* * *

I can’t find where I actually used it right now, but I’ve definitely used patterns like

```julia
maybecopy(x) = copy(x) # fallback
maybecopy(x::Tuple) = maybecopy.(x) # copy each entry, like an Array
maybecopy(x::NamedTuple{N}) where N = NamedTuple{N}(maybecopy(Tuple(x))) # copy underlying tuple
for T in [Nothing, Missing, Symbol, String, #= etc =#]
	@eval maybecopy(x::$T) = x
end
# add methods as MethodErrors emerge

```

to make a usable `copy`-like function for generic code. For a tiny bit more smarts, you can replace the fallback with either of

```julia
# we know the final option will throw a MethodError that we can try to deal with
maybecopy(x::T) where T = hasmethod(copy, Tuple{T}) ? copy(x) : isbitstype(T) ? x : copy(x)

# deepcopy is reliable but has devastatingly poor performance
maybecopy(x::T) where T = hasmethod(copy, Tuple{T}) ? copy(x) : isbitstype(T) ? x : deepcopy(x)

```

so that at least a good number of basic types are covered. There’s a chance that no-op `copy` of even an `isbitstype` is somehow not correct for some esoteric types, but I can’t think of any so I include it here. `deepcopy` should be avoided (for performance) so I’d recommend adding what methods you can find before enabling it.

But if your code needs to work with `Base.copy` directly (i.e., for user-passed functions) then you obviously can’t use a pattern like this (maybe you _could_ with `Cassette.jl`? but that feels excessive and possibly still fragile).

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [April 2, 2024, 7:20pm UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429/3 "2024-04-02T19:20:33Z")

</div>

See previous discussion of `copy` for immutable objects:

- [Coordinating community efforts to enrich function docs - #8 by johnmyleswhite](https://discourse.julialang.org/t/coordinating-community-efforts-to-enrich-function-docs/80338/8)
- [copy not implemented for String · Issue #31995 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/31995)
- [Define copy for immutable values · Issue #45143 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/45143)

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [April 3, 2024, 12:08am UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429/4 "2024-04-03T00:08:15Z")

</div>

Why do you need that? Cannot you call `ismutable` before and decide if you will copy or not based on that?

---

<div class="post-metadata">

### Author: ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)
#### Post date: [April 3, 2024, 1:47am UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429/5 "2024-04-03T01:47:54Z")

</div>

No because `ismutable` just checks if the object’s type is a mutable type, which might not be the intended meaning of “is it mutable”. For example

```julia
julia> struct A
           x
       end

julia> ismutable(A([]))
false

```

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [April 3, 2024, 6:11am UTC](https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429/6 "2024-04-03T06:11:47Z")

</div>

> [@Henrique\_Becker](#):
>
> Why do you need that? Cannot you call `ismutable` before and decide if you will copy or not based on that?

In my case, because I wanna differentiate through a mutable function `f!(y, x)` which returns `nothing` since it does the modifications in-place.  
The experimental Tapir.jl package that I use copies the output of `f!` regardless of what it is, hence my surprise when I discovered this loophole.
