mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +00:00
Merge #3350
3350: Don't emit `new_without_default_derive` if an impl of Default exists regardless of generics r=oli-obk a=pengowen123 Fixes #2226 Co-authored-by: Owen Sanchez <pengowen816@gmail.com>
This commit is contained in:
commit
03f8899fa5
3 changed files with 43 additions and 5 deletions
|
@ -391,7 +391,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
reg.register_early_lint_pass(box int_plus_one::IntPlusOne);
|
reg.register_early_lint_pass(box int_plus_one::IntPlusOne);
|
||||||
reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional);
|
reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional);
|
||||||
reg.register_late_lint_pass(box unused_label::UnusedLabel);
|
reg.register_late_lint_pass(box unused_label::UnusedLabel);
|
||||||
reg.register_late_lint_pass(box new_without_default::NewWithoutDefault);
|
reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default());
|
||||||
reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone()));
|
reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone()));
|
||||||
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
|
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
|
||||||
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone()));
|
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone()));
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use crate::rustc::hir::def_id::DefId;
|
use crate::rustc::hir::def_id::DefId;
|
||||||
use crate::rustc::hir;
|
use crate::rustc::hir;
|
||||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
|
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
|
||||||
|
use crate::rustc::util::nodemap::NodeSet;
|
||||||
use crate::rustc::{declare_tool_lint, lint_array};
|
use crate::rustc::{declare_tool_lint, lint_array};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use crate::rustc::ty::{self, Ty};
|
use crate::rustc::ty::{self, Ty};
|
||||||
|
@ -91,8 +92,10 @@ declare_clippy_lint! {
|
||||||
"`fn new() -> Self` without `#[derive]`able `Default` implementation"
|
"`fn new() -> Self` without `#[derive]`able `Default` implementation"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Clone, Default)]
|
||||||
pub struct NewWithoutDefault;
|
pub struct NewWithoutDefault {
|
||||||
|
impling_types: Option<NodeSet>,
|
||||||
|
}
|
||||||
|
|
||||||
impl LintPass for NewWithoutDefault {
|
impl LintPass for NewWithoutDefault {
|
||||||
fn get_lints(&self) -> LintArray {
|
fn get_lints(&self) -> LintArray {
|
||||||
|
@ -130,13 +133,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
|
if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
|
||||||
|
let self_did = cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id));
|
||||||
let self_ty = cx.tcx
|
let self_ty = cx.tcx
|
||||||
.type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id)));
|
.type_of(self_did);
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if same_tys(cx, self_ty, return_ty(cx, id));
|
if same_tys(cx, self_ty, return_ty(cx, id));
|
||||||
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
|
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
|
||||||
if !implements_trait(cx, self_ty, default_trait_id, &[]);
|
|
||||||
then {
|
then {
|
||||||
|
if self.impling_types.is_none() {
|
||||||
|
let mut impls = NodeSet();
|
||||||
|
cx.tcx.for_each_impl(default_trait_id, |d| {
|
||||||
|
if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
|
||||||
|
if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def.did) {
|
||||||
|
impls.insert(node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.impling_types = Some(impls);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a Default implementation exists for the Self type, regardless of
|
||||||
|
// generics
|
||||||
|
if_chain! {
|
||||||
|
if let Some(ref impling_types) = self.impling_types;
|
||||||
|
if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def();
|
||||||
|
if self_def.did.is_local();
|
||||||
|
then {
|
||||||
|
let self_id = cx.tcx.hir.local_def_id_to_node_id(self_def.did.to_local());
|
||||||
|
if impling_types.contains(&self_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
|
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -107,4 +107,13 @@ impl IgnoreUnsafeNew {
|
||||||
pub unsafe fn new() -> Self { IgnoreUnsafeNew }
|
pub unsafe fn new() -> Self { IgnoreUnsafeNew }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OptionRefWrapper<'a, T: 'a>(Option<&'a T>);
|
||||||
|
|
||||||
|
impl<'a, T: 'a> OptionRefWrapper<'a, T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
OptionRefWrapper(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Loading…
Reference in a new issue