Implement default_mismatches_new lint
#16531
Open
+723
−114
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Re-opening #14234 Implement #14075. Prevents rust-lang/rust#135977.
What it does
If a type has an auto-derived
Defaulttrait and afn new() -> Self, this lint checks if thenew()method performs custom logic rather than callingSelf::default()Why is this bad?
Users expect the
new()method to be equivalent todefault(), so if theDefaulttrait is auto-derived, thenew()method should not perform custom logic. Otherwise, there is a risk of different behavior between the two instantiation methods.Example
Users are unlikely to notice that
MyStruct::new()andMyStruct::default()would produce different results. Thenew()method should use auto-deriveddefault()instead to be consistent:Alternatively, if the
new()method requires non-default initialization, implement a customDefault. This also allows you to mark thenew()implementation asconst:.stderrfile)cargo testpasses locallycargo dev update_lintscargo dev fmtchangelog: [
default_mismatches_new]: new lint to catchfn new() -> Selfmethod not matching theDefaultimplementationNotable cases in the wild
default()andnew()are actually different - likely was a bug that glob team wants to fix (per comments)new()creates cache withVec::with_capacity(), whereasdefault()usesVec::default(). Possibly a bug.Self(())-- should this be ignored?Self { _p: () }forstruct Identity { _p: () }-- probably better to use::default()TODO/TBD
fn new() -> Selfimplementations are OK? (rather than delegating toSelf::default())Selfis a unit typerustc_hir::hir::ImplItemof afn new() -> Self, get the body of that functionreturn Self::default();and no other logic (in all variants likeDefault::default(), etc.clippy_lints/src/default_constructed_unit_structs.rswhile trying to understand its logic - I think we may want to have ais_unit_type(ty)utility function?r? @samueltardieu
See also: non_canonical_partial_ord_impl lint