Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into rustup
Browse files Browse the repository at this point in the history
  • Loading branch information
flip1995 committed Jul 19, 2021
2 parents 1b0e578 + f467750 commit 26321b3
Show file tree
Hide file tree
Showing 40 changed files with 492 additions and 318 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2772,6 +2772,7 @@ Released 2018-09-13
[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
[`self_named_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructor
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
Expand Down
93 changes: 28 additions & 65 deletions clippy_lints/src/assign_ops.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method};
use clippy_utils::{higher, paths, sugg};
use clippy_utils::{binop_traits, sugg};
use clippy_utils::{eq_expr_value, trait_ref_of_method};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
Expand Down Expand Up @@ -85,71 +85,34 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps {
let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
let ty = cx.typeck_results().expr_ty(assignee);
let rty = cx.typeck_results().expr_ty(rhs);
macro_rules! ops {
($op:expr,
$cx:expr,
$ty:expr,
$rty:expr,
$($trait_name:ident),+) => {
match $op {
$(hir::BinOpKind::$trait_name => {
let [krate, module] = paths::OPS_MODULE;
let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
trait_id
} else {
return; // useless if the trait doesn't exist
};
// check that we are not inside an `impl AssignOp` of this exact operation
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
if_chain! {
if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
if trait_ref.path.res.def_id() == trait_id;
then { return; }
if_chain! {
if let Some((_, lang_item)) = binop_traits(op.node);
if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
if trait_ref_of_method(cx, parent_fn)
.map_or(true, |t| t.path.res.def_id() != trait_id);
if implements_trait(cx, ty, trait_id, &[rty.into()]);
then {
span_lint_and_then(
cx,
ASSIGN_OP_PATTERN,
expr.span,
"manual implementation of an assign operation",
|diag| {
if let (Some(snip_a), Some(snip_r)) =
(snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
{
diag.span_suggestion(
expr.span,
"replace it with",
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
Applicability::MachineApplicable,
);
}
implements_trait($cx, $ty, trait_id, &[$rty])
},)*
_ => false,
}
},
);
}
}
if ops!(
op.node,
cx,
ty,
rty.into(),
Add,
Sub,
Mul,
Div,
Rem,
And,
Or,
BitAnd,
BitOr,
BitXor,
Shr,
Shl
) {
span_lint_and_then(
cx,
ASSIGN_OP_PATTERN,
expr.span,
"manual implementation of an assign operation",
|diag| {
if let (Some(snip_a), Some(snip_r)) =
(snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
{
diag.span_suggestion(
expr.span,
"replace it with",
format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
Applicability::MachineApplicable,
);
}
},
);
}
};

let mut visitor = ExprVisitor {
Expand Down Expand Up @@ -206,7 +169,7 @@ fn lint_misrefactored_assign_op(
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
let a = &sugg::Sugg::hir(cx, assignee, "..");
let r = &sugg::Sugg::hir(cx, rhs, "..");
let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
let long = format!("{} = {}", snip_a, sugg::make_binop(op.node.into(), a, r));
diag.span_suggestion(
expr.span,
&format!(
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/eq_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) {
return;
}
if is_useless_with_eq_exprs(higher::binop(op.node)) && eq_expr_value(cx, left, right) {
if is_useless_with_eq_exprs(op.node.into()) && eq_expr_value(cx, left, right) {
span_lint(
cx,
EQ_OP,
Expand Down
2 changes: 0 additions & 2 deletions clippy_lints/src/implicit_hasher.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![cfg_attr(bootstrap, allow(rustc::default_hash_types))]

use std::borrow::Cow;
use std::collections::BTreeMap;

Expand Down
5 changes: 5 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ mod regex;
mod repeat_once;
mod returns;
mod self_assignment;
mod self_named_constructor;
mod semicolon_if_nothing_returned;
mod serde_api;
mod shadow;
Expand Down Expand Up @@ -900,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
returns::LET_AND_RETURN,
returns::NEEDLESS_RETURN,
self_assignment::SELF_ASSIGNMENT,
self_named_constructor::SELF_NAMED_CONSTRUCTOR,
semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
serde_api::SERDE_API_MISUSE,
shadow::SHADOW_REUSE,
Expand Down Expand Up @@ -1406,6 +1408,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(returns::LET_AND_RETURN),
LintId::of(returns::NEEDLESS_RETURN),
LintId::of(self_assignment::SELF_ASSIGNMENT),
LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR),
LintId::of(serde_api::SERDE_API_MISUSE),
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
Expand Down Expand Up @@ -1559,6 +1562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
LintId::of(returns::LET_AND_RETURN),
LintId::of(returns::NEEDLESS_RETURN),
LintId::of(self_named_constructor::SELF_NAMED_CONSTRUCTOR),
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
Expand Down Expand Up @@ -2101,6 +2105,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
let scripts = conf.allowed_scripts.clone();
store.register_early_pass(move || box disallowed_script_idents::DisallowedScriptIdents::new(&scripts));
store.register_late_pass(|| box strlen_on_c_strings::StrlenOnCStrings);
store.register_late_pass(move || box self_named_constructor::SelfNamedConstructor);
}

#[rustfmt::skip]
Expand Down
7 changes: 2 additions & 5 deletions clippy_lints/src/loops/manual_memcpy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,8 @@ struct MinifyingSugg<'a>(Sugg<'a>);

impl<'a> MinifyingSugg<'a> {
fn as_str(&self) -> &str {
// HACK: Don't sync to Clippy! Required because something with the `or_patterns` feature
// changed and this would now require parentheses.
match &self.0 {
Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) => s.as_ref(),
}
let (Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s)) = &self.0;
s.as_ref()
}

fn into_sugg(self) -> Sugg<'a> {
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/matches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ fn check_single_match_single_pattern(
expr: &Expr<'_>,
els: Option<&Expr<'_>>,
) {
if is_wild(&arms[1].pat) {
if is_wild(arms[1].pat) {
report_single_match_single_pattern(cx, ex, arms, expr, els);
}
}
Expand Down Expand Up @@ -1287,7 +1287,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
if let Some((b1_arm, b0_arms)) = arms.split_last();
if let Some(b0) = find_bool_lit(&b0_arms[0].body.kind, desugared);
if let Some(b1) = find_bool_lit(&b1_arm.body.kind, desugared);
if is_wild(&b1_arm.pat);
if is_wild(b1_arm.pat);
if b0 != b1;
let if_guard = &b0_arms[0].guard;
if if_guard.is_none() || b0_arms.len() == 1;
Expand Down
19 changes: 17 additions & 2 deletions clippy_lints/src/missing_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

use clippy_utils::attrs::is_doc_hidden;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast;
use if_chain::if_chain;
use rustc_ast::ast::{self, MetaItem, MetaItemKind};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
Expand Down Expand Up @@ -55,6 +56,20 @@ impl MissingDoc {
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
}

fn has_include(meta: Option<MetaItem>) -> bool {
if_chain! {
if let Some(meta) = meta;
if let MetaItemKind::List(list) = meta.kind;
if let Some(meta) = list.get(0);
if let Some(name) = meta.ident();
then {
name.name == sym::include
} else {
false
}
}
}

fn check_missing_docs_attrs(
&self,
cx: &LateContext<'_>,
Expand All @@ -80,7 +95,7 @@ impl MissingDoc {

let has_doc = attrs
.iter()
.any(|a| a.doc_str().is_some());
.any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
if !has_doc {
span_lint(
cx,
Expand Down
4 changes: 0 additions & 4 deletions clippy_lints/src/mutable_debug_assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
self.found = true;
return;
},
ExprKind::If(..) => {
self.found = true;
return;
},
ExprKind::Path(_) => {
if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
if adj
Expand Down
3 changes: 1 addition & 2 deletions clippy_lints/src/non_expressive_names.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use rustc_ast::ast::{
Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat,
PatKind,
Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind,
};
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
use rustc_lint::{EarlyContext, EarlyLintPass};
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/redundant_clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
visit_op(lhs);
visit_op(rhs);
}
},
_ => (),
}
}
Expand Down
91 changes: 91 additions & 0 deletions clippy_lints/src/self_named_constructor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::return_ty;
use clippy_utils::ty::{contains_adt_constructor, contains_ty};
use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
/// **What it does:** Warns when constructors have the same name as their types.
///
/// **Why is this bad?** Repeating the name of the type is redundant.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust,ignore
/// struct Foo {}
///
/// impl Foo {
/// pub fn foo() -> Foo {
/// Foo {}
/// }
/// }
/// ```
/// Use instead:
/// ```rust,ignore
/// struct Foo {}
///
/// impl Foo {
/// pub fn new() -> Foo {
/// Foo {}
/// }
/// }
/// ```
pub SELF_NAMED_CONSTRUCTOR,
style,
"method should not have the same name as the type it is implemented for"
}

declare_lint_pass!(SelfNamedConstructor => [SELF_NAMED_CONSTRUCTOR]);

impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructor {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
match impl_item.kind {
ImplItemKind::Fn(ref sig, _) => {
if sig.decl.implicit_self.has_implicit_self() {
return;
}
},
_ => return,
}

let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
let item = cx.tcx.hir().expect_item(parent);
let self_ty = cx.tcx.type_of(item.def_id);
let ret_ty = return_ty(cx, impl_item.hir_id());

// Do not check trait impls
if matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) {
return;
}

// Ensure method is constructor-like
if let Some(self_adt) = self_ty.ty_adt_def() {
if !contains_adt_constructor(ret_ty, self_adt) {
return;
}
} else if !contains_ty(ret_ty, self_ty) {
return;
}

if_chain! {
if let Some(self_def) = self_ty.ty_adt_def();
if let Some(self_local_did) = self_def.did.as_local();
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id);
let type_name = x.ident.name.as_str().to_lowercase();
if impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace("_", "") == type_name;

then {
span_lint(
cx,
SELF_NAMED_CONSTRUCTOR,
impl_item.span,
&format!("constructor `{}` has the same name as the type", impl_item.ident.name),
);
}
}
}
}
Loading

0 comments on commit 26321b3

Please sign in to comment.