mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-12-11 22:02:55 +00:00
Add default_trait_access lint
This commit is contained in:
parent
26bc88d48c
commit
4866309f9d
6 changed files with 141 additions and 0 deletions
63
clippy_lints/src/default_trait_access.rs
Normal file
63
clippy_lints/src/default_trait_access.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use rustc::hir::*;
|
||||||
|
use rustc::lint::*;
|
||||||
|
|
||||||
|
use crate::utils::{match_def_path, opt_def_id, paths, span_lint_and_sugg};
|
||||||
|
|
||||||
|
|
||||||
|
/// **What it does:** Checks for literal calls to `Default::default()`.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
|
||||||
|
/// being gotten than the generic `Default`.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
/// ```rust
|
||||||
|
/// // Bad
|
||||||
|
/// let s: String = Default::default();
|
||||||
|
///
|
||||||
|
/// // Good
|
||||||
|
/// let s = String::default();
|
||||||
|
/// ```
|
||||||
|
declare_clippy_lint! {
|
||||||
|
pub DEFAULT_TRAIT_ACCESS,
|
||||||
|
style,
|
||||||
|
"checks for literal calls to Default::default()"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct DefaultTraitAccess;
|
||||||
|
|
||||||
|
impl LintPass for DefaultTraitAccess {
|
||||||
|
fn get_lints(&self) -> LintArray {
|
||||||
|
lint_array!(DEFAULT_TRAIT_ACCESS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
|
||||||
|
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
|
if_chain! {
|
||||||
|
if let ExprCall(ref path, ..) = expr.node;
|
||||||
|
if let ExprPath(ref qpath) = path.node;
|
||||||
|
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
|
||||||
|
if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD);
|
||||||
|
then {
|
||||||
|
match qpath {
|
||||||
|
QPath::Resolved(..) => {
|
||||||
|
// TODO: Work out a way to put "whatever the imported way of referencing
|
||||||
|
// this type in this file" rather than a fully-qualified type.
|
||||||
|
let replacement = format!("{}::default()", cx.tables.expr_ty(expr));
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
DEFAULT_TRAIT_ACCESS,
|
||||||
|
expr.span,
|
||||||
|
&format!("Calling {} is more clear than this expression", replacement),
|
||||||
|
"try",
|
||||||
|
replacement);
|
||||||
|
},
|
||||||
|
QPath::TypeRelative(..) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -111,6 +111,7 @@ pub mod collapsible_if;
|
||||||
pub mod const_static_lifetime;
|
pub mod const_static_lifetime;
|
||||||
pub mod copies;
|
pub mod copies;
|
||||||
pub mod cyclomatic_complexity;
|
pub mod cyclomatic_complexity;
|
||||||
|
pub mod default_trait_access;
|
||||||
pub mod derive;
|
pub mod derive;
|
||||||
pub mod doc;
|
pub mod doc;
|
||||||
pub mod double_comparison;
|
pub mod double_comparison;
|
||||||
|
@ -425,6 +426,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||||
reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
|
reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
|
||||||
reg.register_late_lint_pass(box unwrap::Pass);
|
reg.register_late_lint_pass(box unwrap::Pass);
|
||||||
reg.register_late_lint_pass(box duration_subsec::DurationSubsec);
|
reg.register_late_lint_pass(box duration_subsec::DurationSubsec);
|
||||||
|
reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess);
|
||||||
|
|
||||||
|
|
||||||
reg.register_lint_group("clippy_restriction", vec![
|
reg.register_lint_group("clippy_restriction", vec![
|
||||||
|
@ -512,6 +514,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||||
copies::IF_SAME_THEN_ELSE,
|
copies::IF_SAME_THEN_ELSE,
|
||||||
copies::IFS_SAME_COND,
|
copies::IFS_SAME_COND,
|
||||||
cyclomatic_complexity::CYCLOMATIC_COMPLEXITY,
|
cyclomatic_complexity::CYCLOMATIC_COMPLEXITY,
|
||||||
|
default_trait_access::DEFAULT_TRAIT_ACCESS,
|
||||||
derive::DERIVE_HASH_XOR_EQ,
|
derive::DERIVE_HASH_XOR_EQ,
|
||||||
double_comparison::DOUBLE_COMPARISONS,
|
double_comparison::DOUBLE_COMPARISONS,
|
||||||
double_parens::DOUBLE_PARENS,
|
double_parens::DOUBLE_PARENS,
|
||||||
|
@ -709,6 +712,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||||
block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT,
|
block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT,
|
||||||
collapsible_if::COLLAPSIBLE_IF,
|
collapsible_if::COLLAPSIBLE_IF,
|
||||||
const_static_lifetime::CONST_STATIC_LIFETIME,
|
const_static_lifetime::CONST_STATIC_LIFETIME,
|
||||||
|
default_trait_access::DEFAULT_TRAIT_ACCESS,
|
||||||
enum_variants::ENUM_VARIANT_NAMES,
|
enum_variants::ENUM_VARIANT_NAMES,
|
||||||
enum_variants::MODULE_INCEPTION,
|
enum_variants::MODULE_INCEPTION,
|
||||||
eq_op::OP_REF,
|
eq_op::OP_REF,
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub const C_VOID: [&str; 4] = ["std", "os", "raw", "c_void"];
|
||||||
pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"];
|
pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"];
|
||||||
pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"];
|
pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"];
|
||||||
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
|
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
|
||||||
|
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
|
||||||
pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
|
pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
|
||||||
pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
|
pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
|
||||||
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
|
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
|
||||||
|
|
39
tests/ui/default_trait_access.rs
Normal file
39
tests/ui/default_trait_access.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#![warn(default_trait_access)]
|
||||||
|
|
||||||
|
use std::default::Default as D2;
|
||||||
|
use std::string;
|
||||||
|
use std::default;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let s1: String = Default::default();
|
||||||
|
|
||||||
|
let s2 = String::default();
|
||||||
|
|
||||||
|
let s3: String = D2::default();
|
||||||
|
|
||||||
|
let s4: String = std::default::Default::default();
|
||||||
|
|
||||||
|
let s5 = string::String::default();
|
||||||
|
|
||||||
|
let s6: String = default::Default::default();
|
||||||
|
|
||||||
|
let s7 = std::string::String::default();
|
||||||
|
|
||||||
|
let s8: String = DefaultFactory::make_t_badly();
|
||||||
|
|
||||||
|
let s9: String = DefaultFactory::make_t_nicely();
|
||||||
|
|
||||||
|
println!("[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]", s1, s2, s3, s4, s5, s6, s7, s8, s9);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DefaultFactory;
|
||||||
|
|
||||||
|
impl DefaultFactory {
|
||||||
|
pub fn make_t_badly<T: Default>() -> T {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_t_nicely<T: Default>() -> T {
|
||||||
|
T::default()
|
||||||
|
}
|
||||||
|
}
|
34
tests/ui/default_trait_access.stderr
Normal file
34
tests/ui/default_trait_access.stderr
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
error: Calling std::string::String::default() is more clear than this expression
|
||||||
|
--> $DIR/default_trait_access.rs:8:22
|
||||||
|
|
|
||||||
|
8 | let s1: String = Default::default();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||||
|
|
|
||||||
|
= note: `-D default-trait-access` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: Calling std::string::String::default() is more clear than this expression
|
||||||
|
--> $DIR/default_trait_access.rs:12:22
|
||||||
|
|
|
||||||
|
12 | let s3: String = D2::default();
|
||||||
|
| ^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||||
|
|
||||||
|
error: Calling std::string::String::default() is more clear than this expression
|
||||||
|
--> $DIR/default_trait_access.rs:14:22
|
||||||
|
|
|
||||||
|
14 | let s4: String = std::default::Default::default();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||||
|
|
||||||
|
error: Calling std::string::String::default() is more clear than this expression
|
||||||
|
--> $DIR/default_trait_access.rs:18:22
|
||||||
|
|
|
||||||
|
18 | let s6: String = default::Default::default();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||||
|
|
||||||
|
error: Calling T::default() is more clear than this expression
|
||||||
|
--> $DIR/default_trait_access.rs:33:9
|
||||||
|
|
|
||||||
|
33 | Default::default()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: try: `T::default()`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
0
tests/ui/default_trait_access.stdout
Normal file
0
tests/ui/default_trait_access.stdout
Normal file
Loading…
Reference in a new issue