Skip to content

Commit 9c4651f

Browse files
committed
Auto merge of rust-lang#7187 - camsteffen:avoid-break-exported, r=flip1995,phansch
Add avoid_breaking_exported_api config option changelog: Add `avoid_breaking_exported_api` config option for [`enum_variant_names`], [`large_types_passed_by_value`], [`trivially_copy_pass_by_ref`], [`unnecessary_wraps`], [`upper_case_acronyms`] and [`wrong_self_convention`]. changelog: Deprecates [`pub_enum_variant_names`] and [`wrong_pub_self_convention`] as the non-pub variants are now configurable. changelog: Fix various false negatives for `pub` items that are not exported from the crate. A couple changes to late passes in order to use `cx.access_levels.is_exported` rather than `item.vis.kind.is_pub`. I'm not sure how to better document the config option or lints that are (not) affected (see comments in rust-lang#6806). Suggestions are welcome. cc `@rust-lang/clippy` I added `/clippy.toml` to use the config internally and `/tests/clippy.toml` to maintain a default config in ui tests. Closes rust-lang#6806 Closes rust-lang#4504
2 parents f205dd1 + 6eea598 commit 9c4651f

28 files changed

+232
-232
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml
147147
value` mapping eg.
148148

149149
```toml
150+
avoid-breaking-exported-api = false
150151
blacklisted-names = ["toto", "tata", "titi"]
151152
cognitive-complexity-threshold = 30
152153
```

build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ fn main() {
1414
);
1515
println!(
1616
"cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
17-
rustc_tools_util::get_channel().unwrap_or_default()
17+
rustc_tools_util::get_channel()
1818
);
1919
}

clippy.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
avoid-breaking-exported-api = false

clippy_lints/src/deprecated_lints.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,22 @@ declare_deprecated_lint! {
141141
pub FILTER_MAP,
142142
"this lint has been replaced by `manual_filter_map`, a more specific lint"
143143
}
144+
145+
declare_deprecated_lint! {
146+
/// **What it does:** Nothing. This lint has been deprecated.
147+
///
148+
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
149+
/// enables the `enum_variant_names` lint for public items.
150+
/// ```
151+
pub PUB_ENUM_VARIANT_NAMES,
152+
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items"
153+
}
154+
155+
declare_deprecated_lint! {
156+
/// **What it does:** Nothing. This lint has been deprecated.
157+
///
158+
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
159+
/// enables the `wrong_self_conversion` lint for public items.
160+
pub WRONG_PUB_SELF_CONVENTION,
161+
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items"
162+
}

clippy_lints/src/enum_variants.rs

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use clippy_utils::camel_case;
44
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
55
use clippy_utils::source::is_present_in_source;
6-
use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind};
7-
use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
6+
use rustc_hir::{EnumDef, Item, ItemKind};
7+
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::{declare_tool_lint, impl_lint_pass};
99
use rustc_span::source_map::Span;
1010
use rustc_span::symbol::Symbol;
@@ -39,36 +39,6 @@ declare_clippy_lint! {
3939
"enums where all variants share a prefix/postfix"
4040
}
4141

42-
declare_clippy_lint! {
43-
/// **What it does:** Detects public enumeration variants that are
44-
/// prefixed or suffixed by the same characters.
45-
///
46-
/// **Why is this bad?** Public enumeration variant names should specify their variant,
47-
/// not repeat the enumeration name.
48-
///
49-
/// **Known problems:** None.
50-
///
51-
/// **Example:**
52-
/// ```rust
53-
/// pub enum Cake {
54-
/// BlackForestCake,
55-
/// HummingbirdCake,
56-
/// BattenbergCake,
57-
/// }
58-
/// ```
59-
/// Could be written as:
60-
/// ```rust
61-
/// pub enum Cake {
62-
/// BlackForest,
63-
/// Hummingbird,
64-
/// Battenberg,
65-
/// }
66-
/// ```
67-
pub PUB_ENUM_VARIANT_NAMES,
68-
pedantic,
69-
"public enums where all variants share a prefix/postfix"
70-
}
71-
7242
declare_clippy_lint! {
7343
/// **What it does:** Detects type names that are prefixed or suffixed by the
7444
/// containing module's name.
@@ -127,21 +97,22 @@ declare_clippy_lint! {
12797
pub struct EnumVariantNames {
12898
modules: Vec<(Symbol, String)>,
12999
threshold: u64,
100+
avoid_breaking_exported_api: bool,
130101
}
131102

132103
impl EnumVariantNames {
133104
#[must_use]
134-
pub fn new(threshold: u64) -> Self {
105+
pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
135106
Self {
136107
modules: Vec::new(),
137108
threshold,
109+
avoid_breaking_exported_api,
138110
}
139111
}
140112
}
141113

142114
impl_lint_pass!(EnumVariantNames => [
143115
ENUM_VARIANT_NAMES,
144-
PUB_ENUM_VARIANT_NAMES,
145116
MODULE_NAME_REPETITIONS,
146117
MODULE_INCEPTION
147118
]);
@@ -167,33 +138,42 @@ fn partial_rmatch(post: &str, name: &str) -> usize {
167138
}
168139

169140
fn check_variant(
170-
cx: &EarlyContext<'_>,
141+
cx: &LateContext<'_>,
171142
threshold: u64,
172-
def: &EnumDef,
143+
def: &EnumDef<'_>,
173144
item_name: &str,
174145
item_name_chars: usize,
175146
span: Span,
176-
lint: &'static Lint,
177147
) {
178148
if (def.variants.len() as u64) < threshold {
179149
return;
180150
}
181-
for var in &def.variants {
151+
for var in def.variants {
182152
let name = var.ident.name.as_str();
183153
if partial_match(item_name, &name) == item_name_chars
184154
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
185155
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
186156
{
187-
span_lint(cx, lint, var.span, "variant name starts with the enum's name");
157+
span_lint(
158+
cx,
159+
ENUM_VARIANT_NAMES,
160+
var.span,
161+
"variant name starts with the enum's name",
162+
);
188163
}
189164
if partial_rmatch(item_name, &name) == item_name_chars {
190-
span_lint(cx, lint, var.span, "variant name ends with the enum's name");
165+
span_lint(
166+
cx,
167+
ENUM_VARIANT_NAMES,
168+
var.span,
169+
"variant name ends with the enum's name",
170+
);
191171
}
192172
}
193173
let first = &def.variants[0].ident.name.as_str();
194174
let mut pre = &first[..camel_case::until(&*first)];
195175
let mut post = &first[camel_case::from(&*first)..];
196-
for var in &def.variants {
176+
for var in def.variants {
197177
let name = var.ident.name.as_str();
198178

199179
let pre_match = partial_match(pre, &name);
@@ -226,7 +206,7 @@ fn check_variant(
226206
};
227207
span_lint_and_help(
228208
cx,
229-
lint,
209+
ENUM_VARIANT_NAMES,
230210
span,
231211
&format!("all variants have the same {}fix: `{}`", what, value),
232212
None,
@@ -261,14 +241,14 @@ fn to_camel_case(item_name: &str) -> String {
261241
s
262242
}
263243

264-
impl EarlyLintPass for EnumVariantNames {
265-
fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) {
244+
impl LateLintPass<'_> for EnumVariantNames {
245+
fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
266246
let last = self.modules.pop();
267247
assert!(last.is_some());
268248
}
269249

270250
#[allow(clippy::similar_names)]
271-
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
251+
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
272252
let item_name = item.ident.name.as_str();
273253
let item_name_chars = item_name.chars().count();
274254
let item_camel = to_camel_case(&item_name);
@@ -286,7 +266,7 @@ impl EarlyLintPass for EnumVariantNames {
286266
);
287267
}
288268
}
289-
if item.vis.kind.is_pub() {
269+
if item.vis.node.is_pub() {
290270
let matching = partial_match(mod_camel, &item_camel);
291271
let rmatching = partial_rmatch(mod_camel, &item_camel);
292272
let nchars = mod_camel.chars().count();
@@ -317,11 +297,9 @@ impl EarlyLintPass for EnumVariantNames {
317297
}
318298
}
319299
if let ItemKind::Enum(ref def, _) = item.kind {
320-
let lint = match item.vis.kind {
321-
VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES,
322-
_ => ENUM_VARIANT_NAMES,
323-
};
324-
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint);
300+
if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.hir_id())) {
301+
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
302+
}
325303
}
326304
self.modules.push((item.ident.name, item_camel));
327305
}

clippy_lints/src/lib.rs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,6 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
393393

394394
#[doc(hidden)]
395395
pub fn read_conf(sess: &Session) -> Conf {
396-
use std::path::Path;
397396
let file_name = match utils::conf::lookup_conf_file() {
398397
Ok(Some(path)) => path,
399398
Ok(None) => return Conf::default(),
@@ -404,16 +403,6 @@ pub fn read_conf(sess: &Session) -> Conf {
404403
},
405404
};
406405

407-
let file_name = if file_name.is_relative() {
408-
sess.local_crate_source_file
409-
.as_deref()
410-
.and_then(Path::parent)
411-
.unwrap_or_else(|| Path::new(""))
412-
.join(file_name)
413-
} else {
414-
file_name
415-
};
416-
417406
let TryConf { conf, errors } = utils::conf::read(&file_name);
418407
// all conf errors are non-fatal, we just use the default conf in case of error
419408
for error in errors {
@@ -493,6 +482,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
493482
"clippy::filter_map",
494483
"this lint has been replaced by `manual_filter_map`, a more specific lint",
495484
);
485+
store.register_removed(
486+
"clippy::pub_enum_variant_names",
487+
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items",
488+
);
489+
store.register_removed(
490+
"clippy::wrong_pub_self_convention",
491+
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items",
492+
);
496493
// end deprecated lints, do not remove this comment, it’s used in `update_lints`
497494

498495
// begin register lints, do not remove this comment, it’s used in `update_lints`
@@ -606,7 +603,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
606603
enum_variants::ENUM_VARIANT_NAMES,
607604
enum_variants::MODULE_INCEPTION,
608605
enum_variants::MODULE_NAME_REPETITIONS,
609-
enum_variants::PUB_ENUM_VARIANT_NAMES,
610606
eq_op::EQ_OP,
611607
eq_op::OP_REF,
612608
erasing_op::ERASING_OP,
@@ -790,7 +786,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
790786
methods::UNNECESSARY_LAZY_EVALUATIONS,
791787
methods::UNWRAP_USED,
792788
methods::USELESS_ASREF,
793-
methods::WRONG_PUB_SELF_CONVENTION,
794789
methods::WRONG_SELF_CONVENTION,
795790
methods::ZST_OFFSET,
796791
minmax::MIN_MAX,
@@ -1014,7 +1009,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10141009
LintId::of(methods::FILETYPE_IS_FILE),
10151010
LintId::of(methods::GET_UNWRAP),
10161011
LintId::of(methods::UNWRAP_USED),
1017-
LintId::of(methods::WRONG_PUB_SELF_CONVENTION),
10181012
LintId::of(misc::FLOAT_CMP_CONST),
10191013
LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
10201014
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
@@ -1066,7 +1060,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10661060
LintId::of(doc::MISSING_PANICS_DOC),
10671061
LintId::of(empty_enum::EMPTY_ENUM),
10681062
LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
1069-
LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES),
10701063
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
10711064
LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
10721065
LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
@@ -1850,7 +1843,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
18501843
})
18511844
});
18521845

1853-
store.register_late_pass(move || box methods::Methods::new(msrv));
1846+
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
1847+
store.register_late_pass(move || box methods::Methods::new(avoid_breaking_exported_api, msrv));
18541848
store.register_late_pass(move || box matches::Matches::new(msrv));
18551849
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
18561850
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
@@ -1932,6 +1926,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
19321926
let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
19331927
conf.trivial_copy_size_limit,
19341928
conf.pass_by_value_size_limit,
1929+
conf.avoid_breaking_exported_api,
19351930
&sess.target,
19361931
);
19371932
store.register_late_pass(move || box pass_by_ref_or_value);
@@ -1958,7 +1953,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
19581953
store.register_late_pass(|| box redundant_clone::RedundantClone);
19591954
store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
19601955
store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
1961-
store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
1956+
store.register_late_pass(move || box unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api));
19621957
store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
19631958
store.register_late_pass(|| box transmuting_null::TransmutingNull);
19641959
store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
@@ -1999,10 +1994,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
19991994
let literal_representation_threshold = conf.literal_representation_threshold;
20001995
store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
20011996
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
2002-
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
1997+
store.register_late_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold, avoid_breaking_exported_api));
20031998
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
20041999
let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
2005-
store.register_early_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(upper_case_acronyms_aggressive));
2000+
store.register_late_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(avoid_breaking_exported_api, upper_case_acronyms_aggressive));
20062001
store.register_late_pass(|| box default::Default::default());
20072002
store.register_late_pass(|| box unused_self::UnusedSelf);
20082003
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);

0 commit comments

Comments
 (0)