about summary refs log tree commit diff
path: root/clippy_lints/src
diff options
context:
space:
mode:
Diffstat (limited to 'clippy_lints/src')
-rw-r--r--clippy_lints/src/cognitive_complexity.rs22
-rw-r--r--clippy_lints/src/copies.rs16
-rw-r--r--clippy_lints/src/implicit_hasher.rs40
-rw-r--r--clippy_lints/src/matches/single_match.rs4
-rw-r--r--clippy_lints/src/methods/manual_inspect.rs31
-rw-r--r--clippy_lints/src/missing_doc.rs7
-rw-r--r--clippy_lints/src/multiple_bound_locations.rs8
-rw-r--r--clippy_lints/src/needless_else.rs16
-rw-r--r--clippy_lints/src/needless_if.rs24
-rw-r--r--clippy_lints/src/non_octal_unix_permissions.rs12
-rw-r--r--clippy_lints/src/octal_escapes.rs15
-rw-r--r--clippy_lints/src/ranges.rs19
12 files changed, 107 insertions, 107 deletions
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index e41abf42234..60815f4f2af 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -1,7 +1,7 @@
 //! calculate cognitive complexity and warn about overly complex functions
 
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{get_async_fn_body, is_async_fn, LimitStack};
@@ -12,7 +12,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnDecl};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -50,7 +50,6 @@ impl CognitiveComplexity {
 impl_lint_pass!(CognitiveComplexity => [COGNITIVE_COMPLEXITY]);
 
 impl CognitiveComplexity {
-    #[expect(clippy::cast_possible_truncation)]
     fn check<'tcx>(
         &mut self,
         cx: &LateContext<'tcx>,
@@ -100,17 +99,12 @@ impl CognitiveComplexity {
                 FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
                 FnKind::Closure => {
                     let header_span = body_span.with_hi(decl.output.span().lo());
-                    let pos = snippet_opt(cx, header_span).and_then(|snip| {
-                        let low_offset = snip.find('|')?;
-                        let high_offset = 1 + snip.get(low_offset + 1..)?.find('|')?;
-                        let low = header_span.lo() + BytePos(low_offset as u32);
-                        let high = low + BytePos(high_offset as u32 + 1);
-
-                        Some((low, high))
-                    });
-
-                    if let Some((low, high)) = pos {
-                        Span::new(low, high, header_span.ctxt(), header_span.parent())
+                    #[expect(clippy::range_plus_one)]
+                    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 {
                         return;
                     }
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 480df675d75..d896452be92 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
-use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
+use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, IntoSpan, SpanRangeExt};
 use clippy_utils::ty::{needs_ordered_drop, InteriorMut};
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{
@@ -14,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::hygiene::walk_chain;
 use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, Span, Symbol};
+use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
 
 declare_clippy_lint! {
@@ -266,12 +266,12 @@ fn lint_branches_sharing_code<'tcx>(
 
         let span = span.with_hi(last_block.span.hi());
         // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
-        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent());
-        let span = if snippet_opt(cx, test_span).map_or(false, |snip| snip == "    ") {
-            span.with_lo(test_span.lo())
-        } else {
-            span
-        };
+        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)
+            })
+            .map_or(span, |range| range.with_ctxt(span.ctxt()));
         (span, suggestion.to_string())
     });
 
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index ca830af3b2f..344a04e6e7e 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -14,7 +14,7 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::source::{snippet, IntoSpan, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 
 declare_clippy_lint! {
@@ -59,10 +59,8 @@ declare_clippy_lint! {
 declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]);
 
 impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
-    #[expect(clippy::cast_possible_truncation, clippy::too_many_lines)]
+    #[expect(clippy::too_many_lines)]
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        use rustc_span::BytePos;
-
         fn suggestion(
             cx: &LateContext<'_>,
             diag: &mut Diag<'_, ()>,
@@ -123,10 +121,11 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                     }
 
                     let generics_suggestion_span = impl_.generics.span.substitute_dummy({
-                        let pos = snippet_opt(cx, item.span.until(target.span()))
-                            .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
-                        if let Some(pos) = pos {
-                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
+                        let range = (item.span.lo()..target.span().lo()).map_range(cx, |src, range| {
+                            Some(src.get(range.clone())?.find("impl")? + 4..range.end)
+                        });
+                        if let Some(range) = range {
+                            range.with_ctxt(item.span.ctxt())
                         } else {
                             return;
                         }
@@ -163,21 +162,16 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                             continue;
                         }
                         let generics_suggestion_span = generics.span.substitute_dummy({
-                            let pos = snippet_opt(
-                                cx,
-                                Span::new(
-                                    item.span.lo(),
-                                    body.params[0].pat.span.lo(),
-                                    item.span.ctxt(),
-                                    item.span.parent(),
-                                ),
-                            )
-                            .and_then(|snip| {
-                                let i = snip.find("fn")?;
-                                Some(item.span.lo() + BytePos((i + snip[i..].find('(')?) as u32))
-                            })
-                            .expect("failed to create span for type parameters");
-                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
+                            let range = (item.span.lo()..body.params[0].pat.span.lo()).map_range(cx, |src, range| {
+                                let (pre, post) = src.get(range.clone())?.split_once("fn")?;
+                                let pos = post.find('(')? + pre.len() + 2;
+                                Some(pos..pos)
+                            });
+                            if let Some(range) = range {
+                                range.with_ctxt(item.span.ctxt())
+                            } else {
+                                return;
+                            }
                         });
 
                         let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index 69791414f72..99fdbcff890 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{expr_block, get_source_text, snippet};
+use clippy_utils::source::{expr_block, snippet, SpanRangeExt};
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
 use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs};
 use core::cmp::max;
@@ -17,7 +17,7 @@ use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
 /// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
 /// match arms.
 fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
-    if let Some(ff) = get_source_text(cx, span)
+    if let Some(ff) = span.get_source_text(cx)
         && let Some(text) = ff.as_str()
     {
         text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*")
diff --git a/clippy_lints/src/methods/manual_inspect.rs b/clippy_lints/src/methods/manual_inspect.rs
index 2f9b951c6a7..e3ce64c246a 100644
--- a/clippy_lints/src/methods/manual_inspect.rs
+++ b/clippy_lints/src/methods/manual_inspect.rs
@@ -1,6 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{get_source_text, with_leading_whitespace, SpanRange};
+use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use clippy_utils::ty::get_field_by_name;
 use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures};
 use clippy_utils::{expr_use_ctxt, is_diag_item_method, is_diag_trait_item, path_to_local_id, ExprUseNode};
@@ -9,7 +9,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{BindingMode, BorrowKind, ByRef, ClosureKind, Expr, ExprKind, Mutability, Node, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
-use rustc_span::{sym, BytePos, Span, Symbol, DUMMY_SP};
+use rustc_span::{sym, Span, Symbol, DUMMY_SP};
 
 use super::MANUAL_INSPECT;
 
@@ -98,17 +98,19 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
         let mut addr_of_edits = Vec::with_capacity(delayed.len());
         for x in delayed {
             match x {
-                UseKind::Return(s) => edits.push((with_leading_whitespace(cx, s).set_span_pos(s), String::new())),
+                UseKind::Return(s) => edits.push((s.with_leading_whitespace(cx).with_ctxt(s.ctxt()), String::new())),
                 UseKind::Borrowed(s) => {
-                    if let Some(src) = get_source_text(cx, s)
-                        && let Some(src) = src.as_str()
-                        && let trim_src = src.trim_start_matches([' ', '\t', '\n', '\r', '('])
-                        && trim_src.starts_with('&')
-                    {
-                        let range = s.into_range();
-                        #[expect(clippy::cast_possible_truncation)]
-                        let start = BytePos(range.start.0 + (src.len() - trim_src.len()) as u32);
-                        addr_of_edits.push(((start..BytePos(start.0 + 1)).set_span_pos(s), String::new()));
+                    #[expect(clippy::range_plus_one)]
+                    let range = s.map_range(cx, |src, range| {
+                        let src = src.get(range.clone())?;
+                        let trimmed = src.trim_start_matches([' ', '\t', '\n', '\r', '(']);
+                        trimmed.starts_with('&').then(|| {
+                            let pos = range.start + src.len() - trimmed.len();
+                            pos..pos + 1
+                        })
+                    });
+                    if let Some(range) = range {
+                        addr_of_edits.push((range.with_ctxt(s.ctxt()), String::new()));
                     } else {
                         requires_copy = true;
                         requires_deref = true;
@@ -174,7 +176,10 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
                 }),
             ));
             edits.push((
-                with_leading_whitespace(cx, final_expr.span).set_span_pos(final_expr.span),
+                final_expr
+                    .span
+                    .with_leading_whitespace(cx)
+                    .with_ctxt(final_expr.span.ctxt()),
                 String::new(),
             ));
             let app = if edits.iter().any(|(s, _)| s.from_expansion()) {
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index ca344dc5c81..250fd5cbd48 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -8,7 +8,7 @@
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -266,8 +266,5 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 }
 
 fn span_to_snippet_contains_docs(cx: &LateContext<'_>, search_span: Span) -> bool {
-    let Some(snippet) = snippet_opt(cx, search_span) else {
-        return false;
-    };
-    snippet.lines().rev().any(|line| line.trim().starts_with("///"))
+    search_span.check_source_text(cx, |src| src.lines().rev().any(|line| line.trim().starts_with("///")))
 }
diff --git a/clippy_lints/src/multiple_bound_locations.rs b/clippy_lints/src/multiple_bound_locations.rs
index d608f3bf7b4..d276e29bace 100644
--- a/clippy_lints/src/multiple_bound_locations.rs
+++ b/clippy_lints/src/multiple_bound_locations.rs
@@ -6,7 +6,7 @@ use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -54,8 +54,10 @@ impl EarlyLintPass for MultipleBoundLocations {
                 match clause {
                     WherePredicate::BoundPredicate(pred) => {
                         if (!pred.bound_generic_params.is_empty() || !pred.bounds.is_empty())
-                            && let Some(name) = snippet_opt(cx, pred.bounded_ty.span)
-                            && let Some(bound_span) = generic_params_with_bounds.get(name.as_str())
+                            && let Some(Some(bound_span)) = pred
+                                .bounded_ty
+                                .span
+                                .with_source_text(cx, |src| generic_params_with_bounds.get(src))
                         {
                             emit_lint(cx, *bound_span, pred.bounded_ty.span);
                         }
diff --git a/clippy_lints/src/needless_else.rs b/clippy_lints/src/needless_else.rs
index b6aad69d166..f8bb72a16db 100644
--- a/clippy_lints/src/needless_else.rs
+++ b/clippy_lints/src/needless_else.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_opt, trim_span};
+use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
@@ -41,16 +41,16 @@ impl EarlyLintPass for NeedlessElse {
             && !expr.span.from_expansion()
             && !else_clause.span.from_expansion()
             && block.stmts.is_empty()
-            && let Some(trimmed) = expr.span.trim_start(then_block.span)
-            && let span = trim_span(cx.sess().source_map(), trimmed)
-            && let Some(else_snippet) = snippet_opt(cx, span)
-            // Ignore else blocks that contain comments or #[cfg]s
-            && !else_snippet.contains(['/', '#'])
+            && let range = (then_block.span.hi()..expr.span.hi()).trim_start(cx)
+            && range.clone().check_source_text(cx, |src| {
+                // Ignore else blocks that contain comments or #[cfg]s
+                !src.contains(['/', '#'])
+            })
         {
             span_lint_and_sugg(
                 cx,
                 NEEDLESS_ELSE,
-                span,
+                range.with_ctxt(expr.span.ctxt()),
                 "this `else` branch is empty",
                 "you can remove it",
                 String::new(),
diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs
index 51bee4b51f6..1d6233d432a 100644
--- a/clippy_lints/src/needless_if.rs
+++ b/clippy_lints/src/needless_if.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher::If;
 use clippy_utils::is_from_proc_macro;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{snippet_opt, SpanRangeExt};
 use rustc_errors::Applicability;
 use rustc_hir::{ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -39,18 +39,24 @@ declare_lint_pass!(NeedlessIf => [NEEDLESS_IF]);
 impl LateLintPass<'_> for NeedlessIf {
     fn check_stmt<'tcx>(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'tcx>) {
         if let StmtKind::Expr(expr) = stmt.kind
-            && let Some(If {cond, then, r#else: None }) = If::hir(expr)
+            && let Some(If {
+                cond,
+                then,
+                r#else: None,
+            }) = If::hir(expr)
             && let ExprKind::Block(block, ..) = then.kind
             && block.stmts.is_empty()
             && block.expr.is_none()
             && !in_external_macro(cx.sess(), expr.span)
-            && let Some(then_snippet) = snippet_opt(cx, then.span)
-            // Ignore
-            // - empty macro expansions
-            // - empty reptitions in macro expansions
-            // - comments
-            // - #[cfg]'d out code
-            && then_snippet.chars().all(|ch| matches!(ch, '{' | '}') || ch.is_ascii_whitespace())
+            && then.span.check_source_text(cx, |src| {
+                // Ignore
+                // - empty macro expansions
+                // - empty reptitions in macro expansions
+                // - comments
+                // - #[cfg]'d out code
+                src.bytes()
+                    .all(|ch| matches!(ch, b'{' | b'}') || ch.is_ascii_whitespace())
+            })
             && let Some(cond_snippet) = snippet_opt(cx, cond.span)
             && !is_from_proc_macro(cx, expr)
         {
diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs
index 2701d6bdca3..b915df52762 100644
--- a/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_opt, snippet_with_applicability};
+use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
 use clippy_utils::{match_def_path, paths};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -53,8 +53,9 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
                             && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())))
                     && let ExprKind::Lit(_) = param.kind
                     && param.span.eq_ctxt(expr.span)
-                    && let Some(snip) = snippet_opt(cx, param.span)
-                    && !(snip.starts_with("0o") || snip.starts_with("0b"))
+                    && param
+                        .span
+                        .check_source_text(cx, |src| !matches!(src.as_bytes(), [b'0', b'o' | b'b', ..]))
                 {
                     show_error(cx, param);
                 }
@@ -65,8 +66,9 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
                     && match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE)
                     && let ExprKind::Lit(_) = param.kind
                     && param.span.eq_ctxt(expr.span)
-                    && let Some(snip) = snippet_opt(cx, param.span)
-                    && !(snip.starts_with("0o") || snip.starts_with("0b"))
+                    && param
+                        .span
+                        .check_source_text(cx, |src| !matches!(src.as_bytes(), [b'0', b'o' | b'b', ..]))
                 {
                     show_error(cx, param);
                 }
diff --git a/clippy_lints/src/octal_escapes.rs b/clippy_lints/src/octal_escapes.rs
index 0a7a2cd616c..2eae9b23746 100644
--- a/clippy_lints/src/octal_escapes.rs
+++ b/clippy_lints/src/octal_escapes.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::get_source_text;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::token::LitKind;
 use rustc_ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
@@ -87,14 +87,11 @@ impl EarlyLintPass for OctalEscapes {
 
                     // Last check to make sure the source text matches what we read from the string.
                     // Macros are involved somehow if this doesn't match.
-                    if let Some(src) = get_source_text(cx, span)
-                        && let Some(src) = src.as_str()
-                        && match *src.as_bytes() {
-                            [b'\\', b'0', lo] => lo == c_lo,
-                            [b'\\', b'0', hi, lo] => hi == c_hi && lo == c_lo,
-                            _ => false,
-                        }
-                    {
+                    if span.check_source_text(cx, |src| match *src.as_bytes() {
+                        [b'\\', b'0', lo] => lo == c_lo,
+                        [b'\\', b'0', hi, lo] => hi == c_hi && lo == c_lo,
+                        _ => false,
+                    }) {
                         span_lint_and_then(cx, OCTAL_ESCAPES, span, "octal-looking escape in a literal", |diag| {
                             diag.help_once("octal escapes are not supported, `\\0` is always null")
                                 .span_suggestion(
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 186e548d373..4fdaa9f00a1 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
+use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{get_parent_expr, higher, in_constant, is_integer_const, path_to_local};
 use rustc_ast::ast::RangeLimits;
@@ -285,9 +285,10 @@ fn check_possible_range_contains(
     if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind
         && op == lhs_op.node
         && let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent())
-        && let Some(snip) = &snippet_opt(cx, new_span)
-        // Do not continue if we have mismatched number of parens, otherwise the suggestion is wrong
-        && snip.matches('(').count() == snip.matches(')').count()
+        && new_span.check_source_text(cx, |src| {
+            // Do not continue if we have mismatched number of parens, otherwise the suggestion is wrong
+            src.matches('(').count() == src.matches(')').count()
+        })
     {
         check_possible_range_contains(cx, op, new_lhs, right, expr, new_span);
     }
@@ -363,17 +364,19 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
             |diag| {
                 let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
                 let end = Sugg::hir(cx, y, "y").maybe_par();
-                if let Some(is_wrapped) = &snippet_opt(cx, span) {
-                    if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
+                match span.with_source_text(cx, |src| src.starts_with('(') && src.ends_with(')')) {
+                    Some(true) => {
                         diag.span_suggestion(span, "use", format!("({start}..={end})"), Applicability::MaybeIncorrect);
-                    } else {
+                    },
+                    Some(false) => {
                         diag.span_suggestion(
                             span,
                             "use",
                             format!("{start}..={end}"),
                             Applicability::MachineApplicable, // snippet
                         );
-                    }
+                    },
+                    None => {},
                 }
             },
         );