I think your second paragraph is a misinterpretation of how Rust works.
Everything isn’t implicitly Drop. Drop is an explicit cleanup mechanism that types can opt into.
If it helps you to think of it conceptually as everything having an implicit no-op Drop, then I guess that’s fine, but that’s not what is happening.
There is an automatic Drop “glue code” for types that contain types that implement Drop, so that those will get called, of course. But `i32` does not have Drop, at all.
> Even things that are Copy are implicitly Drop, it's just that the copy is dropped instead of the value.
You cannot implement Drop on a Copy type, so Drop literally never gets called on Copy types. You can’t put non-Copy types inside a Copy type, so there isn’t even Drop glue code. And no, it isn’t implicitly Drop at all! And it has nothing to do with a copy being dropped instead of the original value. Drop isn’t a universal trait.
I also seem to remember in the early post-1.0 days that whether a type implemented Drop or not would significantly impact lifetime analysis, requiring some occasionally obtuse workarounds. Rust lifetime analysis accepts many more correct solutions these days, and it has been awhile since I wrote a lot of Rust code, so I don’t recall how it is these days.
> If it helps you to think of it conceptually as everything having an implicit no-op Drop, then I guess that’s fine, but that’s not what is happening in the generated code.
I understand that types that don't implement Drop do not literally have an implicit `Drop` trait implemented for them by the compiler.
What I meant is that there is no "undroppable" type in Rust: the best you can do is make the type panic in a custom Drop implementation, but any function that takes ownership of a value is effectively described as forwarding, dropping, or forgetting that value based on the lifetime/type of its return. In other words, `mem::forget` can only be defined in terms of Drop (or default drop behavior for a type) in terms of ownership semantics, because its signature admits no other possibilities.
> In other words, `mem::forget` can only be defined in terms of Drop (or default drop behavior for a type) in terms of ownership semantics, because its signature admits no other possibilities.
But again, Drop is a destructor trait. It might be confusing that this shares a name with the concept of "dropping" in Rust, which is when a value goes out of scope, but they're not the same thing. Not every value has Drop, and mem::drop doesn't just work for values that are Drop. It is not defined in terms of Drop, but just Rust's ownership semantics.
Although I am disappointed that the automatically generated Drop glue doesn't "count" for this purpose, and there isn't a higher level Drop trait, so this isn't a fully general solution.
I also don't know where the concept of "undroppable" came from for this conversation. Taken literally, that would mean that the compiler would emit an error any time a value of that type would need to be dropped, so those values could only exist in functions that either return them or return `!`, or as global static values. I never suggested that was a possibility, and Rust does not support types that are undroppable, but it does support types that are not Drop.
Thanks for the explanation! Yeah, I'm realizing that I'm using these terms ambiguously: I do understand the difference between dropping and Drop, but I tend to think (incorrectly!) of the latter as an "implementation" of the former, when it really isn't.
Everything isn’t implicitly Drop. Drop is an explicit cleanup mechanism that types can opt into.
If it helps you to think of it conceptually as everything having an implicit no-op Drop, then I guess that’s fine, but that’s not what is happening.
There is an automatic Drop “glue code” for types that contain types that implement Drop, so that those will get called, of course. But `i32` does not have Drop, at all.
> Even things that are Copy are implicitly Drop, it's just that the copy is dropped instead of the value.
You cannot implement Drop on a Copy type, so Drop literally never gets called on Copy types. You can’t put non-Copy types inside a Copy type, so there isn’t even Drop glue code. And no, it isn’t implicitly Drop at all! And it has nothing to do with a copy being dropped instead of the original value. Drop isn’t a universal trait.
I also seem to remember in the early post-1.0 days that whether a type implemented Drop or not would significantly impact lifetime analysis, requiring some occasionally obtuse workarounds. Rust lifetime analysis accepts many more correct solutions these days, and it has been awhile since I wrote a lot of Rust code, so I don’t recall how it is these days.