Well, let’s see:
- Nontrivial deinit, trivially copyable: (probably impossible)
- Nontrivial deinit, trivially movable, nontrivially copyable: strong class references
- Nontrivial deinit, trivially movable, non-Copyable: file handles, most Rust types
- Nontrivial deinit, nontrivial move: ObjC weak references, many C++ types
- Nontrivial deinit, non-movable: some C++ types, usually self-referential
And then:
- Trivial deinit, trivially copyable: integers
- Trivial deinit, trivially movable, nontrivially copyable: ??
- Trivial deinit, trivially movable, non-Copyable: some kind of token type
- Trivial deinit, nontrivial move: self-referential storage using pointers
- Trivial deinit, non-movable: tokens that hand out pointers? and self-referential storage that didn’t bother to provide a move operator
So even though there’s a missing cell here, I think it’s clear enough that there are valid uses in most of these combinations. Which might even be enough to split out “trivial deinit” as its own base thing (it’s the main requirement for a heterogeneous arena allocator, for example). We don’t currently have a formal notion of “non-movable” either, so it’s hard to speculate that far. But I do think it’s reasonable to not tie it to copying.