diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 1671737db018..4c8cd9669414 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -6,7 +6,7 @@ use clippy_utils::source::SpanRangeExt; use clippy_utils::{def_path_def_ids, path_def_id, paths}; use rustc_ast::ast::{LitKind, StrStyle}; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{BorrowKind, Expr, ExprKind}; +use rustc_hir::{BorrowKind, Expr, ExprKind, OwnerId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Span}; @@ -104,7 +104,7 @@ enum RegexKind { #[derive(Default)] pub struct Regex { definitions: DefIdMap, - loop_stack: Vec, + loop_stack: Vec<(OwnerId, Span)>, } impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX, REGEX_CREATION_IN_LOOPS]); @@ -135,7 +135,8 @@ impl<'tcx> LateLintPass<'tcx> for Regex { && let Some(def_id) = path_def_id(cx, fun) && let Some(regex_kind) = self.definitions.get(&def_id) { - if let Some(&loop_span) = self.loop_stack.last() + if let Some(&(loop_item_id, loop_span)) = self.loop_stack.last() + && loop_item_id == fun.hir_id.owner && (matches!(arg.kind, ExprKind::Lit(_)) || const_str(cx, arg).is_some()) { span_lint_and_help( @@ -154,8 +155,8 @@ impl<'tcx> LateLintPass<'tcx> for Regex { RegexKind::Bytes => check_regex(cx, arg, false), RegexKind::BytesSet => check_set(cx, arg, false), } - } else if let ExprKind::Loop(_, _, _, span) = expr.kind { - self.loop_stack.push(span); + } else if let ExprKind::Loop(block, _, _, span) = expr.kind { + self.loop_stack.push((block.hir_id.owner, span)); } } diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 3352239892c5..f607a2d50c6d 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -120,6 +120,8 @@ fn trivial_regex() { fn regex_creation_in_loops() { loop { + static STATIC_REGEX: std::sync::LazyLock = std::sync::LazyLock::new(|| Regex::new("a.b").unwrap()); + let regex = Regex::new("a.b"); //~^ ERROR: compiling a regex in a loop let regex = BRegex::new("a.b"); diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 38e14b163167..18dd538c68b4 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -196,7 +196,7 @@ LL | let binary_trivial_empty = BRegex::new("^$"); = help: consider using `str::is_empty` error: compiling a regex in a loop - --> tests/ui/regex.rs:123:21 + --> tests/ui/regex.rs:125:21 | LL | let regex = Regex::new("a.b"); | ^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | loop { = help: to override `-D warnings` add `#[allow(clippy::regex_creation_in_loops)]` error: compiling a regex in a loop - --> tests/ui/regex.rs:125:21 + --> tests/ui/regex.rs:127:21 | LL | let regex = BRegex::new("a.b"); | ^^^^^^^^^^^ @@ -222,7 +222,7 @@ LL | loop { | ^^^^ error: compiling a regex in a loop - --> tests/ui/regex.rs:131:25 + --> tests/ui/regex.rs:133:25 | LL | let regex = Regex::new("a.b"); | ^^^^^^^^^^ @@ -234,13 +234,13 @@ LL | loop { | ^^^^ error: compiling a regex in a loop - --> tests/ui/regex.rs:136:32 + --> tests/ui/regex.rs:138:32 | LL | let nested_regex = Regex::new("a.b"); | ^^^^^^^^^^ | help: move the regex construction outside this loop - --> tests/ui/regex.rs:135:9 + --> tests/ui/regex.rs:137:9 | LL | for _ in 0..10 { | ^^^^^^^^^^^^^^