Skip to content

Commit f945351

Browse files
committed
Fix regex lints for regex 1.9.0
1 parent 3f4e599 commit f945351

File tree

3 files changed

+53
-27
lines changed

3 files changed

+53
-27
lines changed

clippy_lints/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
722722
store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
723723
store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
724724
store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
725-
store.register_late_pass(|_| Box::new(regex::Regex));
725+
store.register_late_pass(|_| Box::<regex::Regex>::default());
726726
let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
727727
store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone())));
728728
store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));

clippy_lints/src/regex.rs

+46-20
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use std::fmt::Display;
33
use clippy_utils::consts::{constant, Constant};
44
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
55
use clippy_utils::source::snippet_opt;
6-
use clippy_utils::{match_def_path, paths};
7-
use if_chain::if_chain;
6+
use clippy_utils::{def_path_def_ids, path_def_id, paths};
87
use rustc_ast::ast::{LitKind, StrStyle};
8+
use rustc_hir::def_id::DefIdMap;
99
use rustc_hir::{BorrowKind, Expr, ExprKind};
1010
use rustc_lint::{LateContext, LateLintPass};
11-
use rustc_session::{declare_lint_pass, declare_tool_lint};
11+
use rustc_session::{declare_tool_lint, impl_lint_pass};
1212
use rustc_span::source_map::{BytePos, Span};
1313

1414
declare_clippy_lint! {
@@ -55,26 +55,52 @@ declare_clippy_lint! {
5555
"trivial regular expressions"
5656
}
5757

58-
declare_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
58+
#[derive(Copy, Clone)]
59+
enum RegexKind {
60+
Unicode,
61+
UnicodeSet,
62+
Bytes,
63+
BytesSet,
64+
}
65+
66+
#[derive(Default)]
67+
pub struct Regex {
68+
definitions: DefIdMap<RegexKind>,
69+
}
70+
71+
impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
5972

6073
impl<'tcx> LateLintPass<'tcx> for Regex {
74+
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
75+
// We don't use `match_def_path` here because that relies on matching the exact path, which changed
76+
// between regex 1.8 and 1.9
77+
//
78+
// `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform
79+
// the operation once and store the results
80+
let mut resolve = |path, kind| {
81+
for id in def_path_def_ids(cx, path) {
82+
self.definitions.insert(id, kind);
83+
}
84+
};
85+
86+
resolve(&paths::REGEX_NEW, RegexKind::Unicode);
87+
resolve(&paths::REGEX_BUILDER_NEW, RegexKind::Unicode);
88+
resolve(&paths::REGEX_SET_NEW, RegexKind::UnicodeSet);
89+
resolve(&paths::REGEX_BYTES_NEW, RegexKind::Bytes);
90+
resolve(&paths::REGEX_BYTES_BUILDER_NEW, RegexKind::Bytes);
91+
resolve(&paths::REGEX_BYTES_SET_NEW, RegexKind::BytesSet);
92+
}
93+
6194
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
62-
if_chain! {
63-
if let ExprKind::Call(fun, [arg]) = expr.kind;
64-
if let ExprKind::Path(ref qpath) = fun.kind;
65-
if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
66-
then {
67-
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
68-
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
69-
check_regex(cx, arg, true);
70-
} else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) ||
71-
match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) {
72-
check_regex(cx, arg, false);
73-
} else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) {
74-
check_set(cx, arg, true);
75-
} else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) {
76-
check_set(cx, arg, false);
77-
}
95+
if let ExprKind::Call(fun, [arg]) = expr.kind
96+
&& let Some(def_id) = path_def_id(cx, fun)
97+
&& let Some(regex_kind) = self.definitions.get(&def_id)
98+
{
99+
match regex_kind {
100+
RegexKind::Unicode => check_regex(cx, arg, true),
101+
RegexKind::UnicodeSet => check_set(cx, arg, true),
102+
RegexKind::Bytes => check_regex(cx, arg, false),
103+
RegexKind::BytesSet => check_set(cx, arg, false),
78104
}
79105
}
80106
}

clippy_utils/src/paths.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
9494
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
9595
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
9696
pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
97-
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
98-
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
99-
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
100-
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
101-
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
102-
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
97+
pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
98+
pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
99+
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];
100+
pub const REGEX_BYTES_SET_NEW: [&str; 4] = ["regex", "bytes", "RegexSet", "new"];
101+
pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
102+
pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
103103
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
104104
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
105105
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];

0 commit comments

Comments
 (0)