Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clippy_lints/src/attrs/non_minimal_cfg.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{Attribute, NON_MINIMAL_CFG};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use rustc_ast::{MetaItemInner, MetaItemKind};
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use itertools::Itertools;
use rustc_ast::AttrStyle;
use rustc_errors::Applicability;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/attrs/useless_attribute.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::USELESS_ATTRIBUTE;
use super::utils::{is_lint_level, is_word, namespace_and_lint};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
use clippy_utils::source::{SpanExt, first_line_of_span};
use clippy_utils::sym;
use rustc_ast::{Attribute, Item, ItemKind};
use rustc_errors::Applicability;
Expand Down
3 changes: 1 addition & 2 deletions clippy_lints/src/bool_to_int_with_if.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::HasSession;
use clippy_utils::sugg::Sugg;
use clippy_utils::{higher, is_else_clause, is_in_const_context, span_contains_comment};
use rustc_ast::LitKind;
Expand Down Expand Up @@ -59,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
&& !is_in_const_context(cx)
{
let ty = cx.typeck_results().expr_ty(then);
let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
let mut applicability = if span_contains_comment(cx, expr.span) {
Applicability::MaybeIncorrect
} else {
Applicability::MachineApplicable
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/booleans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::higher::has_let_expr;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{eq_expr_value, sym};
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/borrow_deref_ref.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::reference::DEREF_ADDROF;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{get_parent_expr, is_expr_temporary_value, is_from_proc_macro, is_lint_allowed, is_mutable};
use rustc_errors::Applicability;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/casts/as_ptr_cast_mut.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/casts/cast_lossless.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_const_context;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/casts/manual_dangling_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use clippy_utils::{expr_or_init, is_path_diagnostic_item, std_or_core, sym};
use rustc_ast::LitKind;
use rustc_errors::Applicability;
Expand Down
28 changes: 13 additions & 15 deletions clippy_lints/src/casts/unnecessary_cast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::{SpanRangeExt, snippet_opt};
use clippy_utils::source::SpanExt;
use clippy_utils::visitors::{Visitable, for_each_expr_without_closures};
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
use rustc_ast::{LitFloatType, LitIntType, LitKind};
Expand All @@ -23,7 +23,10 @@ pub(super) fn check<'tcx>(
cast_from: Ty<'tcx>,
cast_to: Ty<'tcx>,
) -> bool {
let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
// FIXME: Delay this to where it's needed.
let Some(src) = cast_expr.span.get_source_text(cx) else {
return false;
};

if let ty::RawPtr(..) = cast_from.kind()
// check both mutability and type are the same
Expand Down Expand Up @@ -56,7 +59,7 @@ pub(super) fn check<'tcx>(
"casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"
),
"try",
cast_str.clone(),
src.to_owned(),
Applicability::MaybeIncorrect,
);
}
Expand Down Expand Up @@ -102,10 +105,7 @@ pub(super) fn check<'tcx>(
}

if let Some(lit) = get_numeric_literal(cast_expr) {
let literal_str = &cast_str;

if let LitKind::Int(n, _) = lit.node
&& let Some(src) = cast_expr.span.get_source_text(cx)
&& cast_to.is_floating_point()
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
&& let from_nbits = 128 - n.get().leading_zeros()
Expand All @@ -121,20 +121,18 @@ pub(super) fn check<'tcx>(

match lit.node {
LitKind::Int(_, LitIntType::Unsuffixed) if cast_to.is_integral() => {
lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
lint_unnecessary_cast(cx, expr, &src, cast_from, cast_to);
return false;
},
LitKind::Float(_, LitFloatType::Unsuffixed) if cast_to.is_floating_point() => {
lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
lint_unnecessary_cast(cx, expr, &src, cast_from, cast_to);
return false;
},
LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_))
| LitKind::Float(_, LitFloatType::Suffixed(_))
if cast_from.kind() == cast_to.kind() =>
{
if let Some(src) = cast_expr.span.get_source_text(cx)
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
{
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
return true;
}
Expand Down Expand Up @@ -167,7 +165,7 @@ pub(super) fn check<'tcx>(
sym::assert_ne_macro,
sym::debug_assert_ne_macro,
];
matches!(expr.span.ctxt().outer_expn_data().macro_def_id, Some(def_id) if
matches!(expr.span.ctxt().outer_expn_data().macro_def_id, Some(def_id) if
cx.tcx.get_diagnostic_name(def_id).is_some_and(|sym| ALLOWED_MACROS.contains(&sym)))
}

Expand Down Expand Up @@ -196,9 +194,9 @@ pub(super) fn check<'tcx>(
format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
"try",
match surrounding {
MaybeParenOrBlock::Paren => format!("({cast_str})"),
MaybeParenOrBlock::Block => format!("{{ {cast_str} }}"),
MaybeParenOrBlock::Nothing => cast_str,
MaybeParenOrBlock::Paren => format!("({src})"),
MaybeParenOrBlock::Block => format!("{{ {src} }}"),
MaybeParenOrBlock::Nothing => src.to_owned(),
},
Applicability::MachineApplicable,
);
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/casts/zero_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::source::SpanExt;
use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability, Ty, TyKind};
Expand Down
17 changes: 9 additions & 8 deletions clippy_lints/src/cognitive_complexity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::{IntoSpan, SpanRangeExt};
use clippy_utils::source::SpanExt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn, sym};
Expand Down Expand Up @@ -110,14 +110,15 @@ impl CognitiveComplexity {
FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
FnKind::Closure => {
let header_span = body_span.with_hi(decl.output.span().lo());
if let Some(range) = header_span.map_range(cx, |_, src, range| {
let mut idxs = src.get(range.clone())?.match_indices('|');
Some(range.start + idxs.next()?.0..range.start + idxs.next()?.0 + 1)
}) {
range.with_ctxt(header_span.ctxt())
} else {
let Some(s) = header_span.map_range(cx, |range| {
range.edit_range(|src, range| {
let mut idxs = src.get(range.clone())?.match_indices('|');
Some(range.start + idxs.next()?.0..range.start + idxs.next()?.0 + 1)
})
}) else {
return;
}
};
s
},
};

Expand Down
31 changes: 15 additions & 16 deletions clippy_lints/src/collapsible_if.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{IntoSpan as _, SpanRangeExt, snippet, snippet_block_with_applicability};
use clippy_utils::source::{SourceFileRange, SpanExt, snippet, snippet_block_with_applicability};
use clippy_utils::{span_contains_non_whitespace, tokenize_with_text};
use rustc_ast::BinOpKind;
use rustc_errors::Applicability;
Expand Down Expand Up @@ -113,15 +113,15 @@ impl CollapsibleIf {
span_extract_keyword(cx.tcx.sess.source_map(), up_to_else, "else")
&& let Some(else_if_keyword_span) =
span_extract_keyword(cx.tcx.sess.source_map(), else_before_if, "if")
&& let Some(else_keyword_span) =
else_keyword_span.map_range(cx, SourceFileRange::add_leading_whitespace)
&& let Some(else_open_bracket) = else_block
.span
.map_range(cx, |range| range.set_to_prefix('{')?.add_leading_whitespace())
&& let Some(else_closing_bracket) = else_block
.span
.map_range(cx, |range| range.set_to_suffix('}')?.add_leading_whitespace())
{
let else_keyword_span = else_keyword_span.with_leading_whitespace(cx).into_span();
let else_open_bracket = else_block.span.split_at(1).0.with_leading_whitespace(cx).into_span();
let else_closing_bracket = {
let end = else_block.span.shrink_to_hi();
end.with_lo(end.lo() - BytePos(1))
.with_leading_whitespace(cx)
.into_span()
};
let sugg = vec![
// Remove the outer else block `else`
(else_keyword_span, String::new()),
Expand Down Expand Up @@ -171,20 +171,19 @@ impl CollapsibleIf {
&& self.eligible_condition(cx, check_inner)
&& expr.span.eq_ctxt(inner.span)
&& !block_starts_with_significant_tokens(cx, then, inner, self.lint_commented_code)
&& let Some(then_open_bracket) = then
.span
.map_range(cx, |range| range.set_to_prefix('{')?.add_leading_whitespace())
&& let Some(then_closing_bracket) = then
.span
.map_range(cx, |range| range.set_to_suffix('}')?.add_leading_whitespace())
{
span_lint_and_then(
cx,
COLLAPSIBLE_IF,
expr.span,
"this `if` statement can be collapsed",
|diag| {
let then_open_bracket = then.span.split_at(1).0.with_leading_whitespace(cx).into_span();
let then_closing_bracket = {
let end = then.span.shrink_to_hi();
end.with_lo(end.lo() - BytePos(1))
.with_leading_whitespace(cx)
.into_span()
};
let (paren_start, inner_if_span, paren_end) = peel_parens(cx.tcx.sess.source_map(), inner.span);
let inner_if = inner_if_span.split_at(2).0;
let mut sugg = vec![
Expand Down
20 changes: 11 additions & 9 deletions clippy_lints/src/copies.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint, span_lint_and_note, span_lint_and_then};
use clippy_utils::higher::has_let_expr;
use clippy_utils::source::{IntoSpan, SpanRangeExt, first_line_of_span, indent_of, reindent_multiline, snippet};
use clippy_utils::source::{SpanExt, first_line_of_span, indent_of, reindent_multiline, snippet};
use clippy_utils::ty::{InteriorMut, needs_ordered_drop};
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{
Expand Down Expand Up @@ -239,21 +239,23 @@ fn lint_branches_sharing_code<'tcx>(
let suggestion = reindent_multiline(&suggestion, true, cond_indent);
(replace_span, suggestion)
});
let end_suggestion = res.end_span(last_block, sm).map(|span| {
let end_suggestion = res.end_span(last_block, sm).and_then(|span| {
let moved_snipped = reindent_multiline(&snippet(cx, span, "_"), true, None);
let indent = indent_of(cx, expr.span.shrink_to_hi());
let suggestion = "}\n".to_string() + &moved_snipped;
let suggestion = reindent_multiline(&suggestion, true, indent);

let span = span.with_hi(last_block.span.hi());
// Improve formatting if the inner block has indentation (i.e. normal Rust formatting)
let span = span
.map_range(cx, |_, src, range| {
(range.start > 4 && src.get(range.start - 4..range.start)? == " ")
.then_some(range.start - 4..range.end)
let span = span.map_range(cx, |range| {
range.set_end_if_after(last_block.span.hi())?.edit_range(|src, range| {
if src.get(..range.start)?.ends_with(" ") {
Some(range.start - 4..range.end)
} else {
Some(range)
}
})
.map_or(span, |range| range.with_ctxt(span.ctxt()));
(span, suggestion.clone())
})?;
Some((span, suggestion))
});

let (span, msg, end_span) = match (&start_suggestion, &end_suggestion) {
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/default_constructed_unit_structs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_ty_alias;
use clippy_utils::source::SpanRangeExt as _;
use clippy_utils::source::SpanExt as _;
use hir::ExprKind;
use hir::def::Res;
use rustc_errors::Applicability;
Expand Down Expand Up @@ -75,7 +75,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
&& !base.is_suggestable_infer_ty()
{
let mut removals = vec![(expr.span.with_lo(qpath.qself_span().hi()), String::new())];
if expr.span.with_source_text(cx, |s| s.starts_with('<')) == Some(true) {
if expr.span.check_source_text(cx, |s| s.starts_with('<')) {
// Remove `<`, '>` has already been removed by the existing removal expression.
removals.push((expr.span.with_hi(qpath.qself_span().lo()), String::new()));
}
Expand Down
48 changes: 30 additions & 18 deletions clippy_lints/src/default_numeric_fallback.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::numeric_literal;
use clippy_utils::source::snippet_opt;
use clippy_utils::source::SpanExt;
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{Visitor, walk_expr, walk_pat, walk_stmt};
Expand Down Expand Up @@ -63,6 +62,20 @@ impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback {
}
}

enum SuffixKind {
Int,
Float,
}
impl SuffixKind {
fn from_ty(ty: Ty<'_>) -> Option<Self> {
match *ty.kind() {
ty::Int(IntTy::I32) => Some(Self::Int),
ty::Float(FloatTy::F64) => Some(Self::Float),
_ => None,
}
}
}

struct NumericFallbackVisitor<'a, 'tcx> {
/// Stack manages type bound of exprs. The top element holds current expr type.
ty_bounds: Vec<ExplicitTyBound>,
Expand Down Expand Up @@ -90,31 +103,30 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
lit.node,
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)
)
&& let Some(suffix_kind) = SuffixKind::from_ty(lit_ty)
&& let Some(src) = lit.span.get_source_text(self.cx)
&& let Some(&final_char) = src.as_bytes().last()
{
let (suffix, is_float) = match lit_ty.kind() {
ty::Int(IntTy::I32) => ("i32", false),
ty::Float(FloatTy::F64) => ("f64", true),
_ => return,
};
span_lint_hir_and_then(
self.cx,
DEFAULT_NUMERIC_FALLBACK,
emit_hir_id,
lit.span,
"default numeric fallback might occur",
|diag| {
let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
src
} else {
match lit.node {
LitKind::Int(src, _) => format!("{src}"),
LitKind::Float(src, _) => format!("{src}"),
_ => unreachable!("Default numeric fallback never results in other types"),
}
let sugg = match (suffix_kind, final_char) {
(SuffixKind::Int, b'_') => "i32",
(SuffixKind::Int, _) => "_i32",
(SuffixKind::Float, b'_') => "f64",
(SuffixKind::Float, b'.') => "0_f64",
(SuffixKind::Float, _) => "_f64",
};

let sugg = numeric_literal::format(&src, Some(suffix), is_float);
diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
diag.span_suggestion_verbose(
lit.span.shrink_to_hi(),
"add a suffix",
sugg,
Applicability::MaybeIncorrect,
);
},
);
}
Expand Down
Loading