Merge commit '09ac14c901' into clippyup

This commit is contained in:
Philipp Krones 2023-11-02 17:35:56 +01:00
parent aae86ccc47
commit 77c1e3aaa1
418 changed files with 4900 additions and 3588 deletions

View file

@ -24,11 +24,11 @@ declare_clippy_lint! {
/// using absolute paths is the proper way of referencing items in one.
///
/// ### Example
/// ```rust
/// ```no_run
/// let x = std::f64::consts::PI;
/// ```
/// Use any of the below instead, or anything else:
/// ```rust
/// ```no_run
/// use std::f64;
/// use std::f64::consts;
/// use std::f64::consts::PI;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{trim_span, walk_span_to_context};
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
use rustc_errors::Applicability;
@ -17,11 +17,11 @@ declare_clippy_lint! {
/// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
///
/// ### Example
/// ```rust
/// ```no_run
/// let _ = 'a'..'z';
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let _ = 'a'..='z';
/// ```
#[clippy::version = "1.68.0"]
@ -82,33 +82,20 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
(
Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
)
| (
) | (
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
)
| (
) | (
Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
)
)
&& !in_external_macro(cx.sess(), span)
{
span_lint_and_then(
cx,
ALMOST_COMPLETE_RANGE,
span,
"almost complete ascii range",
|diag| {
if let Some((span, sugg)) = sugg {
diag.span_suggestion(
span,
"use an inclusive range",
sugg,
Applicability::MaybeIncorrect,
);
}
span_lint_and_then(cx, ALMOST_COMPLETE_RANGE, span, "almost complete ascii range", |diag| {
if let Some((span, sugg)) = sugg {
diag.span_suggestion(span, "use an inclusive range", sugg, Applicability::MaybeIncorrect);
}
);
});
}
}

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::msrvs::{self, Msrv};
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -24,12 +24,12 @@ declare_clippy_lint! {
/// issue](https://github.com/rust-lang/rust/issues).
///
/// ### Example
/// ```rust
/// ```no_run
/// let x = 3.14;
/// let y = 1_f64 / x;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let x = std::f32::consts::PI;
/// let y = std::f64::consts::FRAC_1_PI;
/// ```

View file

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::cell::RefCell;
/// # use std::sync::Arc;
///
@ -62,19 +62,21 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
ARC_WITH_NON_SEND_SYNC,
expr.span,
"usage of an `Arc` that is not `Send` or `Sync`",
|diag| with_forced_trimmed_paths!({
if !is_send {
diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`"));
}
if !is_sync {
diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`"));
}
|diag| {
with_forced_trimmed_paths!({
if !is_send {
diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`"));
}
if !is_sync {
diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`"));
}
diag.note(format!("required for `{ty}` to implement `Send` and `Sync`"));
diag.note(format!("required for `{ty}` to implement `Send` and `Sync`"));
diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`");
}
));
diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`");
});
},
);
}
}
}

View file

@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
return;
}
}
let semicolon = if is_expr_final_block_expr(cx.tcx, e) {";"} else {""};
let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
let mut app = Applicability::MachineApplicable;
match method_segment.ident.as_str() {
"is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => {
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
),
app,
);
}
},
"is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => {
span_lint_and_sugg(
cx,
@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
),
app,
);
}
},
_ => (),
};
}

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::implements_trait;
use rustc_errors::Applicability;
use rustc_hir::{CoroutineSource, Body, BodyId, CoroutineKind, ExprKind, QPath};
use rustc_hir::{Body, BodyId, CoroutineKind, CoroutineSource, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -15,7 +15,7 @@ declare_clippy_lint! {
/// An await is likely missing.
///
/// ### Example
/// ```rust
/// ```no_run
/// async fn foo() {}
///
/// fn bar() {
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// async fn foo() {}
///
/// fn bar() {

View file

@ -1,9 +1,9 @@
//! checks for attributes
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_from_proc_macro;
use clippy_utils::macros::{is_panic, macro_backtrace};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use if_chain::if_chain;
use rustc_ast::token::{Token, TokenKind};
@ -129,7 +129,7 @@ declare_clippy_lint! {
/// a valid semver. Failing that, the contained information is useless.
///
/// ### Example
/// ```rust
/// ```no_run
/// #[deprecated(since = "forever")]
/// fn something_else() { /* ... */ }
/// ```
@ -156,14 +156,14 @@ declare_clippy_lint! {
/// currently works for basic cases but is not perfect.
///
/// ### Example
/// ```rust
/// ```no_run
/// #[allow(dead_code)]
///
/// fn not_quite_good_code() { }
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// // Good (as inner attribute)
/// #![allow(dead_code)]
///
@ -198,25 +198,25 @@ declare_clippy_lint! {
/// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
///
/// ### Example
/// ```rust
/// ```no_run
/// /// Some doc comment with a blank line after it.
///
/// fn not_quite_good_code() { }
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// /// Good (no blank line)
/// fn this_is_fine() { }
/// ```
///
/// ```rust
/// ```no_run
/// // Good (convert to a regular comment)
///
/// fn this_is_fine_too() { }
/// ```
///
/// ```rust
/// ```no_run
/// //! Good (convert to a comment on an inner attribute)
///
/// fn this_is_fine_as_well() { }
@ -236,12 +236,12 @@ declare_clippy_lint! {
/// These lints should only be enabled on a lint-by-lint basis and with careful consideration.
///
/// ### Example
/// ```rust
/// ```no_run
/// #![deny(clippy::restriction)]
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #![deny(clippy::as_conversions)]
/// ```
#[clippy::version = "1.47.0"]
@ -265,13 +265,13 @@ declare_clippy_lint! {
/// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
///
/// ### Example
/// ```rust
/// ```no_run
/// #[cfg_attr(rustfmt, rustfmt_skip)]
/// fn main() { }
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #[rustfmt::skip]
/// fn main() { }
/// ```
@ -290,13 +290,13 @@ declare_clippy_lint! {
/// by the conditional compilation engine.
///
/// ### Example
/// ```rust
/// ```no_run
/// #[cfg(linux)]
/// fn conditional() { }
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # mod hidden {
/// #[cfg(target_os = "linux")]
/// fn conditional() { }
@ -325,14 +325,14 @@ declare_clippy_lint! {
/// ensure that others understand the reasoning
///
/// ### Example
/// ```rust
/// ```no_run
/// #![feature(lint_reasons)]
///
/// #![allow(clippy::some_lint)]
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #![feature(lint_reasons)]
///
/// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")]
@ -352,7 +352,7 @@ declare_clippy_lint! {
/// panicking with the expected message, and not another unrelated panic.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn random() -> i32 { 0 }
///
/// #[should_panic]
@ -363,7 +363,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// fn random() -> i32 { 0 }
///
/// #[should_panic = "attempt to divide by zero"]
@ -386,13 +386,13 @@ declare_clippy_lint! {
/// If there is only one condition, no need to wrap it into `any` or `all` combinators.
///
/// ### Example
/// ```rust
/// ```no_run
/// #[cfg(any(unix))]
/// pub struct Bar;
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #[cfg(unix)]
/// pub struct Bar;
/// ```
@ -409,16 +409,16 @@ declare_clippy_lint! {
///
/// ### Why is this bad?
/// Misspelling `feature` as `features` can be sometimes hard to spot. It
/// may cause conditional compilation not work quitely.
/// may cause conditional compilation not work quietly.
///
/// ### Example
/// ```rust
/// ```no_run
/// #[cfg(features = "some-feature")]
/// fn conditional() { }
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #[cfg(feature = "some-feature")]
/// fn conditional() { }
/// ```
@ -602,9 +602,26 @@ fn check_should_panic_reason(cx: &LateContext<'_>, attr: &Attribute) {
if let AttrArgs::Delimited(args) = &normal_attr.item.args
&& let mut tt_iter = args.tokens.trees()
&& let Some(TokenTree::Token(Token { kind: TokenKind::Ident(sym::expected, _), .. }, _)) = tt_iter.next()
&& let Some(TokenTree::Token(Token { kind: TokenKind::Eq, .. }, _)) = tt_iter.next()
&& let Some(TokenTree::Token(Token { kind: TokenKind::Literal(_), .. }, _)) = tt_iter.next()
&& let Some(TokenTree::Token(
Token {
kind: TokenKind::Ident(sym::expected, _),
..
},
_,
)) = tt_iter.next()
&& let Some(TokenTree::Token(
Token {
kind: TokenKind::Eq, ..
},
_,
)) = tt_iter.next()
&& let Some(TokenTree::Token(
Token {
kind: TokenKind::Literal(_),
..
},
_,
)) = tt_iter.next()
{
// `#[should_panic(expected = "..")]` found, good
return;
@ -914,7 +931,9 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
for item in items {
if let NestedMetaItem::MetaItem(meta) = item {
if meta.has_name(sym!(features)) && let Some(val) = meta.value_str() {
if meta.has_name(sym!(features))
&& let Some(val) = meta.value_str()
{
span_lint_and_sugg(
cx,
MAYBE_MISUSED_CFG,
@ -933,16 +952,16 @@ fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
}
fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
if attr.has_name(sym::cfg) &&
let Some(items) = attr.meta_item_list()
if attr.has_name(sym::cfg)
&& let Some(items) = attr.meta_item_list()
{
check_nested_cfg(cx, &items);
}
}
fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) {
if attr.has_name(sym::cfg) &&
let Some(items) = attr.meta_item_list()
if attr.has_name(sym::cfg)
&& let Some(items) = attr.meta_item_list()
{
check_nested_misused_cfg(cx, &items);
}

View file

@ -1,15 +1,14 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_hir::{CoroutineSource, Body, CoroutineKind};
use rustc_hir::{Body, CoroutineKind, CoroutineSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::CoroutineLayout;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
use crate::utils::conf::DisallowedPath;
declare_clippy_lint! {
/// ### What it does
/// Checks for calls to await while holding a non-async-aware MutexGuard.
@ -29,7 +28,7 @@ declare_clippy_lint! {
/// to wrap the `.lock()` call in a block instead of explicitly dropping the guard.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::sync::Mutex;
/// # async fn baz() {}
/// async fn foo(x: &Mutex<u32>) {
@ -47,7 +46,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::sync::Mutex;
/// # async fn baz() {}
/// async fn foo(x: &Mutex<u32>) {
@ -87,7 +86,7 @@ declare_clippy_lint! {
/// to wrap the `.borrow[_mut]()` call in a block instead of explicitly dropping the ref.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::cell::RefCell;
/// # async fn baz() {}
/// async fn foo(x: &RefCell<u32>) {
@ -105,7 +104,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::cell::RefCell;
/// # async fn baz() {}
/// async fn foo(x: &RefCell<u32>) {
@ -151,7 +150,7 @@ declare_clippy_lint! {
/// ]
/// ```
///
/// ```rust
/// ```no_run
/// # async fn baz() {}
/// struct CustomLockType;
/// struct OtherCustomLockType;

View file

@ -21,7 +21,7 @@ declare_clippy_lint! {
/// Style, using blocks in the condition makes it hard to read.
///
/// ### Examples
/// ```rust
/// ```no_run
/// # fn somefunc() -> bool { true };
/// if { true } { /* ... */ }
///
@ -29,7 +29,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # fn somefunc() -> bool { true };
/// if true { /* ... */ }
///

View file

@ -18,13 +18,13 @@ declare_clippy_lint! {
/// It is shorter to use the equivalent.
///
/// ### Example
/// ```rust
/// ```no_run
/// assert_eq!("a".is_empty(), false);
/// assert_ne!("a".is_empty(), true);
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// assert!(!"a".is_empty());
/// ```
#[clippy::version = "1.53.0"]

View file

@ -21,7 +21,7 @@ declare_clippy_lint! {
/// See https://doc.rust-lang.org/std/primitive.bool.html#impl-From%3Cbool%3E
///
/// ### Example
/// ```rust
/// ```no_run
/// # let condition = false;
/// if condition {
/// 1_i64
@ -30,12 +30,12 @@ declare_clippy_lint! {
/// };
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # let condition = false;
/// i64::from(condition);
/// ```
/// or
/// ```rust
/// ```no_run
/// # let condition = false;
/// condition as i64;
/// ```
@ -55,7 +55,11 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
}
fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
if let Some(If { cond, then, r#else: Some(r#else) }) = If::hir(expr)
if let Some(If {
cond,
then,
r#else: Some(r#else),
}) = If::hir(expr)
&& let Some(then_lit) = int_literal(then)
&& let Some(else_lit) = int_literal(r#else)
{
@ -90,19 +94,18 @@ fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>
let into_snippet = snippet.clone().maybe_par();
let as_snippet = snippet.as_ty(ty);
span_lint_and_then(cx,
span_lint_and_then(
cx,
BOOL_TO_INT_WITH_IF,
expr.span,
"boolean to int conversion using if",
|diag| {
diag.span_suggestion(
expr.span,
"replace with from",
suggestion,
applicability,
);
diag.note(format!("`{as_snippet}` or `{into_snippet}.into()` can also be valid options"));
});
diag.span_suggestion(expr.span, "replace with from", suggestion, applicability);
diag.note(format!(
"`{as_snippet}` or `{into_snippet}.into()` can also be valid options"
));
},
);
};
}
@ -110,7 +113,7 @@ fn check_if_else<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>
fn int_literal<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>) -> Option<&'tcx rustc_hir::Expr<'tcx>> {
if let ExprKind::Block(block, _) = expr.kind
&& let Block {
stmts: [], // Shouldn't lint if statements with side effects
stmts: [], // Shouldn't lint if statements with side effects
expr: Some(expr),
..
} = block

View file

@ -472,8 +472,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
self.bool_expr(e);
},
ExprKind::Unary(UnOp::Not, inner) => {
if let ExprKind::Unary(UnOp::Not, ex) = inner.kind &&
!self.cx.typeck_results().node_types()[ex.hir_id].is_bool() {
if let ExprKind::Unary(UnOp::Not, ex) = inner.kind
&& !self.cx.typeck_results().node_types()[ex.hir_id].is_bool()
{
return;
}
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
@ -500,10 +501,10 @@ struct NotSimplificationVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind &&
!inner.span.from_expansion() &&
let Some(suggestion) = simplify_not(self.cx, inner)
&& self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind
&& !inner.span.from_expansion()
&& let Some(suggestion) = simplify_not(self.cx, inner)
&& self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
{
span_lint_and_sugg(
self.cx,

View file

@ -19,7 +19,7 @@ declare_clippy_lint! {
///
/// ### Known problems
/// False negative on such code:
/// ```
/// ```no_run
/// let x = &12;
/// let addr_x = &x as *const _ as usize;
/// let addr_y = &&*x as *const _ as usize; // assert ok now, and lint triggered.
@ -28,14 +28,14 @@ declare_clippy_lint! {
/// ```
///
/// ### Example
/// ```rust
/// ```no_run
/// let s = &String::new();
///
/// let a: &String = &* s;
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let s = &String::new();
/// let a: &String = s;
/// ```

View file

@ -24,11 +24,11 @@ declare_clippy_lint! {
/// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
///
/// ### Example
/// ```rust
/// ```no_run
/// let x: Box<String> = Box::new(Default::default());
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let x: Box<String> = Box::default();
/// ```
#[clippy::version = "1.66.0"]
@ -61,9 +61,9 @@ impl LateLintPass<'_> for BoxDefault {
} else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
} else {
return
return;
},
Applicability::MachineApplicable
Applicability::MachineApplicable,
);
}
}
@ -110,7 +110,8 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
Node::Expr(Expr {
kind: ExprKind::Call(path, args),
..
}) | Node::Block(Block {
})
| Node::Block(Block {
expr:
Some(Expr {
kind: ExprKind::Call(path, args),
@ -119,10 +120,10 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
..
}),
) => {
if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) &&
let Some(sig) = expr_sig(cx, path) &&
let Some(input) = sig.input(index) &&
!cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait()
if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
&& let Some(sig) = expr_sig(cx, path)
&& let Some(input) = sig.input(index)
&& !cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait()
{
input.no_bound_vars().is_some()
} else {

View file

@ -9,12 +9,19 @@ use rustc_middle::ty::{self, Ty, TypeAndMut};
use super::AS_PTR_CAST_MUT;
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>) {
if let ty::RawPtr(ptrty @ TypeAndMut { mutbl: Mutability::Mut, .. }) = cast_to.kind()
&& let ty::RawPtr(TypeAndMut { mutbl: Mutability::Not, .. }) =
cx.typeck_results().node_type(cast_expr.hir_id).kind()
if let ty::RawPtr(
ptrty @ TypeAndMut {
mutbl: Mutability::Mut, ..
},
) = cast_to.kind()
&& let ty::RawPtr(TypeAndMut {
mutbl: Mutability::Not, ..
}) = cx.typeck_results().node_type(cast_expr.hir_id).kind()
&& let ExprKind::MethodCall(method_name, receiver, [], _) = cast_expr.peel_blocks().kind
&& method_name.ident.name == rustc_span::sym::as_ptr
&& let Some(as_ptr_did) = cx.typeck_results().type_dependent_def_id(cast_expr.peel_blocks().hir_id)
&& let Some(as_ptr_did) = cx
.typeck_results()
.type_dependent_def_id(cast_expr.peel_blocks().hir_id)
&& let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity()
&& let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next()
&& let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind()
@ -30,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
&format!("casting the result of `as_ptr` to *{ptrty}"),
"replace with",
format!("{recv}.as_mut_ptr()"),
applicability
applicability,
);
}
}

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::in_constant;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability;

View file

@ -26,8 +26,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
// There probably is no obvious reason to do this, just to be consistent with `as` cases.
&& !is_hir_ty_cfg_dependant(cx, cast_to)
{
let (cast_from, cast_to) =
(cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
}
}
@ -81,9 +80,9 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
cx.tcx.get_diagnostic_name(def_id),
Some(
sym::ptr_write_unaligned
| sym::ptr_read_unaligned
| sym::intrinsics_unaligned_volatile_load
| sym::intrinsics_unaligned_volatile_store
| sym::ptr_read_unaligned
| sym::intrinsics_unaligned_volatile_load
| sym::intrinsics_unaligned_volatile_store
)
)
{

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source;
use if_chain::if_chain;
use rustc_ast::Mutability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use if_chain::if_chain;
use rustc_errors::Applicability;

View file

@ -22,8 +22,8 @@ mod unnecessary_cast;
mod utils;
mod zero_ptr;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::is_hir_ty_cfg_dependant;
use clippy_utils::msrvs::{self, Msrv};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@ -45,7 +45,7 @@ declare_clippy_lint! {
/// those places in the code.
///
/// ### Example
/// ```rust
/// ```no_run
/// let x = u64::MAX;
/// x as f64;
/// ```
@ -67,7 +67,7 @@ declare_clippy_lint! {
/// as a one-time check to see where numerical wrapping can arise.
///
/// ### Example
/// ```rust
/// ```no_run
/// let y: i8 = -1;
/// y as u128; // will return 18446744073709551615
/// ```
@ -90,13 +90,13 @@ declare_clippy_lint! {
/// checks could be beneficial.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn as_u8(x: u64) -> u8 {
/// x as u8
/// }
/// ```
/// Use instead:
/// ```
/// ```no_run
/// fn as_u8(x: u64) -> u8 {
/// if let Ok(x) = u8::try_from(x) {
/// x
@ -132,7 +132,7 @@ declare_clippy_lint! {
/// example below.
///
/// ### Example
/// ```rust
/// ```no_run
/// u32::MAX as i32; // will yield a value of `-1`
/// ```
#[clippy::version = "pre 1.29.0"]
@ -155,7 +155,7 @@ declare_clippy_lint! {
/// people reading the code to know that the conversion is lossless.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn as_u64(x: u8) -> u64 {
/// x as u64
/// }
@ -163,7 +163,7 @@ declare_clippy_lint! {
///
/// Using `::from` would look like this:
///
/// ```rust
/// ```no_run
/// fn as_u64(x: u8) -> u64 {
/// u64::from(x)
/// }
@ -191,14 +191,14 @@ declare_clippy_lint! {
/// intermediate references, raw pointers and trait objects may or may not work.
///
/// ### Example
/// ```rust
/// ```no_run
/// let _ = 2i32 as i32;
/// let _ = 0.5 as f32;
/// ```
///
/// Better:
///
/// ```rust
/// ```no_run
/// let _ = 2_i32;
/// let _ = 0.5_f32;
/// ```
@ -223,7 +223,7 @@ declare_clippy_lint! {
/// u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis.
///
/// ### Example
/// ```rust
/// ```no_run
/// let _ = (&1u8 as *const u8) as *const u16;
/// let _ = (&mut 1u8 as *mut u8) as *mut u16;
///
@ -249,13 +249,13 @@ declare_clippy_lint! {
/// Casting to isize also doesn't make sense since there are no signed addresses.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn fun() -> i32 { 1 }
/// let _ = fun as i64;
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # fn fun() -> i32 { 1 }
/// let _ = fun as usize;
/// ```
@ -276,7 +276,7 @@ declare_clippy_lint! {
/// a comment) to perform the truncation.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn fn1() -> i16 {
/// 1
/// };
@ -284,7 +284,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// // Cast to usize first, then comment with the reason for the truncation
/// fn fn1() -> i16 {
/// 1
@ -310,7 +310,7 @@ declare_clippy_lint! {
/// pointer casts in your code.
///
/// ### Example
/// ```rust
/// ```no_run
/// // fn1 is cast as `usize`
/// fn fn1() -> u16 {
/// 1
@ -319,7 +319,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// // maybe you intended to call the function?
/// fn fn2() -> u16 {
/// 1
@ -378,14 +378,14 @@ declare_clippy_lint! {
/// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`.
///
/// ### Example
/// ```rust
/// ```no_run
/// let ptr: *const u32 = &42_u32;
/// let mut_ptr: *mut u32 = &mut 42_u32;
/// let _ = ptr as *const i32;
/// let _ = mut_ptr as *mut i32;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let ptr: *const u32 = &42_u32;
/// let mut_ptr: *mut u32 = &mut 42_u32;
/// let _ = ptr.cast::<i32>();
@ -408,13 +408,13 @@ declare_clippy_lint! {
/// type.
///
/// ### Example
/// ```rust
/// ```no_run
/// let ptr: *const u32 = &42_u32;
/// let mut_ptr = ptr as *mut u32;
/// let ptr = mut_ptr as *const u32;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let ptr: *const u32 = &42_u32;
/// let mut_ptr = ptr.cast_mut();
/// let ptr = mut_ptr.cast_const();
@ -434,7 +434,7 @@ declare_clippy_lint! {
/// The resulting integral value will not match the value of the variant it came from.
///
/// ### Example
/// ```rust
/// ```no_run
/// enum E { X = 256 };
/// let _ = E::X as u8;
/// ```
@ -457,7 +457,7 @@ declare_clippy_lint! {
///
/// ### Example
/// // Missing data
/// ```rust
/// ```no_run
/// let a = [1_i32, 2, 3, 4];
/// let p = &a as *const [i32] as *const [u8];
/// unsafe {
@ -465,7 +465,7 @@ declare_clippy_lint! {
/// }
/// ```
/// // Undefined Behavior (note: also potential alignment issues)
/// ```rust
/// ```no_run
/// let a = [1_u8, 2, 3, 4];
/// let p = &a as *const [u8] as *const [u32];
/// unsafe {
@ -473,7 +473,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length
/// ```rust
/// ```no_run
/// let a = [1_i32, 2, 3, 4];
/// let old_ptr = &a as *const [i32];
/// // The data pointer is cast to a pointer to the target `u8` not `[u8]`
@ -497,7 +497,7 @@ declare_clippy_lint! {
/// The cast is easily confused with casting a c-like enum value to an integer.
///
/// ### Example
/// ```rust
/// ```no_run
/// enum E { X(i32) };
/// let _ = E::X as usize;
/// ```
@ -515,12 +515,12 @@ declare_clippy_lint! {
/// The `unsigned_abs()` method avoids panic when called on the MIN value.
///
/// ### Example
/// ```rust
/// ```no_run
/// let x: i32 = -42;
/// let y: u32 = x.abs() as u32;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let x: i32 = -42;
/// let y: u32 = x.unsigned_abs();
/// ```
@ -541,13 +541,13 @@ declare_clippy_lint! {
/// The lint is allowed by default as using `_` is less wordy than always specifying the type.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn foo(n: usize) {}
/// let n: u16 = 256;
/// foo(n as _);
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// fn foo(n: usize) {}
/// let n: u16 = 256;
/// foo(n as usize);
@ -570,7 +570,7 @@ declare_clippy_lint! {
/// Read the `ptr::addr_of` docs for more information.
///
/// ### Example
/// ```rust
/// ```no_run
/// let val = 1;
/// let p = &val as *const i32;
///
@ -578,7 +578,7 @@ declare_clippy_lint! {
/// let p_mut = &mut val_mut as *mut i32;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let val = 1;
/// let p = std::ptr::addr_of!(val);
///
@ -627,13 +627,13 @@ declare_clippy_lint! {
/// mutability is used, making it unlikely that having it as a mutable pointer is correct.
///
/// ### Example
/// ```rust
/// ```no_run
/// let mut vec = Vec::<u8>::with_capacity(1);
/// let ptr = vec.as_ptr() as *mut u8;
/// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let mut vec = Vec::<u8>::with_capacity(1);
/// let ptr = vec.as_mut_ptr();
/// unsafe { ptr.write(4) };
@ -675,12 +675,12 @@ declare_clippy_lint! {
/// {`std`, `core`}`::ptr::`{`null`, `null_mut`}.
///
/// ### Example
/// ```rust
/// ```no_run
/// let a = 0 as *const u32;
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let a = std::ptr::null::<u32>();
/// ```
#[clippy::version = "pre 1.29.0"]

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{Msrv, POINTER_CAST_CONSTNESS};
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_errors::Applicability;
@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
msrv: &Msrv,
) {
if_chain! {
if msrv.meets(POINTER_CAST_CONSTNESS);
if msrv.meets(msrvs::POINTER_CAST_CONSTNESS);
if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind();
if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind();
if matches!((from_mutbl, to_mutbl),

View file

@ -97,7 +97,9 @@ pub(super) fn check<'tcx>(
}
// skip cast of fn call that returns type alias
if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) {
if let ExprKind::Cast(inner, ..) = expr.kind
&& is_cast_from_ty_alias(cx, inner, cast_from)
{
return false;
}
@ -189,11 +191,10 @@ fn lint_unnecessary_cast(
let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
&& let ExprKind::MethodCall(..) = parent_expr.kind
&& literal_str.starts_with('-')
{
format!("({literal_str}_{cast_to})")
} else {
format!("{literal_str}_{cast_to}")
{
format!("({literal_str}_{cast_to})")
} else {
format!("{literal_str}_{cast_to}")
};
span_lint_and_sugg(
@ -269,7 +270,9 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
&& let Some(parent) = get_parent_node(cx.tcx, hir_id)
&& let Node::Local(l) = parent
{
if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) {
if let Some(e) = l.init
&& is_cast_from_ty_alias(cx, e, cast_from)
{
return ControlFlow::Break::<()>(());
}

View file

@ -1,7 +1,7 @@
//! lint on manually implemented checked conversions that could be transformed into `try_from`
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
use if_chain::if_chain;
@ -19,13 +19,13 @@ declare_clippy_lint! {
/// Reduces the readability of statements & is error prone.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let foo: u32 = 5;
/// foo <= i32::MAX as u32;
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let foo = 1;
/// # #[allow(unused)]
/// i32::try_from(foo).is_ok();

View file

@ -32,7 +32,7 @@ declare_clippy_lint! {
/// makes code look more complex than it really is.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let (x, y) = (true, true);
/// if x {
/// if y {
@ -42,7 +42,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let (x, y) = (true, true);
/// if x && y {
/// // …

View file

@ -20,7 +20,7 @@ declare_clippy_lint! {
/// instead.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let samples = vec![3, 1, 2];
/// let mut sorted_samples = samples.clone();
/// sorted_samples.sort();
@ -29,7 +29,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # let samples = vec![3, 1, 2];
/// let mut sorted_samples = samples.clone();
/// sorted_samples.sort();

View file

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// https://doc.rust-lang.org/reference/macros-by-example.html#hygiene
///
/// ### Example
/// ```rust
/// ```no_run
/// #[macro_export]
/// macro_rules! print_message {
/// () => {
@ -28,7 +28,7 @@ declare_clippy_lint! {
/// pub const MESSAGE: &str = "Hello!";
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// #[macro_export]
/// macro_rules! print_message {
/// () => {

View file

@ -6,8 +6,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")]
crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO,
@ -30,6 +28,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")]
crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::metadata_collector::METADATA_COLLECTOR_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO,
@ -37,6 +37,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO,
crate::absolute_paths::ABSOLUTE_PATHS_INFO,
crate::allow_attributes::ALLOW_ATTRIBUTES_INFO,
crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
@ -272,6 +274,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::loops::NEVER_LOOP_INFO,
crate::loops::SAME_ITEM_PUSH_INFO,
crate::loops::SINGLE_ELEMENT_LOOP_INFO,
crate::loops::UNUSED_ENUMERATE_INDEX_INFO,
crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
crate::loops::WHILE_LET_LOOP_INFO,
crate::loops::WHILE_LET_ON_ITERATOR_INFO,
@ -428,6 +431,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::TYPE_ID_ON_BOX_INFO,
crate::methods::UNINIT_ASSUMED_INIT_INFO,
crate::methods::UNIT_HASH_INFO,
crate::methods::UNNECESSARY_FALLIBLE_CONVERSIONS_INFO,
crate::methods::UNNECESSARY_FILTER_MAP_INFO,
crate::methods::UNNECESSARY_FIND_MAP_INFO,
crate::methods::UNNECESSARY_FOLD_INFO,
@ -441,6 +445,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::USELESS_ASREF_INFO,
crate::methods::VEC_RESIZE_TO_ZERO_INFO,
crate::methods::VERBOSE_FILE_READS_INFO,
crate::methods::WAKER_CLONE_WAKE_INFO,
crate::methods::WRONG_SELF_CONVENTION_INFO,
crate::methods::ZST_OFFSET_INFO,
crate::min_ident_chars::MIN_IDENT_CHARS_INFO,

View file

@ -23,12 +23,12 @@ declare_clippy_lint! {
/// generic `Default`.
///
/// ### Example
/// ```rust
/// ```no_run
/// let s: String = Default::default();
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let s = String::default();
/// ```
#[clippy::version = "pre 1.29.0"]
@ -49,7 +49,7 @@ declare_clippy_lint! {
/// Assignments to patterns that are of tuple type are not linted.
///
/// ### Example
/// ```
/// ```no_run
/// # #[derive(Default)]
/// # struct A { i: i32 }
/// let mut a: A = Default::default();
@ -57,7 +57,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```
/// ```no_run
/// # #[derive(Default)]
/// # struct A { i: i32 }
/// let a = A {

View file

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// This adds code complexity and an unnecessary function call.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::marker::PhantomData;
/// #[derive(Default)]
/// struct S<T> {
@ -29,7 +29,7 @@ declare_clippy_lint! {
/// };
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::marker::PhantomData;
/// struct S<T> {
/// _marker: PhantomData<T>

View file

@ -14,12 +14,12 @@ declare_clippy_lint! {
/// ### Why is this bad?
/// `std::iter::empty()` is the more idiomatic way.
/// ### Example
/// ```rust
/// ```no_run
/// let _ = std::iter::Empty::<usize>::default();
/// let iter: std::iter::Empty<usize> = std::iter::Empty::default();
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let _ = std::iter::empty::<usize>();
/// let iter: std::iter::Empty<usize> = std::iter::empty();
/// ```
@ -68,7 +68,10 @@ fn make_sugg(
_ => None,
})
{
format!("std::iter::empty::<{}>()", snippet_with_context(cx, iter_ty.span, ctxt, "..", applicability).0)
format!(
"std::iter::empty::<{}>()",
snippet_with_context(cx, iter_ty.span, ctxt, "..", applicability).0
)
} else {
"std::iter::empty()".to_owned()
}

View file

@ -31,13 +31,13 @@ declare_clippy_lint! {
/// This lint can only be allowed at the function level or above.
///
/// ### Example
/// ```rust
/// ```no_run
/// let i = 10;
/// let f = 1.23;
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let i = 10i32;
/// let f = 1.23f64;
/// ```

View file

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// specified layout. These cases may lead to undefined behavior in unsafe blocks.
///
/// ### Example
/// ```rust
/// ```no_run
/// union Foo {
/// a: i32,
/// b: u32,
@ -30,7 +30,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// #[repr(C)]
/// union Foo {
/// a: i32,

View file

@ -29,14 +29,14 @@ declare_clippy_lint! {
/// when not part of a method chain.
///
/// ### Example
/// ```rust
/// ```no_run
/// use std::ops::Deref;
/// let a: &mut String = &mut String::from("foo");
/// let b: &str = a.deref();
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let a: &mut String = &mut String::from("foo");
/// let b = &*a;
/// ```
@ -68,7 +68,7 @@ declare_clippy_lint! {
/// in such a case can change the semantics of the code.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn fun(_a: &i32) {}
///
/// let x: &i32 = &&&&&&5;
@ -76,7 +76,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # fn fun(_a: &i32) {}
/// let x: &i32 = &5;
/// fun(x);
@ -95,7 +95,7 @@ declare_clippy_lint! {
/// The address-of operator at the use site is clearer about the need for a reference.
///
/// ### Example
/// ```rust
/// ```no_run
/// let x = Some("");
/// if let Some(ref x) = x {
/// // use `x` here
@ -103,7 +103,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let x = Some("");
/// if let Some(x) = x {
/// // use `&x` here
@ -123,12 +123,12 @@ declare_clippy_lint! {
/// This unnecessarily complicates the code.
///
/// ### Example
/// ```rust
/// ```no_run
/// let x = String::new();
/// let y: &str = &*x;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let x = String::new();
/// let y: &str = &x;
/// ```
@ -353,23 +353,26 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
// priority.
if let Some(fn_id) = typeck.type_dependent_def_id(hir_id)
&& let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
&& let arg_ty
= cx.tcx.erase_regions(use_cx.adjustments.last().map_or(expr_ty, |a| a.target))
&& let arg_ty = cx
.tcx
.erase_regions(use_cx.adjustments.last().map_or(expr_ty, |a| a.target))
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
&& let args = cx
.typeck_results()
.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default()
&& let impl_ty = if cx.tcx.fn_sig(fn_id)
.instantiate_identity()
.skip_binder()
.inputs()[0].is_ref()
{
// Trait methods taking `&self`
sub_ty
} else {
// Trait methods taking `self`
arg_ty
} && impl_ty.is_ref()
.node_args_opt(hir_id)
.map(|args| &args[1..])
.unwrap_or_default()
&& let impl_ty =
if cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder().inputs()[0]
.is_ref()
{
// Trait methods taking `&self`
sub_ty
} else {
// Trait methods taking `self`
arg_ty
}
&& impl_ty.is_ref()
&& implements_trait(
cx,
impl_ty,
@ -414,9 +417,9 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
let (required_refs, msg) = if can_auto_borrow {
(1, if deref_count == 1 { borrow_msg } else { deref_msg })
} else if let Some(&Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
..
}) = next_adjust
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
..
}) = next_adjust
&& matches!(mutability, AutoBorrowMutability::Mut { .. })
&& !stability.is_reborrow_stable()
{
@ -705,9 +708,11 @@ fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> boo
{
match parent.kind {
ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _)
if child.hir_id == e.hir_id => true,
ExprKind::Match(.., MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar)
| ExprKind::Field(_, _) => true,
if child.hir_id == e.hir_id =>
{
true
},
ExprKind::Match(.., MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar) | ExprKind::Field(_, _) => true,
_ => false,
}
} else {

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::indent_of;
use clippy_utils::{is_default_equivalent, peel_blocks};
use rustc_errors::Applicability;
@ -21,7 +21,7 @@ declare_clippy_lint! {
/// It is less concise.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Foo {
/// bar: bool
/// }
@ -36,7 +36,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #[derive(Default)]
/// struct Foo {
/// bar: bool

View file

@ -173,7 +173,7 @@ declare_clippy_lint! {
/// `Eq` themselves.
///
/// ### Example
/// ```rust
/// ```no_run
/// #[derive(PartialEq)]
/// struct Foo {
/// i_am_eq: i32,
@ -181,7 +181,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// #[derive(PartialEq, Eq)]
/// struct Foo {
/// i_am_eq: i32,

View file

@ -1,3 +1,4 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::macro_backtrace;
use rustc_ast::Attribute;
@ -8,8 +9,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{ExpnId, Span};
use crate::utils::conf;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured macros in clippy.toml
@ -35,7 +34,7 @@ declare_clippy_lint! {
/// { path = "serde::Serialize", reason = "no serializing" },
/// ]
/// ```
/// ```
/// ```no_run
/// use serde::Serialize;
///
/// // Example code where clippy issues a warning
@ -55,13 +54,13 @@ declare_clippy_lint! {
}
pub struct DisallowedMacros {
conf_disallowed: Vec<conf::DisallowedPath>,
conf_disallowed: Vec<DisallowedPath>,
disallowed: DefIdMap<usize>,
seen: FxHashSet<ExpnId>,
}
impl DisallowedMacros {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self {
conf_disallowed,
disallowed: DefIdMap::default(),

View file

@ -1,13 +1,11 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
use rustc_hir::def_id::DefIdMap;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use crate::utils::conf;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured methods and functions in clippy.toml
@ -59,12 +57,12 @@ declare_clippy_lint! {
#[derive(Clone, Debug)]
pub struct DisallowedMethods {
conf_disallowed: Vec<conf::DisallowedPath>,
conf_disallowed: Vec<DisallowedPath>,
disallowed: DefIdMap<usize>,
}
impl DisallowedMethods {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self {
conf_disallowed,
disallowed: DefIdMap::default(),

View file

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// avoided.
///
/// ### Example
/// ```rust
/// ```no_run
/// let foo = 3.14;
/// ```
#[clippy::version = "pre 1.29.0"]

View file

@ -30,7 +30,7 @@ declare_clippy_lint! {
/// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents
///
/// ### Example
/// ```rust
/// ```no_run
/// // Assuming that `clippy.toml` contains the following line:
/// // allowed-scripts = ["Latin", "Cyrillic"]
/// let counter = 10; // OK, latin is allowed.

View file

@ -1,5 +1,5 @@
use clippy_config::types::DisallowedPath;
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
@ -8,8 +8,6 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
use crate::utils::conf;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured types in clippy.toml.
@ -50,15 +48,16 @@ declare_clippy_lint! {
style,
"use of disallowed types"
}
#[derive(Clone, Debug)]
pub struct DisallowedTypes {
conf_disallowed: Vec<conf::DisallowedPath>,
conf_disallowed: Vec<DisallowedPath>,
def_ids: FxHashMap<DefId, usize>,
prim_tys: FxHashMap<PrimTy, usize>,
}
impl DisallowedTypes {
pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
Self {
conf_disallowed,
def_ids: FxHashMap::default(),
@ -123,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
}
}
fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &conf::DisallowedPath) {
fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) {
span_lint_and_then(
cx,
DISALLOWED_TYPES,

View file

@ -58,14 +58,14 @@ declare_clippy_lint! {
/// would fail.
///
/// ### Examples
/// ```rust
/// ```no_run
/// /// Do something with the foo_bar parameter. See also
/// /// that::other::module::foo.
/// // ^ `foo_bar` and `that::other::module::foo` should be ticked.
/// fn doit(foo_bar: usize) {}
/// ```
///
/// ```rust
/// ```no_run
/// // Link text with `[]` brackets should be written as following:
/// /// Consume the array and return the inner
/// /// [`SmallVec<[T; INLINE_CAPACITY]>`][SmallVec].
@ -88,7 +88,7 @@ declare_clippy_lint! {
/// preconditions, so that users can be sure they are using them safely.
///
/// ### Examples
/// ```rust
/// ```no_run
///# type Universe = ();
/// /// This function should really be documented
/// pub unsafe fn start_apocalypse(u: &mut Universe) {
@ -98,7 +98,7 @@ declare_clippy_lint! {
///
/// At least write a line about safety:
///
/// ```rust
/// ```no_run
///# type Universe = ();
/// /// # Safety
/// ///
@ -126,7 +126,7 @@ declare_clippy_lint! {
/// Since the following function returns a `Result` it has an `# Errors` section in
/// its doc comment:
///
/// ```rust
/// ```no_run
///# use std::io;
/// /// # Errors
/// ///
@ -155,7 +155,7 @@ declare_clippy_lint! {
/// Since the following function may panic it has a `# Panics` section in
/// its doc comment:
///
/// ```rust
/// ```no_run
/// /// # Panics
/// ///
/// /// Will panic if y is 0
@ -182,7 +182,7 @@ declare_clippy_lint! {
/// if the `fn main()` is left implicit.
///
/// ### Examples
/// ```rust
/// ```no_run
/// /// An example of a doctest with a `main()` function
/// ///
/// /// # Examples
@ -210,12 +210,12 @@ declare_clippy_lint! {
/// It is likely a typo when defining an intra-doc link
///
/// ### Example
/// ```rust
/// ```no_run
/// /// See also: ['foo']
/// fn bar() {}
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// /// See also: [`foo`]
/// fn bar() {}
/// ```
@ -235,7 +235,7 @@ declare_clippy_lint! {
/// need to describe safety preconditions that users are required to uphold.
///
/// ### Examples
/// ```rust
/// ```no_run
///# type Universe = ();
/// /// # Safety
/// ///
@ -248,7 +248,7 @@ declare_clippy_lint! {
/// The function is safe, so there shouldn't be any preconditions
/// that have to be explained for safety reasons.
///
/// ```rust
/// ```no_run
///# type Universe = ();
/// /// This function should really be documented
/// pub fn start_apocalypse(u: &mut Universe) {
@ -569,9 +569,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
if let End(Heading(_, _, _)) = event {
in_heading = false;
}
if ticks_unbalanced
&& let Some(span) = fragments.span(cx, paragraph_range.clone())
{
if ticks_unbalanced && let Some(span) = fragments.span(cx, paragraph_range.clone()) {
span_lint_and_help(
cx,
DOC_MARKDOWN,
@ -617,8 +615,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
check_link_quotes(cx, trimmed_text, range.clone(), fragments);
}
if let Some(link) = in_link.as_ref()
&& let Ok(url) = Url::parse(link)
&& (url.scheme() == "https" || url.scheme() == "http") {
&& let Ok(url) = Url::parse(link)
&& (url.scheme() == "https" || url.scheme() == "http")
{
// Don't check the text associated with external URLs
continue;
}
@ -716,7 +715,9 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, range: Range<u
// Because of the global session, we need to create a new session in a different thread with
// the edition we need.
let text = text.to_owned();
if thread::spawn(move || has_needless_main(text, edition)).join().expect("thread::spawn failed")
if thread::spawn(move || has_needless_main(text, edition))
.join()
.expect("thread::spawn failed")
&& let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace)
{
span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
@ -756,11 +757,12 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
}
fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
/// Checks if a string is camel-case, i.e., contains at least two uppercase
/// letters (`Clippy` is ok) and one lower-case letter (`NASA` is ok).
/// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
/// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
/// letter (`NASA` is ok).
/// Plurals are also excluded (`IDs` is ok).
fn is_camel_case(s: &str) -> bool {
if s.starts_with(|c: char| c.is_ascii_digit()) {
if s.starts_with(|c: char| c.is_ascii_digit() | c.is_ascii_lowercase()) {
return false;
}

View file

@ -12,7 +12,7 @@ declare_clippy_lint! {
/// mistake.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn simple_double_parens() -> i32 {
/// ((0))
/// }
@ -22,7 +22,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// fn simple_no_parens() -> i32 {
/// 0
/// }

View file

@ -16,7 +16,7 @@ declare_clippy_lint! {
/// have been intended.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Foo;
/// let x = Foo;
/// std::mem::drop(x);
@ -36,7 +36,7 @@ declare_clippy_lint! {
/// have been intended.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Foo;
/// let x = Foo;
/// std::mem::forget(x);
@ -57,7 +57,7 @@ declare_clippy_lint! {
/// destructor, possibly causing leaks.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::mem;
/// # use std::rc::Rc;
/// mem::forget(Rc::new(55))
@ -90,7 +90,8 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
let is_copy = is_copy(cx, arg_ty);
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let (lint, msg, note_span) = match fn_name {
// early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types
// early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references,
// forgetting_copy_types
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
sym::mem_forget if arg_ty.is_ref() => return,
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
@ -100,8 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
|| is_must_use_func_call(cx, arg)
|| is_must_use_ty(cx, arg_ty)
|| drop_is_single_call_in_arm
) =>
|| drop_is_single_call_in_arm) =>
{
(DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span))
},
@ -122,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
} else {
(FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into(), Some(arg.span))
}
}
},
_ => return,
};
span_lint_and_note(

View file

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10).
///
/// ### Example
/// ```rust
/// ```no_run
/// # fn a() {}
/// # fn b() {}
/// # let x: i32 = 1;
@ -28,7 +28,7 @@ declare_clippy_lint! {
///
/// Use instead:
///
/// ```rust
/// ```no_run
/// # fn a() {}
/// # fn b() {}
/// # let x: i32 = 1;

View file

@ -16,7 +16,7 @@ declare_clippy_lint! {
/// destructured, which might be the intention behind adding the implementation as a marker.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct S;
///
/// impl Drop for S {
@ -24,7 +24,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct S;
/// ```
#[clippy::version = "1.62.0"]

View file

@ -23,12 +23,12 @@ declare_clippy_lint! {
///
///
/// ### Example
/// ```rust
/// ```no_run
/// enum Test {}
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// #![feature(never_type)]
///
/// struct Test(!);

View file

@ -15,11 +15,11 @@ declare_clippy_lint! {
/// Empty brackets after a struct declaration can be omitted.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Cookie {}
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct Cookie;
/// ```
#[clippy::version = "1.62.0"]
@ -35,7 +35,8 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
if let ItemKind::Struct(var_data, _) = &item.kind
&& has_brackets(var_data)
&& has_no_fields(cx, var_data, span_after_ident) {
&& has_no_fields(cx, var_data, span_after_ident)
{
span_lint_and_then(
cx,
EMPTY_STRUCTS_WITH_BRACKETS,
@ -46,8 +47,9 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
span_after_ident,
"remove the brackets",
";",
Applicability::Unspecified);
},
Applicability::Unspecified,
);
},
);
}
}

View file

@ -23,7 +23,7 @@ declare_clippy_lint! {
///
/// ### Known problems
/// The suggestion may have type inference errors in some cases. e.g.
/// ```rust
/// ```no_run
/// let mut map = std::collections::HashMap::new();
/// let _ = if !map.contains_key(&0) {
/// map.insert(0, 0)
@ -33,7 +33,7 @@ declare_clippy_lint! {
/// ```
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::collections::HashMap;
/// # let mut map = HashMap::new();
/// # let k = 1;
@ -43,7 +43,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::collections::HashMap;
/// # let mut map = HashMap::new();
/// # let k = 1;

View file

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// architectures, but works fine on 64 bit.
///
/// ### Example
/// ```rust
/// ```no_run
/// # #[cfg(target_pointer_width = "64")]
/// #[repr(usize)]
/// enum NonPortable {

View file

@ -68,7 +68,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !in_external_macro(cx.sess(), expr.span)
&& let ExprKind::Let(let_expr) = expr.kind
&& unary_pattern(let_expr.pat) {
&& unary_pattern(let_expr.pat)
{
let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
let mut applicability = Applicability::MachineApplicable;
@ -79,7 +80,9 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
"({})",
snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0,
),
_ => snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0.to_string(),
_ => snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability)
.0
.to_string(),
};
span_lint_and_sugg(
cx,

View file

@ -41,10 +41,11 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
};
match item.kind {
ItemKind::TyAlias(..) if item.ident.name == sym::Error
&& is_visible_outside_module(cx, item.owner_id.def_id)
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& implements_trait(cx, ty, error_def_id, &[]) =>
ItemKind::TyAlias(..)
if item.ident.name == sym::Error
&& is_visible_outside_module(cx, item.owner_id.def_id)
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& implements_trait(cx, ty, error_def_id, &[]) =>
{
span_lint(
cx,
@ -53,13 +54,14 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
"exported type alias named `Error` that implements `Error`",
);
},
ItemKind::Impl(imp) if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
&& error_def_id == trait_def_id
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
&& let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id)
&& let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id())
&& ident.name == sym::Error
&& is_visible_outside_module(cx, def_id) =>
ItemKind::Impl(imp)
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
&& error_def_id == trait_def_id
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
&& let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id)
&& let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id())
&& ident.name == sym::Error
&& is_visible_outside_module(cx, def_id) =>
{
span_lint_hir_and_then(
cx,
@ -69,9 +71,9 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
"exported type named `Error` that implements `Error`",
|diag| {
diag.span_note(item.span, "`Error` was implemented here");
}
},
);
}
},
_ => {},
}
}

View file

@ -28,12 +28,12 @@ declare_clippy_lint! {
/// into something.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn foo(x: Box<u32>) {}
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// fn foo(x: u32) {}
/// ```
#[clippy::version = "pre 1.29.0"]

View file

@ -119,19 +119,21 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
match body.value.kind {
ExprKind::Call(callee, args)
if matches!(callee.kind, ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))) =>
if matches!(
callee.kind,
ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))
) =>
{
let callee_ty = typeck.expr_ty(callee).peel_refs();
if matches!(
type_diagnostic_name(cx, callee_ty),
Some(sym::Arc | sym::Rc)
) || !check_inputs(typeck, body.params, None, args) {
if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
|| !check_inputs(typeck, body.params, None, args)
{
return;
}
let callee_ty_adjusted = typeck.expr_adjustments(callee).last().map_or(
callee_ty,
|a| a.target.peel_refs(),
);
let callee_ty_adjusted = typeck
.expr_adjustments(callee)
.last()
.map_or(callee_ty, |a| a.target.peel_refs());
let sig = match callee_ty_adjusted.kind() {
ty::FnDef(def, _) => cx.tcx.fn_sig(def).skip_binder().skip_binder(),
@ -160,36 +162,26 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
// For now ignore all callee types which reference a type parameter.
&& !generic_args.types().any(|t| matches!(t.kind(), ty::Param(_)))
{
span_lint_and_then(
cx,
REDUNDANT_CLOSURE,
expr.span,
"redundant closure",
|diag| {
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
if let Ok((ClosureKind::FnMut, _))
= cx.tcx.infer_ctxt().build().type_implements_fn_trait(
cx.param_env,
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
ImplPolarity::Positive,
) && path_to_local(callee)
.map_or(
false,
|l| local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr),
)
{
// Mutable closure is used after current expr; we cannot consume it.
snippet = format!("&mut {snippet}");
}
diag.span_suggestion(
expr.span,
"replace the closure with the function itself",
snippet,
Applicability::MachineApplicable,
);
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait(
cx.param_env,
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
ImplPolarity::Positive,
) && path_to_local(callee).map_or(false, |l| {
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
}) {
// Mutable closure is used after current expr; we cannot consume it.
snippet = format!("&mut {snippet}");
}
diag.span_suggestion(
expr.span,
"replace the closure with the function itself",
snippet,
Applicability::MachineApplicable,
);
}
);
});
}
},
ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => {

View file

@ -22,7 +22,7 @@ declare_clippy_lint! {
/// readability and API.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct S {
/// is_pending: bool,
/// is_processing: bool,
@ -31,7 +31,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// enum S {
/// Pending,
/// Processing,
@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
// functions with a body are already checked by `check_fn`
if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind
&& fn_sig.header.abi == Abi::Rust
{
{
self.check_fn_sig(cx, fn_sig.decl, fn_sig.span);
}
}
@ -174,11 +174,8 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_header) = fn_kind.header()
&& fn_header.abi == Abi::Rust
&& get_parent_as_impl(cx.tcx, hir_id)
.map_or(true,
|impl_item| impl_item.of_trait.is_none()
)
{
&& get_parent_as_impl(cx.tcx, hir_id).map_or(true, |impl_item| impl_item.of_trait.is_none())
{
self.check_fn_sig(cx, fn_decl, span);
}
}

View file

@ -17,14 +17,14 @@ declare_clippy_lint! {
/// disable them by default.
///
/// ### Example
/// ```rust
/// ```no_run
/// enum Foo {
/// Bar,
/// Baz
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// #[non_exhaustive]
/// enum Foo {
/// Bar,
@ -47,14 +47,14 @@ declare_clippy_lint! {
/// disable them by default.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Foo {
/// bar: u8,
/// baz: String,
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// #[non_exhaustive]
/// struct Foo {
/// bar: u8,

View file

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// the main function.
///
/// ### Example
/// ```
/// ```no_run
/// std::process::exit(0)
/// ```
///

View file

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// Using `(e)println! is clearer and more concise
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::io::Write;
/// # let bar = "furchtbar";
/// writeln!(&mut std::io::stderr(), "foo: {:?}", bar).unwrap();
@ -27,7 +27,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::io::Write;
/// # let bar = "furchtbar";
/// eprintln!("foo: {:?}", bar);
@ -58,7 +58,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
Some(sym::io_stderr) => ("stderr", "e"),
_ => return,
};
let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else { return; };
let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else {
return;
};
// ordering is important here, since `writeln!` uses `write!` internally
let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() {
@ -78,18 +80,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
macro_name.replace("write", "print"),
)
} else {
(
format!("{dest_name}().write_fmt(...)"),
"print".into(),
)
(format!("{dest_name}().write_fmt(...)"), "print".into())
};
let mut applicability = Applicability::MachineApplicable;
let inputs_snippet = snippet_with_applicability(
cx,
format_args_inputs_span(&format_args),
"..",
&mut applicability,
);
let inputs_snippet =
snippet_with_applicability(cx, format_args_inputs_span(&format_args), "..", &mut applicability);
span_lint_and_sugg(
cx,
EXPLICIT_WRITE,

View file

@ -23,13 +23,13 @@ declare_clippy_lint! {
/// requires using a turbofish, which serves no purpose but to satisfy the compiler.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn unused_ty<T>(x: u8) {
/// // ..
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// fn no_unused_ty(x: u8) {
/// // ..
/// }
@ -177,20 +177,22 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
.iter()
.rev()
.map(|(idx, param)| {
if let Some(next) = explicit_params.get(idx + 1) && end != Some(next.def_id) {
// Extend the current span forward, up until the next param in the list.
param.span.until(next.span)
} else {
// Extend the current span back to include the comma following the previous
// param. If the span of the next param in the list has already been
// extended, we continue the chain. This is why we're iterating in reverse.
end = Some(param.def_id);
if let Some(next) = explicit_params.get(idx + 1)
&& end != Some(next.def_id)
{
// Extend the current span forward, up until the next param in the list.
param.span.until(next.span)
} else {
// Extend the current span back to include the comma following the previous
// param. If the span of the next param in the list has already been
// extended, we continue the chain. This is why we're iterating in reverse.
end = Some(param.def_id);
// idx will never be 0, else we'd be removing the entire list of generics
let prev = explicit_params[idx - 1];
let prev_span = self.get_bound_span(prev);
self.get_bound_span(param).with_lo(prev_span.hi())
}
// idx will never be 0, else we'd be removing the entire list of generics
let prev = explicit_params[idx - 1];
let prev_span = self.get_bound_span(prev);
self.get_bound_span(param).with_lo(prev_span.hi())
}
})
.collect()
};

View file

@ -17,7 +17,7 @@ declare_clippy_lint! {
/// `TryFrom` should be used if there's a possibility of failure.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Foo(i32);
///
/// impl From<String> for Foo {
@ -28,7 +28,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// struct Foo(i32);
///
/// impl TryFrom<String> for Foo {

View file

@ -18,13 +18,13 @@ declare_clippy_lint! {
/// Rust will truncate the literal silently.
///
/// ### Example
/// ```rust
/// ```no_run
/// let v: f32 = 0.123_456_789_9;
/// println!("{}", v); // 0.123_456_789
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let v: f64 = 0.123_456_789_9;
/// println!("{}", v); // 0.123_456_789_9
/// ```
@ -44,12 +44,12 @@ declare_clippy_lint! {
/// conversion to a float.
///
/// ### Example
/// ```rust
/// ```no_run
/// let _: f32 = 16_777_217.0; // 16_777_216.0
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let _: f32 = 16_777_216.0;
/// let _: f64 = 16_777_217.0;
/// ```

View file

@ -27,7 +27,7 @@ declare_clippy_lint! {
/// Negatively impacts accuracy.
///
/// ### Example
/// ```rust
/// ```no_run
/// let a = 3f32;
/// let _ = a.powf(1.0 / 3.0);
/// let _ = (1.0 + a).ln();
@ -35,7 +35,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let a = 3f32;
/// let _ = a.cbrt();
/// let _ = a.ln_1p();
@ -57,7 +57,7 @@ declare_clippy_lint! {
/// Negatively impacts accuracy and performance.
///
/// ### Example
/// ```rust
/// ```no_run
/// use std::f32::consts::E;
///
/// let a = 3f32;
@ -83,7 +83,7 @@ declare_clippy_lint! {
///
/// is better expressed as
///
/// ```rust
/// ```no_run
/// use std::f32::consts::E;
///
/// let a = 3f32;
@ -323,9 +323,9 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
let maybe_neg_sugg = |expr, hir_id| {
let sugg = Sugg::hir(cx, expr, "..");
if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
format!("-{}", sugg.maybe_par())
-sugg
} else {
sugg.to_string()
sugg
}
};
@ -470,25 +470,13 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
let maybe_neg_sugg = |expr| {
let sugg = Sugg::hir(cx, expr, "..");
if let BinOpKind::Sub = op {
format!("-{sugg}")
} else {
sugg.to_string()
}
if let BinOpKind::Sub = op { -sugg } else { sugg }
};
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
(
inner_lhs,
Sugg::hir(cx, inner_rhs, "..").to_string(),
maybe_neg_sugg(rhs),
)
(inner_lhs, Sugg::hir(cx, inner_rhs, ".."), maybe_neg_sugg(rhs))
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
(
inner_lhs,
maybe_neg_sugg(inner_rhs),
Sugg::hir(cx, lhs, "..").to_string(),
)
(inner_lhs, maybe_neg_sugg(inner_rhs), Sugg::hir(cx, lhs, ".."))
} else {
return;
};

View file

@ -23,13 +23,13 @@ declare_clippy_lint! {
/// if `foo: &str`.
///
/// ### Examples
/// ```rust
/// ```no_run
/// let foo = "foo";
/// format!("{}", foo);
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// let foo = "foo";
/// foo.to_owned();
/// ```
@ -54,7 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
([], [_]) => {
// Simulate macro expansion, converting {{ and }} to { and }.
let Some(snippet) = snippet_opt(cx, format_args.span) else { return };
let Some(snippet) = snippet_opt(cx, format_args.span) else {
return;
};
let s_expand = snippet.replace("{{", "{").replace("}}", "}");
let sugg = format!("{s_expand}.to_string()");
span_useless_format(cx, call_site, sugg, applicability);
@ -76,13 +78,14 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
_ => false,
};
let sugg = if is_new_string {
snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned()
snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability)
.0
.into_owned()
} else {
let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
format!("{}.to_string()", sugg.maybe_par())
};
span_useless_format(cx, call_site, sugg, applicability);
}
},
_ => {},

View file

@ -1,11 +1,11 @@
use arrayvec::ArrayVec;
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::{
find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro,
is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage,
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_lang_item};
use if_chain::if_chain;
@ -35,12 +35,12 @@ declare_clippy_lint! {
/// The recommended code is both shorter and avoids a temporary allocation.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::panic::Location;
/// println!("error: {}", format!("something failed at {}", Location::caller()));
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::panic::Location;
/// println!("error: something failed at {}", Location::caller());
/// ```
@ -61,12 +61,12 @@ declare_clippy_lint! {
/// unnecessary.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::panic::Location;
/// println!("error: something failed at {}", Location::caller().to_string());
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::panic::Location;
/// println!("error: something failed at {}", Location::caller());
/// ```
@ -87,7 +87,7 @@ declare_clippy_lint! {
/// The inlined syntax, where allowed, is simpler.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let var = 42;
/// # let width = 1;
/// # let prec = 2;
@ -98,7 +98,7 @@ declare_clippy_lint! {
/// format!("{:.*}", prec, var);
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # let var = 42;
/// # let width = 1;
/// # let prec = 2;
@ -111,12 +111,12 @@ declare_clippy_lint! {
///
/// If allow-mixed-uninlined-format-args is set to false in clippy.toml,
/// the following code will also trigger the lint:
/// ```rust
/// ```no_run
/// # let var = 42;
/// format!("{} {}", var, 1+2);
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # let var = 42;
/// format!("{var} {}", 1+2);
/// ```
@ -141,13 +141,13 @@ declare_clippy_lint! {
/// an expected formatting operation such as adding padding isn't happening.
///
/// ### Example
/// ```rust
/// ```no_run
/// println!("{:.}", 1.0);
///
/// println!("not padded: {:5}", format_args!("..."));
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// println!("{}", 1.0);
///
/// println!("not padded: {}", format_args!("..."));
@ -370,7 +370,7 @@ fn check_one_arg(
};
fixes.push((pos_span, replacement));
fixes.push((arg_span, String::new()));
true // successful inlining, continue checking
true // successful inlining, continue checking
} else {
// Do not continue inlining (return false) in case
// * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)`

View file

@ -21,7 +21,7 @@ declare_clippy_lint! {
///
/// ### Example
///
/// ```rust
/// ```no_run
/// use std::fmt;
///
/// struct Structure(i32);
@ -33,7 +33,7 @@ declare_clippy_lint! {
///
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// use std::fmt;
///
/// struct Structure(i32);
@ -59,7 +59,7 @@ declare_clippy_lint! {
/// should write to the `Formatter`, not stdout/stderr.
///
/// ### Example
/// ```rust
/// ```no_run
/// use std::fmt::{Display, Error, Formatter};
///
/// struct S;
@ -72,7 +72,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// use std::fmt::{Display, Error, Formatter};
///
/// struct S;

View file

@ -21,13 +21,13 @@ declare_clippy_lint! {
/// While using `write!` in the suggested way should never fail, this isn't necessarily clear to the programmer.
///
/// ### Example
/// ```rust
/// ```no_run
/// let mut s = String::new();
/// s += &format!("0x{:X}", 1024);
/// s.push_str(&format!("0x{:X}", 1024));
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// use std::fmt::Write as _; // import without risk of name clashing
///
/// let mut s = String::new();
@ -58,7 +58,7 @@ fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
arms.iter().any(|arm| is_format(cx, arm.body))
},
Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => {
is_format(cx, then) ||r#else.is_some_and(|e| is_format(cx, e))
is_format(cx, then) || r#else.is_some_and(|e| is_format(cx, e))
},
_ => false,
}
@ -69,17 +69,15 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let arg = match expr.kind {
ExprKind::MethodCall(_, _, [arg], _) => {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) &&
match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& match_def_path(cx, fn_def_id, &paths::PUSH_STR)
{
arg
} else {
return;
}
}
ExprKind::AssignOp(op, left, arg)
if op.node == BinOpKind::Add && is_string(cx, left) => {
arg
},
ExprKind::AssignOp(op, left, arg) if op.node == BinOpKind::Add && is_string(cx, left) => arg,
_ => return,
};
if is_format(cx, arg) {

View file

@ -37,7 +37,7 @@ declare_clippy_lint! {
/// This is either a typo in the binary operator or confusing.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let foo = true;
/// # let bar = false;
/// // &&! looks like a different operator
@ -45,7 +45,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let foo = true;
/// # let bar = false;
/// if foo && !bar {}

View file

@ -14,7 +14,7 @@ declare_clippy_lint! {
/// comment.
///
/// ### Example
/// ```rust
/// ```no_run
/// //// My amazing data structure
/// pub struct Foo {
/// // ...
@ -22,7 +22,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// /// My amazing data structure
/// pub struct Foo {
/// // ...

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::path_def_id;
use clippy_utils::source::snippet_opt;
use rustc_errors::Applicability;
@ -24,7 +24,7 @@ declare_clippy_lint! {
/// According the std docs implementing `From<..>` is preferred since it gives you `Into<..>` for free where the reverse isn't true.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct StringWrapper(String);
///
/// impl Into<StringWrapper> for String {
@ -34,7 +34,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct StringWrapper(String);
///
/// impl From<String> for StringWrapper {
@ -88,7 +88,8 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
cx.tcx.sess.source_map().guess_head_span(item.span),
"an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true",
|diag| {
// If the target type is likely foreign mention the orphan rules as it's a common source of confusion
// If the target type is likely foreign mention the orphan rules as it's a common source of
// confusion
if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) {
diag.help(
"`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\
@ -96,7 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
);
}
let message = format!("replace the `Into` implementation with `From<{}>`", middle_trait_ref.self_ty());
let message = format!(
"replace the `Into` implementation with `From<{}>`",
middle_trait_ref.self_ty()
);
if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) {
diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
} else {
@ -110,12 +114,12 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
extract_msrv_attr!(LateContext);
}
/// Finds the occurences of `Self` and `self`
/// Finds the occurrences of `Self` and `self`
struct SelfFinder<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
/// Occurences of `Self`
/// Occurrences of `Self`
upper: Vec<Span>,
/// Occurences of `self`
/// Occurrences of `self`
lower: Vec<Span>,
/// If any of the `self`/`Self` usages were from an expansion, or the body contained a binding
/// already named `val`

View file

@ -18,13 +18,13 @@ declare_clippy_lint! {
/// For this to be safe, `c_void` would need to have the same memory layout as the original type, which is often not the case.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::ffi::c_void;
/// let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
/// let _ = unsafe { Box::from_raw(ptr) };
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::ffi::c_void;
/// # let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
/// let _ = unsafe { Box::from_raw(ptr as *mut usize) };
@ -40,14 +40,22 @@ declare_lint_pass!(FromRawWithVoidPtr => [FROM_RAW_WITH_VOID_PTR]);
impl LateLintPass<'_> for FromRawWithVoidPtr {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Call(box_from_raw, [arg]) = expr.kind
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind
&& seg.ident.name == sym!(from_raw)
&& let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
&& let arg_kind = cx.typeck_results().expr_ty(arg).kind()
&& let RawPtr(TypeAndMut { ty, .. }) = arg_kind
&& is_c_void(cx, *ty) {
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind
&& seg.ident.name == sym!(from_raw)
&& let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
&& let arg_kind = cx.typeck_results().expr_ty(arg).kind()
&& let RawPtr(TypeAndMut { ty, .. }) = arg_kind
&& is_c_void(cx, *ty)
{
let msg = format!("creating a `{type_str}` from a void raw pointer");
span_lint_and_help(cx, FROM_RAW_WITH_VOID_PTR, expr.span, &msg, Some(arg.span), "cast this to a pointer of the appropriate type");
span_lint_and_help(
cx,
FROM_RAW_WITH_VOID_PTR,
expr.span,
&msg,
Some(arg.span),
"cast this to a pointer of the appropriate type",
);
}
}
}

View file

@ -23,7 +23,7 @@ declare_clippy_lint! {
/// grouping some parameters into a new type.
///
/// ### Example
/// ```rust
/// ```no_run
/// # struct Color;
/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
/// // ..
@ -46,7 +46,7 @@ declare_clippy_lint! {
/// multiple functions.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn im_too_long() {
/// println!("");
/// // ... 100 more LoC
@ -129,7 +129,7 @@ declare_clippy_lint! {
/// a remnant of a refactoring that removed the return type.
///
/// ### Examples
/// ```rust
/// ```no_run
/// #[must_use]
/// fn useless() { }
/// ```
@ -151,7 +151,7 @@ declare_clippy_lint! {
/// attribute to improve the lint message.
///
/// ### Examples
/// ```rust
/// ```no_run
/// #[must_use]
/// fn double_must_use() -> Result<(), ()> {
/// unimplemented!();
@ -183,7 +183,7 @@ declare_clippy_lint! {
/// `#[must_use]`.
///
/// ### Examples
/// ```rust
/// ```no_run
/// // this could be annotated with `#[must_use]`.
/// pub fn id<T>(t: T) -> T { t }
/// ```
@ -211,7 +211,7 @@ declare_clippy_lint! {
/// instead.
///
/// ### Examples
/// ```rust
/// ```no_run
/// pub fn read_u8() -> Result<u8, ()> { Err(()) }
/// ```
/// should become
@ -262,7 +262,7 @@ declare_clippy_lint! {
/// The size determined by Clippy is platform-dependent.
///
/// ### Examples
/// ```rust
/// ```no_run
/// pub enum ParseError {
/// UnparsedBytes([u8; 512]),
/// UnexpectedEof,
@ -274,7 +274,7 @@ declare_clippy_lint! {
/// }
/// ```
/// should be
/// ```
/// ```no_run
/// pub enum ParseError {
/// UnparsedBytes(Box<[u8; 512]>),
/// UnexpectedEof,
@ -301,7 +301,7 @@ declare_clippy_lint! {
///
/// ### Example
/// ```rust
/// ```no_run
/// struct A {
/// a: String,
/// b: String,
@ -315,7 +315,7 @@ declare_clippy_lint! {
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct A {
/// a: String,
/// b: String,
@ -340,14 +340,14 @@ declare_clippy_lint! {
/// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor.
///
/// ### Example
/// ```rust
/// ```no_run
/// trait MyTrait {}
/// fn foo(a: impl MyTrait) {
/// // [...]
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// trait MyTrait {}
/// fn foo<T: MyTrait>(a: T) {
/// // [...]

View file

@ -118,9 +118,10 @@ fn check_needless_must_use(
if sig.header.is_async() {
let infcx = cx.tcx.infer_ctxt().build();
if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
&& !is_must_use_ty(cx, future_ty) {
return;
}
&& !is_must_use_ty(cx, future_ty)
{
return;
}
}
span_lint_and_help(

View file

@ -21,7 +21,9 @@ fn result_err_ty<'tcx>(
) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> {
if !in_external_macro(cx.sess(), item_span)
&& let hir::FnRetTy::Return(hir_ty) = decl.output
&& let ty = cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).instantiate_identity().output())
&& let ty = cx
.tcx
.erase_late_bound_regions(cx.tcx.fn_sig(id).instantiate_identity().output())
&& is_type_diagnostic_item(cx, ty, sym::Result)
&& let ty::Adt(_, args) = ty.kind()
{

View file

@ -34,11 +34,11 @@ declare_clippy_lint! {
/// produced.
///
/// ### Example
/// ```rust
/// ```no_run
/// async fn not_send(bytes: std::rc::Rc<[u8]>) {}
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// async fn is_send(bytes: std::sync::Arc<[u8]>) {}
/// ```
#[clippy::version = "1.44.0"]

View file

@ -1,6 +1,7 @@
//! lint on if branches that could be swapped so no `!` operation is necessary
//! on the condition
use clippy_utils::consts::{constant_simple, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_else_clause;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@ -16,7 +17,7 @@ declare_clippy_lint! {
/// Negations reduce the readability of statements.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let v: Vec<usize> = vec![];
/// # fn a() {}
/// # fn b() {}
@ -29,7 +30,7 @@ declare_clippy_lint! {
///
/// Could be written:
///
/// ```rust
/// ```no_run
/// # let v: Vec<usize> = vec![];
/// # fn a() {}
/// # fn b() {}
@ -47,6 +48,13 @@ declare_clippy_lint! {
declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
if let Some(value) = constant_simple(cx, cx.typeck_results(), expr) {
return Constant::Int(0) == value;
}
false
}
impl LateLintPass<'_> for IfNotElse {
fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
// While loops will be desugared to ExprKind::If. This will cause the lint to fire.
@ -72,7 +80,9 @@ impl LateLintPass<'_> for IfNotElse {
"remove the `!` and swap the blocks of the `if`/`else`",
);
},
ExprKind::Binary(ref kind, _, _) if kind.node == BinOpKind::Ne => {
ExprKind::Binary(ref kind, _, lhs) if kind.node == BinOpKind::Ne && !is_zero_const(lhs, cx) => {
// Disable firing the lint on `… != 0`, as these are likely to be bit tests.
// For example, `if foo & 0x0F00 != 0 { … } else { … }` already is in the "proper" order.
span_lint_and_help(
cx,
IF_NOT_ELSE,

View file

@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
@ -21,7 +21,7 @@ declare_clippy_lint! {
/// in comparison to `bool::then`.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let v = vec![0];
/// let a = if v.is_empty() {
/// println!("true!");
@ -33,7 +33,7 @@ declare_clippy_lint! {
///
/// Could be written:
///
/// ```rust
/// ```no_run
/// # let v = vec![0];
/// let a = v.is_empty().then(|| {
/// println!("true!");
@ -76,7 +76,11 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
let ctxt = expr.span.ctxt();
if let Some(higher::If { cond, then, r#else: Some(els) }) = higher::If::hir(expr)
if let Some(higher::If {
cond,
then,
r#else: Some(els),
}) = higher::If::hir(expr)
&& let ExprKind::Block(then_block, _) = then.kind
&& let Some(then_expr) = then_block.expr
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
@ -86,7 +90,9 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
&& !contains_return(then_block.stmts)
{
let mut app = Applicability::Unspecified;
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app).maybe_par().to_string();
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
.maybe_par()
.to_string();
let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
let mut method_body = if then_block.stmts.is_empty() {
arg_snip.into_owned()
@ -100,9 +106,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
"then"
};
let help = format!(
"consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",
);
let help =
format!("consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",);
span_lint_and_help(
cx,
IF_THEN_SOME_ELSE_NONE,

View file

@ -15,14 +15,14 @@ declare_clippy_lint! {
/// would detect a type change that `_` would ignore.
///
/// ### Example
/// ```rust
/// ```no_run
/// match std::fs::create_dir("tmp-work-dir") {
/// Ok(_) => println!("Working directory created"),
/// Err(s) => eprintln!("Could not create directory: {s}"),
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// match std::fs::create_dir("tmp-work-dir") {
/// Ok(()) => println!("Working directory created"),
/// Err(s) => eprintln!("Could not create directory: {s}"),
@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
},
_ => {},
}
if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).is_unit() {
if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).peel_refs().is_unit() {
span_lint_and_sugg(
cx,
IGNORED_UNIT_PATTERNS,

View file

@ -35,7 +35,7 @@ declare_clippy_lint! {
/// pieces of code, possibly including external crates.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::collections::HashMap;
/// # use std::hash::{Hash, BuildHasher};
/// # trait Serialize {};
@ -44,7 +44,7 @@ declare_clippy_lint! {
/// pub fn foo(map: &mut HashMap<i32, i32>) { }
/// ```
/// could be rewritten as
/// ```rust
/// ```no_run
/// # use std::collections::HashMap;
/// # use std::hash::{Hash, BuildHasher};
/// # trait Serialize {};

View file

@ -24,13 +24,13 @@ declare_clippy_lint! {
/// corresponding statements.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn foo(x: usize) -> usize {
/// x
/// }
/// ```
/// add return
/// ```rust
/// ```no_run
/// fn foo(x: usize) -> usize {
/// return x;
/// }

View file

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// The built-in function is more readable and may be faster.
///
/// ### Example
/// ```rust
/// ```no_run
///let mut u:u32 = 7000;
///
/// if u != u32::MAX {
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
///let mut u:u32 = 7000;
///
/// u = u.saturating_add(1);
@ -82,18 +82,18 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
fn get_int_max(ty: Ty<'_>) -> Option<u128> {
match ty.peel_refs().kind() {
Int(IntTy::I8) => i8::max_value().try_into().ok(),
Int(IntTy::I16) => i16::max_value().try_into().ok(),
Int(IntTy::I32) => i32::max_value().try_into().ok(),
Int(IntTy::I64) => i64::max_value().try_into().ok(),
Int(IntTy::I128) => i128::max_value().try_into().ok(),
Int(IntTy::Isize) => isize::max_value().try_into().ok(),
Uint(UintTy::U8) => u8::max_value().try_into().ok(),
Uint(UintTy::U16) => u16::max_value().try_into().ok(),
Uint(UintTy::U32) => u32::max_value().try_into().ok(),
Uint(UintTy::U64) => u64::max_value().try_into().ok(),
Uint(UintTy::U128) => Some(u128::max_value()),
Uint(UintTy::Usize) => usize::max_value().try_into().ok(),
Int(IntTy::I8) => i8::MAX.try_into().ok(),
Int(IntTy::I16) => i16::MAX.try_into().ok(),
Int(IntTy::I32) => i32::MAX.try_into().ok(),
Int(IntTy::I64) => i64::MAX.try_into().ok(),
Int(IntTy::I128) => i128::MAX.try_into().ok(),
Int(IntTy::Isize) => isize::MAX.try_into().ok(),
Uint(UintTy::U8) => Some(u8::MAX.into()),
Uint(UintTy::U16) => Some(u16::MAX.into()),
Uint(UintTy::U32) => Some(u32::MAX.into()),
Uint(UintTy::U64) => Some(u64::MAX.into()),
Uint(UintTy::U128) => Some(u128::MAX),
Uint(UintTy::Usize) => usize::MAX.try_into().ok(),
_ => None,
}
}

View file

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// Simplicity and readability. Instead we can easily use an builtin function.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let end: u32 = 10;
/// # let start: u32 = 5;
/// let mut i: u32 = end - start;
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let end: u32 = 10;
/// # let start: u32 = 5;
/// let mut i: u32 = end - start;

View file

@ -29,7 +29,7 @@ declare_clippy_lint! {
/// (e.g. `trait A {} trait B: A {} trait C: B {}`, then having an `fn() -> impl A + C`)
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::ops::{Deref,DerefMut};
/// fn f() -> impl Deref<Target = i32> + DerefMut<Target = i32> {
/// // ^^^^^^^^^^^^^^^^^^^ unnecessary bound, already implied by the `DerefMut` trait bound
@ -37,7 +37,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::ops::{Deref,DerefMut};
/// fn f() -> impl DerefMut<Target = i32> {
/// Box::new(123)
@ -230,19 +230,24 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
// Example:
// `impl Deref<Target = i32> + DerefMut<Target = u32>` is not allowed.
// `DerefMut::Target` needs to match `Deref::Target`.
let implied_bounds: Vec<_> = opaque_ty.bounds.iter().filter_map(|bound| {
if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
&& let [.., path] = poly_trait.trait_ref.path.segments
&& poly_trait.bound_generic_params.is_empty()
&& let Some(trait_def_id) = path.res.opt_def_id()
&& let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates
&& !predicates.is_empty() // If the trait has no supertrait, there is nothing to add.
{
Some((bound.span(), path, predicates, trait_def_id))
} else {
None
}
}).collect();
let implied_bounds: Vec<_> = opaque_ty
.bounds
.iter()
.filter_map(|bound| {
if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
&& let [.., path] = poly_trait.trait_ref.path.segments
&& poly_trait.bound_generic_params.is_empty()
&& let Some(trait_def_id) = path.res.opt_def_id()
&& let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates
&& !predicates.is_empty()
// If the trait has no supertrait, there is nothing to add.
{
Some((bound.span(), path, predicates, trait_def_id))
} else {
None
}
})
.collect();
// Lint all bounds in the `impl Trait` type that are also in the `implied_bounds` vec.
// This involves some extra logic when generic arguments are present, since
@ -253,30 +258,31 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args)
&& let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings)
&& let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id()
&& let Some((implied_by_span, implied_by_args, implied_by_bindings)) = implied_bounds
.iter()
.find_map(|&(span, implied_by_path, preds, implied_by_def_id)| {
let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args);
let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings);
&& let Some((implied_by_span, implied_by_args, implied_by_bindings)) =
implied_bounds
.iter()
.find_map(|&(span, implied_by_path, preds, implied_by_def_id)| {
let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args);
let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings);
preds.iter().find_map(|(clause, _)| {
if let ClauseKind::Trait(tr) = clause.kind().skip_binder()
&& tr.def_id() == def_id
&& is_same_generics(
cx.tcx,
tr.trait_ref.args,
implied_by_args,
implied_args,
implied_by_def_id,
def_id,
)
{
Some((span, implied_by_args, implied_by_bindings))
} else {
None
}
preds.iter().find_map(|(clause, _)| {
if let ClauseKind::Trait(tr) = clause.kind().skip_binder()
&& tr.def_id() == def_id
&& is_same_generics(
cx.tcx,
tr.trait_ref.args,
implied_by_args,
implied_args,
implied_by_def_id,
def_id,
)
{
Some((span, implied_by_args, implied_by_bindings))
} else {
None
}
})
})
})
{
emit_lint(
cx,
@ -286,7 +292,7 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
implied_bindings,
implied_by_bindings,
implied_by_args,
implied_by_span
implied_by_span,
);
}
}

View file

@ -19,7 +19,7 @@ declare_clippy_lint! {
/// Since the order of fields in a constructor doesn't affect the
/// resulted instance as the below example indicates,
///
/// ```rust
/// ```no_run
/// #[derive(Debug, PartialEq, Eq)]
/// struct Foo {
/// x: i32,
@ -35,7 +35,7 @@ declare_clippy_lint! {
/// inconsistent order can be confusing and decreases readability and consistency.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Foo {
/// x: i32,
/// y: i32,
@ -47,7 +47,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # struct Foo {
/// # x: i32,
/// # y: i32,

View file

@ -1,7 +1,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::is_copy;
use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
use if_chain::if_chain;
@ -31,7 +31,7 @@ declare_clippy_lint! {
/// patterns.
///
/// ### Example
/// ```rust
/// ```no_run
/// let slice: Option<&[u32]> = Some(&[1, 2, 3]);
///
/// if let Some(slice) = slice {
@ -39,7 +39,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// let slice: Option<&[u32]> = Some(&[1, 2, 3]);
///
/// if let Some(&[first, ..]) = slice {

View file

@ -26,7 +26,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let x = [1, 2, 3, 4];
/// // Index within bounds
///
@ -65,7 +65,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # #![allow(unused)]
///
/// # let x = vec![0; 5];

View file

@ -39,7 +39,7 @@ declare_clippy_lint! {
/// this lint is not clever enough to analyze it.
///
/// ### Example
/// ```rust
/// ```no_run
/// let infinite_iter = 0..;
/// # #[allow(unused)]
/// [0..].iter().zip(infinite_iter.take_while(|x| *x > 5));

View file

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// Splitting the implementation of a type makes the code harder to navigate.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct X;
/// impl X {
/// fn one() {}
@ -30,7 +30,7 @@ declare_clippy_lint! {
///
/// Could be written:
///
/// ```rust
/// ```no_run
/// struct X;
/// impl X {
/// fn one() {}

View file

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// This method is also implicitly defined if a type implements the `Display` trait. As the functionality of `Display` is much more versatile, it should be preferred.
///
/// ### Example
/// ```rust
/// ```no_run
/// pub struct A;
///
/// impl A {
@ -26,7 +26,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// use std::fmt;
///
/// pub struct A;
@ -51,7 +51,7 @@ declare_clippy_lint! {
/// This method is also implicitly defined if a type implements the `Display` trait. The less versatile inherent method will then shadow the implementation introduced by `Display`.
///
/// ### Example
/// ```rust
/// ```no_run
/// use std::fmt;
///
/// pub struct A;
@ -70,7 +70,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// use std::fmt;
///
/// pub struct A;

View file

@ -20,7 +20,7 @@ declare_clippy_lint! {
/// benefit as opposed to tuple initializers
///
/// ### Example
/// ```rust
/// ```no_run
/// struct TupleStruct(u8, u16);
///
/// let _ = TupleStruct {

View file

@ -18,7 +18,7 @@ declare_clippy_lint! {
/// The inline attribute is ignored for trait methods without bodies.
///
/// ### Example
/// ```rust
/// ```no_run
/// trait Animal {
/// #[inline]
/// fn name(&self) -> &'static str;

View file

@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{self, span_lint_and_sugg};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty;
@ -21,13 +21,13 @@ declare_clippy_lint! {
/// `prev_instant.elapsed()` also more clearly signals intention.
///
/// ### Example
/// ```rust
/// ```no_run
/// use std::time::Instant;
/// let prev_instant = Instant::now();
/// let duration = Instant::now() - prev_instant;
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// use std::time::Instant;
/// let prev_instant = Instant::now();
/// let duration = prev_instant.elapsed();
@ -47,13 +47,13 @@ declare_clippy_lint! {
/// unintentional panics.
///
/// ### Example
/// ```rust
/// ```no_run
/// # use std::time::{Instant, Duration};
/// let time_passed = Instant::now() - Duration::from_secs(5);
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # use std::time::{Instant, Duration};
/// let time_passed = Instant::now().checked_sub(Duration::from_secs(5));
/// ```

View file

@ -16,14 +16,14 @@ declare_clippy_lint! {
/// Readability -- better to use `> y` instead of `>= y + 1`.
///
/// ### Example
/// ```rust
/// ```no_run
/// # let x = 1;
/// # let y = 1;
/// if x >= y + 1 {}
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// # let x = 1;
/// # let y = 1;
/// if x > y {}

View file

@ -26,7 +26,7 @@ declare_clippy_lint! {
/// https://github.com/rust-lang/rust-clippy/issues/886
///
/// ### Example
/// ```rust
/// ```no_run
/// let x: u8 = 1;
/// (x as u32) > 300;
/// ```

View file

@ -26,7 +26,7 @@ declare_clippy_lint! {
/// (the prefixes are `Foo1` and `Foo2` respectively), as also `Bar螃`, `Bar蟹`
///
/// ### Example
/// ```rust
/// ```no_run
/// enum Cake {
/// BlackForestCake,
/// HummingbirdCake,
@ -34,7 +34,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// enum Cake {
/// BlackForest,
/// Hummingbird,
@ -56,14 +56,14 @@ declare_clippy_lint! {
/// It requires the user to type the module name twice.
///
/// ### Example
/// ```rust
/// ```no_run
/// mod cake {
/// struct BlackForestCake;
/// }
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// mod cake {
/// struct BlackForest;
/// }
@ -119,7 +119,7 @@ declare_clippy_lint! {
/// (the prefixes are `foo1` and `foo2` respectively), as also `bar螃`, `bar蟹`
///
/// ### Example
/// ```rust
/// ```no_run
/// struct Cake {
/// cake_sugar: u8,
/// cake_flour: u8,
@ -127,7 +127,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct Cake {
/// sugar: u8,
/// flour: u8,
@ -320,6 +320,11 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
return;
}
for var in def.variants {
check_enum_start(cx, item_name, var);
check_enum_end(cx, item_name, var);
}
let first = match def.variants.first() {
Some(variant) => variant.ident.name.as_str(),
None => return,
@ -328,8 +333,6 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
let mut post = pre.clone();
post.reverse();
for var in def.variants {
check_enum_start(cx, item_name, var);
check_enum_end(cx, item_name, var);
let name = var.ident.name.as_str();
let variant_split = camel_case_split(name);

View file

@ -16,7 +16,7 @@ declare_clippy_lint! {
/// it's hard to figure out which item is meant in a statement.
///
/// ### Example
/// ```rust
/// ```no_run
/// fn foo() {
/// println!("cake");
/// }
@ -31,7 +31,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// fn foo() {
/// println!("cake");
/// }

View file

@ -14,7 +14,7 @@ declare_clippy_lint! {
/// ### Why is this bad?
/// Having items declared after the testing module is confusing and may lead to bad test coverage.
/// ### Example
/// ```rust
/// ```no_run
/// #[cfg(test)]
/// mod tests {
/// // [...]
@ -25,7 +25,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// fn my_function() {
/// // [...]
/// }
@ -74,9 +74,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
if let Some(last) = after.last()
&& after.iter().all(|&item| {
!matches!(item.kind, ItemKind::Mod(_))
&& !item.span.from_expansion()
&& !is_from_proc_macro(cx, item)
!matches!(item.kind, ItemKind::Mod(_)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item)
})
&& !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id()))
{
@ -99,10 +97,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
{
diag.multipart_suggestion_with_style(
"move the items to before the test module was defined",
vec![
(prev.span.shrink_to_hi(), items),
(items_span, String::new())
],
vec![(prev.span.shrink_to_hi(), items), (items_span, String::new())],
Applicability::MachineApplicable,
SuggestionStyle::HideCodeAlways,
);

View file

@ -15,7 +15,7 @@ declare_clippy_lint! {
/// Methods named `iter` or `iter_mut` conventionally return an `Iterator`.
///
/// ### Example
/// ```rust
/// ```no_run
/// // `String` does not implement `Iterator`
/// struct Data {}
/// impl Data {
@ -25,7 +25,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// use std::str::Chars;
/// struct Data {}
/// impl Data {

View file

@ -19,8 +19,13 @@ declare_clippy_lint! {
/// It's not bad, but having them is idiomatic and allows the type to be used in for loops directly
/// (`for val in &iter {}`), without having to first call `iter()` or `iter_mut()`.
///
/// ### Limitations
/// This lint focuses on providing an idiomatic API. Therefore, it will only
/// lint on types which are accessible outside of the crate. For internal types,
/// the `IntoIterator` trait can be implemented on demand if it is actually needed.
///
/// ### Example
/// ```rust
/// ```no_run
/// struct MySlice<'a>(&'a [u8]);
/// impl<'a> MySlice<'a> {
/// pub fn iter(&self) -> std::slice::Iter<'a, u8> {
@ -29,7 +34,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct MySlice<'a>(&'a [u8]);
/// impl<'a> MySlice<'a> {
/// pub fn iter(&self) -> std::slice::Iter<'a, u8> {
@ -61,8 +66,16 @@ declare_clippy_lint! {
/// by just calling `.iter()`, instead of the more awkward `<&Type>::into_iter` or `(&val).into_iter()` syntax
/// in case of ambiguity with another `IntoIterator` impl.
///
/// ### Limitations
/// This lint focuses on providing an idiomatic API. Therefore, it will only
/// lint on types which are accessible outside of the crate. For internal types,
/// these methods can be added on demand if they are actually needed. Otherwise,
/// it would trigger the [`dead_code`] lint for the unused method.
///
/// [`dead_code`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#dead-code
///
/// ### Example
/// ```rust
/// ```no_run
/// struct MySlice<'a>(&'a [u8]);
/// impl<'a> IntoIterator for &MySlice<'a> {
/// type Item = &'a u8;
@ -73,7 +86,7 @@ declare_clippy_lint! {
/// }
/// ```
/// Use instead:
/// ```rust
/// ```no_run
/// struct MySlice<'a>(&'a [u8]);
/// impl<'a> MySlice<'a> {
/// pub fn iter(&self) -> std::slice::Iter<'a, u8> {
@ -104,6 +117,12 @@ fn is_nameable_in_impl_trait(ty: &rustc_hir::Ty<'_>) -> bool {
!matches!(ty.kind, TyKind::OpaqueDef(..))
}
fn is_ty_exported(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
ty.ty_adt_def()
.and_then(|adt| adt.did().as_local())
.is_some_and(|did| cx.effective_visibilities.is_exported(did))
}
/// Returns the deref chain of a type, starting with the type itself.
fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
iter::successors(Some(ty), |&ty| {
@ -136,17 +155,18 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
if let ItemKind::Impl(imp) = item.kind
&& let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind
&& let Some(trait_ref) = imp.of_trait
&& trait_ref.trait_def_id().is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did))
&& trait_ref
.trait_def_id()
.is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did))
&& let &ty::Ref(_, ty, mtbl) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
&& let expected_method_name = match mtbl {
Mutability::Mut => sym::iter_mut,
Mutability::Not => sym::iter,
}
&& !deref_chain(cx, ty)
.any(|ty| {
// We can't check inherent impls for slices, but we know that they have an `iter(_mut)` method
ty.peel_refs().is_slice() || adt_has_inherent_method(cx, ty, expected_method_name)
})
&& !deref_chain(cx, ty).any(|ty| {
// We can't check inherent impls for slices, but we know that they have an `iter(_mut)` method
ty.peel_refs().is_slice() || adt_has_inherent_method(cx, ty, expected_method_name)
})
&& let Some(iter_assoc_span) = imp.items.iter().find_map(|item| {
if item.ident.name == sym!(IntoIter) {
Some(cx.tcx.hir().impl_item(item.id).expect_type().span)
@ -154,6 +174,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
None
}
})
&& is_ty_exported(cx, ty)
{
span_lint_and_then(
cx,
@ -165,7 +186,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
// to avoid name ambiguities, as there might be an inherent into_iter method
// that we don't want to call.
let sugg = format!(
"
"
impl {self_ty_without_ref} {{
fn {expected_method_name}({ref_self}self) -> {iter_ty} {{
<{ref_self}Self as IntoIterator>::into_iter(self)
@ -183,9 +204,9 @@ impl {self_ty_without_ref} {{
sugg,
// Just like iter_without_into_iter, this suggestion is on a best effort basis
// and requires potentially adding lifetimes or moving them around.
Applicability::Unspecified
Applicability::Unspecified,
);
}
},
);
}
}
@ -221,11 +242,12 @@ impl {self_ty_without_ref} {{
cx.tcx,
cx.param_env,
iterator_did,
sym!(Item),
sym::Item,
[ret_ty],
)
// Only lint if the `IntoIterator` impl doesn't actually exist
&& !implements_trait(cx, ref_ty, into_iter_did, &[])
&& is_ty_exported(cx, ref_ty.peel_refs())
{
let self_ty_snippet = format!("{borrow_prefix}{}", snippet(cx, imp.self_ty.span, ".."));
@ -233,22 +255,26 @@ impl {self_ty_without_ref} {{
cx,
ITER_WITHOUT_INTO_ITER,
item.span,
&format!("`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`", item.ident),
&format!(
"`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`",
item.ident
),
|diag| {
// Get the lower span of the `impl` block, and insert the suggestion right before it:
// impl X {
// ^ fn iter(&self) -> impl IntoIterator { ... }
// }
let span_behind_impl = cx.tcx
let span_behind_impl = cx
.tcx
.def_span(cx.tcx.hir().parent_id(item.hir_id()).owner.def_id)
.shrink_to_lo();
let sugg = format!(
"
"
impl IntoIterator for {self_ty_snippet} {{
type IntoIter = {ret_ty};
type Iter = {iter_ty};
fn into_iter() -> Self::IntoIter {{
type Item = {iter_ty};
fn into_iter(self) -> Self::IntoIter {{
self.iter()
}}
}}
@ -262,7 +288,8 @@ impl IntoIterator for {self_ty_snippet} {{
// such as adding some lifetimes in the associated types, or importing types.
Applicability::Unspecified,
);
});
},
);
}
}
}

View file

@ -38,7 +38,7 @@ declare_clippy_lint! {
/// this may lead to a false positive.
///
/// ### Example
/// ```rust
/// ```no_run
/// enum Test {
/// A(i32),
/// B([i32; 8000]),
@ -46,7 +46,7 @@ declare_clippy_lint! {
/// ```
///
/// Use instead:
/// ```rust
/// ```no_run
/// // Possibly better
/// enum Test2 {
/// A(i32),

Some files were not shown because too many files have changed in this diff Show more