rust-lang / rust-lang/rust-clippy
Lint: Explicit destructor should necessiate not using #[derive(Clone)]
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
In C++, there is a concept called the Rule of three. It essentially means that if a class has any of those:
- Destructor
- Copy constructor
- Copy assignment operator
- Move constructor
- Move assignment operator
It should probably all five of those.
In Rust, the user cannot redefine moves, and copy assignment operator is Clone::clone_from which has a reasonable implementation if Clone::clone is implemented correctly. Therefore, the rule could be simplified to the Rule of two. In short, if a type has either one of those two, it should implement both.
Dropimplementation- non-trivial
Cloneimplementation
Non-trivial Clone implementation is a tricky thing. #[derive(Clone)] is trivial, but so is an explicit implementation that pretty much clones or copies every field (which is sometimes necessary due to https://github.com/rust-lang/rust/issues/26925 or to implement clone_from method). Also, an implementation that is *self is trivial. Determining whether a Clone implementation is trivial may be tricky.
In my opinion, an implementation that simply constructs the same structure while copying or cloning all fields or assigning value of the same type for ZSTs should be considered trivial (it's very likely an user will type _phantom: PhantomData instead of _phantom: self._phantom which is why ZSTs should have a special exception).
Having #[derive(Clone)] with Drop implementation is almost certainly a mistake, and so is having an explicit non-trivial Clone implementation without an explicit a destructor. The reason being is that implementing either of those implies that the type is managing resources, and the default implementation is going to be wrong here. Alternatively either of those is implemented for recursive data types (linked lists, trees, JSON objects) to prevent stack overflow while forgetting about the other one.
Note that having a Drop implementation while not implementing Clone at all is fine.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the issue description and investigate how Clippy represents existing lints for Drop and Clone. Define how trivial Clone implementations and ZST fields should be treated before choosing the lint scope; done means the behavior is specified and the proposed lint consistently flags the described mismatches without flagging the stated exceptions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100