Auto merge of #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 #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 #6806
Closes #4504
This commit is contained in:
bors 2021-05-27 04:49:56 +00:00
commit 9c4651f2ee
28 changed files with 232 additions and 232 deletions

View file

@ -147,6 +147,7 @@ Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml
value` mapping eg. value` mapping eg.
```toml ```toml
avoid-breaking-exported-api = false
blacklisted-names = ["toto", "tata", "titi"] blacklisted-names = ["toto", "tata", "titi"]
cognitive-complexity-threshold = 30 cognitive-complexity-threshold = 30
``` ```

View file

@ -14,6 +14,6 @@ fn main() {
); );
println!( println!(
"cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
rustc_tools_util::get_channel().unwrap_or_default() rustc_tools_util::get_channel()
); );
} }

1
clippy.toml Normal file
View file

@ -0,0 +1 @@
avoid-breaking-exported-api = false

View file

@ -141,3 +141,22 @@ declare_deprecated_lint! {
pub FILTER_MAP, pub FILTER_MAP,
"this lint has been replaced by `manual_filter_map`, a more specific lint" "this lint has been replaced by `manual_filter_map`, a more specific lint"
} }
declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
/// enables the `enum_variant_names` lint for public items.
/// ```
pub PUB_ENUM_VARIANT_NAMES,
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items"
}
declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
/// enables the `wrong_self_conversion` lint for public items.
pub WRONG_PUB_SELF_CONVENTION,
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items"
}

View file

@ -3,8 +3,8 @@
use clippy_utils::camel_case; use clippy_utils::camel_case;
use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::source::is_present_in_source; use clippy_utils::source::is_present_in_source;
use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind}; use rustc_hir::{EnumDef, Item, ItemKind};
use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
@ -39,36 +39,6 @@ declare_clippy_lint! {
"enums where all variants share a prefix/postfix" "enums where all variants share a prefix/postfix"
} }
declare_clippy_lint! {
/// **What it does:** Detects public enumeration variants that are
/// prefixed or suffixed by the same characters.
///
/// **Why is this bad?** Public enumeration variant names should specify their variant,
/// not repeat the enumeration name.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// pub enum Cake {
/// BlackForestCake,
/// HummingbirdCake,
/// BattenbergCake,
/// }
/// ```
/// Could be written as:
/// ```rust
/// pub enum Cake {
/// BlackForest,
/// Hummingbird,
/// Battenberg,
/// }
/// ```
pub PUB_ENUM_VARIANT_NAMES,
pedantic,
"public enums where all variants share a prefix/postfix"
}
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Detects type names that are prefixed or suffixed by the /// **What it does:** Detects type names that are prefixed or suffixed by the
/// containing module's name. /// containing module's name.
@ -127,21 +97,22 @@ declare_clippy_lint! {
pub struct EnumVariantNames { pub struct EnumVariantNames {
modules: Vec<(Symbol, String)>, modules: Vec<(Symbol, String)>,
threshold: u64, threshold: u64,
avoid_breaking_exported_api: bool,
} }
impl EnumVariantNames { impl EnumVariantNames {
#[must_use] #[must_use]
pub fn new(threshold: u64) -> Self { pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
Self { Self {
modules: Vec::new(), modules: Vec::new(),
threshold, threshold,
avoid_breaking_exported_api,
} }
} }
} }
impl_lint_pass!(EnumVariantNames => [ impl_lint_pass!(EnumVariantNames => [
ENUM_VARIANT_NAMES, ENUM_VARIANT_NAMES,
PUB_ENUM_VARIANT_NAMES,
MODULE_NAME_REPETITIONS, MODULE_NAME_REPETITIONS,
MODULE_INCEPTION MODULE_INCEPTION
]); ]);
@ -167,33 +138,42 @@ fn partial_rmatch(post: &str, name: &str) -> usize {
} }
fn check_variant( fn check_variant(
cx: &EarlyContext<'_>, cx: &LateContext<'_>,
threshold: u64, threshold: u64,
def: &EnumDef, def: &EnumDef<'_>,
item_name: &str, item_name: &str,
item_name_chars: usize, item_name_chars: usize,
span: Span, span: Span,
lint: &'static Lint,
) { ) {
if (def.variants.len() as u64) < threshold { if (def.variants.len() as u64) < threshold {
return; return;
} }
for var in &def.variants { for var in def.variants {
let name = var.ident.name.as_str(); let name = var.ident.name.as_str();
if partial_match(item_name, &name) == item_name_chars if partial_match(item_name, &name) == item_name_chars
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
{ {
span_lint(cx, lint, var.span, "variant name starts with the enum's name"); span_lint(
cx,
ENUM_VARIANT_NAMES,
var.span,
"variant name starts with the enum's name",
);
} }
if partial_rmatch(item_name, &name) == item_name_chars { if partial_rmatch(item_name, &name) == item_name_chars {
span_lint(cx, lint, var.span, "variant name ends with the enum's name"); span_lint(
cx,
ENUM_VARIANT_NAMES,
var.span,
"variant name ends with the enum's name",
);
} }
} }
let first = &def.variants[0].ident.name.as_str(); let first = &def.variants[0].ident.name.as_str();
let mut pre = &first[..camel_case::until(&*first)]; let mut pre = &first[..camel_case::until(&*first)];
let mut post = &first[camel_case::from(&*first)..]; let mut post = &first[camel_case::from(&*first)..];
for var in &def.variants { for var in def.variants {
let name = var.ident.name.as_str(); let name = var.ident.name.as_str();
let pre_match = partial_match(pre, &name); let pre_match = partial_match(pre, &name);
@ -226,7 +206,7 @@ fn check_variant(
}; };
span_lint_and_help( span_lint_and_help(
cx, cx,
lint, ENUM_VARIANT_NAMES,
span, span,
&format!("all variants have the same {}fix: `{}`", what, value), &format!("all variants have the same {}fix: `{}`", what, value),
None, None,
@ -261,14 +241,14 @@ fn to_camel_case(item_name: &str) -> String {
s s
} }
impl EarlyLintPass for EnumVariantNames { impl LateLintPass<'_> for EnumVariantNames {
fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) { fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
let last = self.modules.pop(); let last = self.modules.pop();
assert!(last.is_some()); assert!(last.is_some());
} }
#[allow(clippy::similar_names)] #[allow(clippy::similar_names)]
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
let item_name = item.ident.name.as_str(); let item_name = item.ident.name.as_str();
let item_name_chars = item_name.chars().count(); let item_name_chars = item_name.chars().count();
let item_camel = to_camel_case(&item_name); let item_camel = to_camel_case(&item_name);
@ -286,7 +266,7 @@ impl EarlyLintPass for EnumVariantNames {
); );
} }
} }
if item.vis.kind.is_pub() { if item.vis.node.is_pub() {
let matching = partial_match(mod_camel, &item_camel); let matching = partial_match(mod_camel, &item_camel);
let rmatching = partial_rmatch(mod_camel, &item_camel); let rmatching = partial_rmatch(mod_camel, &item_camel);
let nchars = mod_camel.chars().count(); let nchars = mod_camel.chars().count();
@ -317,11 +297,9 @@ impl EarlyLintPass for EnumVariantNames {
} }
} }
if let ItemKind::Enum(ref def, _) = item.kind { if let ItemKind::Enum(ref def, _) = item.kind {
let lint = match item.vis.kind { if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.hir_id())) {
VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES, check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
_ => ENUM_VARIANT_NAMES, }
};
check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint);
} }
self.modules.push((item.ident.name, item_camel)); self.modules.push((item.ident.name, item_camel));
} }

View file

@ -393,7 +393,6 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
#[doc(hidden)] #[doc(hidden)]
pub fn read_conf(sess: &Session) -> Conf { pub fn read_conf(sess: &Session) -> Conf {
use std::path::Path;
let file_name = match utils::conf::lookup_conf_file() { let file_name = match utils::conf::lookup_conf_file() {
Ok(Some(path)) => path, Ok(Some(path)) => path,
Ok(None) => return Conf::default(), Ok(None) => return Conf::default(),
@ -404,16 +403,6 @@ pub fn read_conf(sess: &Session) -> Conf {
}, },
}; };
let file_name = if file_name.is_relative() {
sess.local_crate_source_file
.as_deref()
.and_then(Path::parent)
.unwrap_or_else(|| Path::new(""))
.join(file_name)
} else {
file_name
};
let TryConf { conf, errors } = utils::conf::read(&file_name); let TryConf { conf, errors } = utils::conf::read(&file_name);
// all conf errors are non-fatal, we just use the default conf in case of error // all conf errors are non-fatal, we just use the default conf in case of error
for error in errors { for error in errors {
@ -493,6 +482,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
"clippy::filter_map", "clippy::filter_map",
"this lint has been replaced by `manual_filter_map`, a more specific lint", "this lint has been replaced by `manual_filter_map`, a more specific lint",
); );
store.register_removed(
"clippy::pub_enum_variant_names",
"set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items",
);
store.register_removed(
"clippy::wrong_pub_self_convention",
"set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items",
);
// end deprecated lints, do not remove this comment, its used in `update_lints` // end deprecated lints, do not remove this comment, its used in `update_lints`
// begin register lints, do not remove this comment, its used in `update_lints` // begin register lints, do not remove this comment, its used in `update_lints`
@ -606,7 +603,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
enum_variants::ENUM_VARIANT_NAMES, enum_variants::ENUM_VARIANT_NAMES,
enum_variants::MODULE_INCEPTION, enum_variants::MODULE_INCEPTION,
enum_variants::MODULE_NAME_REPETITIONS, enum_variants::MODULE_NAME_REPETITIONS,
enum_variants::PUB_ENUM_VARIANT_NAMES,
eq_op::EQ_OP, eq_op::EQ_OP,
eq_op::OP_REF, eq_op::OP_REF,
erasing_op::ERASING_OP, erasing_op::ERASING_OP,
@ -790,7 +786,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
methods::UNNECESSARY_LAZY_EVALUATIONS, methods::UNNECESSARY_LAZY_EVALUATIONS,
methods::UNWRAP_USED, methods::UNWRAP_USED,
methods::USELESS_ASREF, methods::USELESS_ASREF,
methods::WRONG_PUB_SELF_CONVENTION,
methods::WRONG_SELF_CONVENTION, methods::WRONG_SELF_CONVENTION,
methods::ZST_OFFSET, methods::ZST_OFFSET,
minmax::MIN_MAX, minmax::MIN_MAX,
@ -1014,7 +1009,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(methods::FILETYPE_IS_FILE), LintId::of(methods::FILETYPE_IS_FILE),
LintId::of(methods::GET_UNWRAP), LintId::of(methods::GET_UNWRAP),
LintId::of(methods::UNWRAP_USED), LintId::of(methods::UNWRAP_USED),
LintId::of(methods::WRONG_PUB_SELF_CONVENTION),
LintId::of(misc::FLOAT_CMP_CONST), LintId::of(misc::FLOAT_CMP_CONST),
LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), 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:
LintId::of(doc::MISSING_PANICS_DOC), LintId::of(doc::MISSING_PANICS_DOC),
LintId::of(empty_enum::EMPTY_ENUM), LintId::of(empty_enum::EMPTY_ENUM),
LintId::of(enum_variants::MODULE_NAME_REPETITIONS), LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES),
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS), LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
@ -1850,7 +1843,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
}) })
}); });
store.register_late_pass(move || box methods::Methods::new(msrv)); let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
store.register_late_pass(move || box methods::Methods::new(avoid_breaking_exported_api, msrv));
store.register_late_pass(move || box matches::Matches::new(msrv)); store.register_late_pass(move || box matches::Matches::new(msrv));
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv)); store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv)); 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:
let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new( let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
conf.trivial_copy_size_limit, conf.trivial_copy_size_limit,
conf.pass_by_value_size_limit, conf.pass_by_value_size_limit,
conf.avoid_breaking_exported_api,
&sess.target, &sess.target,
); );
store.register_late_pass(move || box pass_by_ref_or_value); 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:
store.register_late_pass(|| box redundant_clone::RedundantClone); store.register_late_pass(|| box redundant_clone::RedundantClone);
store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit); store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy); store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps); store.register_late_pass(move || box unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api));
store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants); store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
store.register_late_pass(|| box transmuting_null::TransmutingNull); store.register_late_pass(|| box transmuting_null::TransmutingNull);
store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite); 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:
let literal_representation_threshold = conf.literal_representation_threshold; let literal_representation_threshold = conf.literal_representation_threshold;
store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold)); store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
let enum_variant_name_threshold = conf.enum_variant_name_threshold; let enum_variant_name_threshold = conf.enum_variant_name_threshold;
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold)); store.register_late_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold, avoid_breaking_exported_api));
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments); store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive; let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
store.register_early_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(upper_case_acronyms_aggressive)); store.register_late_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(avoid_breaking_exported_api, upper_case_acronyms_aggressive));
store.register_late_pass(|| box default::Default::default()); store.register_late_pass(|| box default::Default::default());
store.register_late_pass(|| box unused_self::UnusedSelf); store.register_late_pass(|| box unused_self::UnusedSelf);
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall); store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);

View file

@ -282,30 +282,6 @@ declare_clippy_lint! {
"defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention" "defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
} }
declare_clippy_lint! {
/// **What it does:** This is the same as
/// [`wrong_self_convention`](#wrong_self_convention), but for public items.
///
/// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention).
///
/// **Known problems:** Actually *renaming* the function may break clients if
/// the function is part of the public interface. In that case, be mindful of
/// the stability guarantees you've given your users.
///
/// **Example:**
/// ```rust
/// # struct X;
/// impl<'a> X {
/// pub fn as_str(self) -> &'a str {
/// "foo"
/// }
/// }
/// ```
pub WRONG_PUB_SELF_CONVENTION,
restriction,
"defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
}
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for usage of `ok().expect(..)`. /// **What it does:** Checks for usage of `ok().expect(..)`.
/// ///
@ -1658,13 +1634,17 @@ declare_clippy_lint! {
} }
pub struct Methods { pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Option<RustcVersion>, msrv: Option<RustcVersion>,
} }
impl Methods { impl Methods {
#[must_use] #[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self { pub fn new(avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>) -> Self {
Self { msrv } Self {
avoid_breaking_exported_api,
msrv,
}
} }
} }
@ -1673,7 +1653,6 @@ impl_lint_pass!(Methods => [
EXPECT_USED, EXPECT_USED,
SHOULD_IMPLEMENT_TRAIT, SHOULD_IMPLEMENT_TRAIT,
WRONG_SELF_CONVENTION, WRONG_SELF_CONVENTION,
WRONG_PUB_SELF_CONVENTION,
OK_EXPECT, OK_EXPECT,
MAP_UNWRAP_OR, MAP_UNWRAP_OR,
RESULT_MAP_OR_INTO_OPTION, RESULT_MAP_OR_INTO_OPTION,
@ -1838,11 +1817,13 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
} }
} }
if sig.decl.implicit_self.has_implicit_self() { if sig.decl.implicit_self.has_implicit_self()
&& !(self.avoid_breaking_exported_api
&& cx.access_levels.is_exported(impl_item.hir_id()))
{
wrong_self_convention::check( wrong_self_convention::check(
cx, cx,
&name, &name,
item.vis.node.is_pub(),
self_ty, self_ty,
first_arg_ty, first_arg_ty,
first_arg.pat.span, first_arg.pat.span,
@ -1915,7 +1896,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
wrong_self_convention::check( wrong_self_convention::check(
cx, cx,
&item.ident.name.as_str(), &item.ident.name.as_str(),
false,
self_ty, self_ty,
first_arg_ty, first_arg_ty,
first_arg_span, first_arg_span,

View file

@ -6,7 +6,6 @@ use rustc_middle::ty::TyS;
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use std::fmt; use std::fmt;
use super::WRONG_PUB_SELF_CONVENTION;
use super::WRONG_SELF_CONVENTION; use super::WRONG_SELF_CONVENTION;
#[rustfmt::skip] #[rustfmt::skip]
@ -85,18 +84,12 @@ impl fmt::Display for Convention {
pub(super) fn check<'tcx>( pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
item_name: &str, item_name: &str,
is_pub: bool,
self_ty: &'tcx TyS<'tcx>, self_ty: &'tcx TyS<'tcx>,
first_arg_ty: &'tcx TyS<'tcx>, first_arg_ty: &'tcx TyS<'tcx>,
first_arg_span: Span, first_arg_span: Span,
implements_trait: bool, implements_trait: bool,
is_trait_item: bool, is_trait_item: bool,
) { ) {
let lint = if is_pub {
WRONG_PUB_SELF_CONVENTION
} else {
WRONG_SELF_CONVENTION
};
if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| { if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| {
convs convs
.iter() .iter()
@ -142,7 +135,7 @@ pub(super) fn check<'tcx>(
span_lint_and_help( span_lint_and_help(
cx, cx,
lint, WRONG_SELF_CONVENTION,
first_arg_span, first_arg_span,
&format!( &format!(
"{} usually take {}", "{} usually take {}",

View file

@ -102,10 +102,16 @@ declare_clippy_lint! {
pub struct PassByRefOrValue { pub struct PassByRefOrValue {
ref_min_size: u64, ref_min_size: u64,
value_max_size: u64, value_max_size: u64,
avoid_breaking_exported_api: bool,
} }
impl<'tcx> PassByRefOrValue { impl<'tcx> PassByRefOrValue {
pub fn new(ref_min_size: Option<u64>, value_max_size: u64, target: &Target) -> Self { pub fn new(
ref_min_size: Option<u64>,
value_max_size: u64,
avoid_breaking_exported_api: bool,
target: &Target,
) -> Self {
let ref_min_size = ref_min_size.unwrap_or_else(|| { let ref_min_size = ref_min_size.unwrap_or_else(|| {
let bit_width = u64::from(target.pointer_width); let bit_width = u64::from(target.pointer_width);
// Cap the calculated bit width at 32-bits to reduce // Cap the calculated bit width at 32-bits to reduce
@ -120,10 +126,14 @@ impl<'tcx> PassByRefOrValue {
Self { Self {
ref_min_size, ref_min_size,
value_max_size, value_max_size,
avoid_breaking_exported_api,
} }
} }
fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) { fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) {
if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) {
return;
}
let fn_def_id = cx.tcx.hir().local_def_id(hir_id); let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
let fn_sig = cx.tcx.fn_sig(fn_def_id); let fn_sig = cx.tcx.fn_sig(fn_def_id);
@ -184,7 +194,6 @@ impl<'tcx> PassByRefOrValue {
} }
if_chain! { if_chain! {
if !cx.access_levels.is_exported(hir_id);
if is_copy(cx, ty); if is_copy(cx, ty);
if !is_self_ty(input); if !is_self_ty(input);
if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());

View file

@ -8,7 +8,7 @@ use rustc_hir::LangItem::{OptionSome, ResultOk};
use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node}; use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::Span; use rustc_span::Span;
@ -52,7 +52,19 @@ declare_clippy_lint! {
"functions that only return `Ok` or `Some`" "functions that only return `Ok` or `Some`"
} }
declare_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]); pub struct UnnecessaryWraps {
avoid_breaking_exported_api: bool,
}
impl_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]);
impl UnnecessaryWraps {
pub fn new(avoid_breaking_exported_api: bool) -> Self {
Self {
avoid_breaking_exported_api,
}
}
}
impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
fn check_fn( fn check_fn(
@ -66,13 +78,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
) { ) {
// Abort if public function/method or closure. // Abort if public function/method or closure.
match fn_kind { match fn_kind {
FnKind::ItemFn(.., visibility) | FnKind::Method(.., Some(visibility)) => { FnKind::ItemFn(..) | FnKind::Method(..) => {
if visibility.node.is_pub() { if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) {
return; return;
} }
}, },
FnKind::Closure => return, FnKind::Closure => return,
FnKind::Method(..) => (),
} }
// Abort if the method is implementing a trait or of it a trait method. // Abort if the method is implementing a trait or of it a trait method.

View file

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use itertools::Itertools; use itertools::Itertools;
use rustc_ast::ast::{Item, ItemKind, VisibilityKind};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
@ -38,12 +38,14 @@ declare_clippy_lint! {
#[derive(Default)] #[derive(Default)]
pub struct UpperCaseAcronyms { pub struct UpperCaseAcronyms {
avoid_breaking_exported_api: bool,
upper_case_acronyms_aggressive: bool, upper_case_acronyms_aggressive: bool,
} }
impl UpperCaseAcronyms { impl UpperCaseAcronyms {
pub fn new(aggressive: bool) -> Self { pub fn new(avoid_breaking_exported_api: bool, aggressive: bool) -> Self {
Self { Self {
avoid_breaking_exported_api,
upper_case_acronyms_aggressive: aggressive, upper_case_acronyms_aggressive: aggressive,
} }
} }
@ -72,7 +74,7 @@ fn correct_ident(ident: &str) -> String {
ident ident
} }
fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) { fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) {
let span = ident.span; let span = ident.span;
let ident = &ident.as_str(); let ident = &ident.as_str();
let corrected = correct_ident(ident); let corrected = correct_ident(ident);
@ -96,23 +98,27 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) {
} }
} }
impl EarlyLintPass for UpperCaseAcronyms { impl LateLintPass<'_> for UpperCaseAcronyms {
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) { fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) {
// do not lint public items or in macros // do not lint public items or in macros
if !in_external_macro(cx.sess(), it.span) && !matches!(it.vis.kind, VisibilityKind::Public) { if in_external_macro(cx.sess(), it.span)
if matches!( || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.hir_id()))
it.kind, {
ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) return;
) { }
match it.kind {
ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => {
check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive); check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
} else if let ItemKind::Enum(ref enumdef, _) = it.kind { },
ItemKind::Enum(ref enumdef, _) => {
// check enum variants seperately because again we only want to lint on private enums and // check enum variants seperately because again we only want to lint on private enums and
// the fn check_variant does not know about the vis of the enum of its variants // the fn check_variant does not know about the vis of the enum of its variants
enumdef enumdef
.variants .variants
.iter() .iter()
.for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive)); .for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive));
} },
_ => {},
} }
} }
} }

View file

@ -122,6 +122,8 @@ macro_rules! define_Conf {
// N.B., this macro is parsed by util/lintlib.py // N.B., this macro is parsed by util/lintlib.py
define_Conf! { define_Conf! {
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION. Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
/// Lint: CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports /// Lint: CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports
(msrv: Option<String> = None), (msrv: Option<String> = None),
/// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
@ -208,15 +210,13 @@ pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
.map_or_else(|| PathBuf::from("."), PathBuf::from); .map_or_else(|| PathBuf::from("."), PathBuf::from);
loop { loop {
for config_file_name in &CONFIG_FILE_NAMES { for config_file_name in &CONFIG_FILE_NAMES {
let config_file = current.join(config_file_name); if let Ok(config_file) = current.join(config_file_name).canonicalize() {
match fs::metadata(&config_file) { match fs::metadata(&config_file) {
// Only return if it's a file to handle the unlikely situation of a directory named Err(e) if e.kind() == io::ErrorKind::NotFound => {},
// `clippy.toml`. Err(e) => return Err(e),
Ok(ref md) if !md.is_dir() => return Ok(Some(config_file)), Ok(md) if md.is_dir() => {},
// Return the error if it's something other than `NotFound`; otherwise we didn't Ok(_) => return Ok(Some(config_file)),
// find the project file yet, and continue searching. }
Err(e) if e.kind() != io::ErrorKind::NotFound => return Err(e),
_ => {},
} }
} }

View file

@ -100,9 +100,9 @@ pub fn get_commit_date() -> Option<String> {
} }
#[must_use] #[must_use]
pub fn get_channel() -> Option<String> { pub fn get_channel() -> String {
match env::var("CFG_RELEASE_CHANNEL") { match env::var("CFG_RELEASE_CHANNEL") {
Ok(channel) => Some(channel), Ok(channel) => channel,
Err(_) => { Err(_) => {
// if that failed, try to ask rustc -V, do some parsing and find out // if that failed, try to ask rustc -V, do some parsing and find out
match std::process::Command::new("rustc") match std::process::Command::new("rustc")
@ -113,16 +113,16 @@ pub fn get_channel() -> Option<String> {
{ {
Some(rustc_output) => { Some(rustc_output) => {
if rustc_output.contains("beta") { if rustc_output.contains("beta") {
Some(String::from("beta")) String::from("beta")
} else if rustc_output.contains("stable") { } else if rustc_output.contains("stable") {
Some(String::from("stable")) String::from("stable")
} else { } else {
// default to nightly if we fail to parse // default to nightly if we fail to parse
Some(String::from("nightly")) String::from("nightly")
} }
}, },
// default to nightly // default to nightly
None => Some(String::from("nightly")), None => String::from("nightly"),
} }
}, },
} }

1
tests/clippy.toml Normal file
View file

@ -0,0 +1 @@
# default config for tests, overrides clippy.toml at the project root

View file

@ -4,8 +4,8 @@
use compiletest_rs as compiletest; use compiletest_rs as compiletest;
use compiletest_rs::common::Mode as TestMode; use compiletest_rs::common::Mode as TestMode;
use std::env::{self, set_var, var}; use std::env::{self, remove_var, set_var, var_os};
use std::ffi::OsStr; use std::ffi::{OsStr, OsString};
use std::fs; use std::fs;
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -88,9 +88,11 @@ fn default_config() -> compiletest::Config {
config config
} }
fn run_mode(cfg: &mut compiletest::Config) { fn run_ui(cfg: &mut compiletest::Config) {
cfg.mode = TestMode::Ui; cfg.mode = TestMode::Ui;
cfg.src_base = Path::new("tests").join("ui"); cfg.src_base = Path::new("tests").join("ui");
// use tests/clippy.toml
let _g = VarGuard::set("CARGO_MANIFEST_DIR", std::fs::canonicalize("tests").unwrap());
compiletest::run_tests(cfg); compiletest::run_tests(cfg);
} }
@ -114,7 +116,7 @@ fn run_ui_toml(config: &mut compiletest::Config) {
continue; continue;
} }
let dir_path = dir.path(); let dir_path = dir.path();
set_var("CARGO_MANIFEST_DIR", &dir_path); let _g = VarGuard::set("CARGO_MANIFEST_DIR", &dir_path);
for file in fs::read_dir(&dir_path)? { for file in fs::read_dir(&dir_path)? {
let file = file?; let file = file?;
let file_path = file.path(); let file_path = file.path();
@ -145,9 +147,7 @@ fn run_ui_toml(config: &mut compiletest::Config) {
let tests = compiletest::make_tests(config); let tests = compiletest::make_tests(config);
let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap_or_default();
let res = run_tests(config, tests); let res = run_tests(config, tests);
set_var("CARGO_MANIFEST_DIR", &manifest_dir);
match res { match res {
Ok(true) => {}, Ok(true) => {},
Ok(false) => panic!("Some tests failed"), Ok(false) => panic!("Some tests failed"),
@ -208,7 +208,7 @@ fn run_ui_cargo(config: &mut compiletest::Config) {
Some("main.rs") => {}, Some("main.rs") => {},
_ => continue, _ => continue,
} }
set_var("CLIPPY_CONF_DIR", case.path()); let _g = VarGuard::set("CLIPPY_CONF_DIR", case.path());
let paths = compiletest::common::TestPaths { let paths = compiletest::common::TestPaths {
file: file_path, file: file_path,
base: config.src_base.clone(), base: config.src_base.clone(),
@ -236,10 +236,8 @@ fn run_ui_cargo(config: &mut compiletest::Config) {
let tests = compiletest::make_tests(config); let tests = compiletest::make_tests(config);
let current_dir = env::current_dir().unwrap(); let current_dir = env::current_dir().unwrap();
let conf_dir = var("CLIPPY_CONF_DIR").unwrap_or_default();
let res = run_tests(config, &config.filters, tests); let res = run_tests(config, &config.filters, tests);
env::set_current_dir(current_dir).unwrap(); env::set_current_dir(current_dir).unwrap();
set_var("CLIPPY_CONF_DIR", conf_dir);
match res { match res {
Ok(true) => {}, Ok(true) => {},
@ -260,8 +258,32 @@ fn prepare_env() {
fn compile_test() { fn compile_test() {
prepare_env(); prepare_env();
let mut config = default_config(); let mut config = default_config();
run_mode(&mut config); run_ui(&mut config);
run_ui_toml(&mut config); run_ui_toml(&mut config);
run_ui_cargo(&mut config); run_ui_cargo(&mut config);
run_internal_tests(&mut config); run_internal_tests(&mut config);
} }
/// Restores an env var on drop
#[must_use]
struct VarGuard {
key: &'static str,
value: Option<OsString>,
}
impl VarGuard {
fn set(key: &'static str, val: impl AsRef<OsStr>) -> Self {
let value = var_os(key);
set_var(key, val);
Self { key, value }
}
}
impl Drop for VarGuard {
fn drop(&mut self) {
match self.value.as_deref() {
None => remove_var(self.key),
Some(value) => set_var(self.key, value),
}
}
}

View file

@ -1,4 +1,4 @@
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1 error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1
error: aborting due to previous error error: aborting due to previous error

View file

@ -20,7 +20,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
0 0
} }
pub struct A; struct A;
impl A { impl A {
pub fn as_ref(self) -> &'static str { pub fn as_ref(self) -> &'static str {

View file

@ -12,5 +12,7 @@
#[warn(clippy::unknown_clippy_lints)] #[warn(clippy::unknown_clippy_lints)]
#[warn(clippy::find_map)] #[warn(clippy::find_map)]
#[warn(clippy::filter_map)] #[warn(clippy::filter_map)]
#[warn(clippy::pub_enum_variant_names)]
#[warn(clippy::wrong_pub_self_convention)]
fn main() {} fn main() {}

View file

@ -84,5 +84,17 @@ error: lint `clippy::filter_map` has been removed: this lint has been replaced b
LL | #[warn(clippy::filter_map)] LL | #[warn(clippy::filter_map)]
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
error: aborting due to 14 previous errors error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items
--> $DIR/deprecated.rs:15:8
|
LL | #[warn(clippy::pub_enum_variant_names)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items
--> $DIR/deprecated.rs:16:8
|
LL | #[warn(clippy::wrong_pub_self_convention)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 16 previous errors

View file

@ -1,5 +1,4 @@
#![feature(non_ascii_idents)] #![warn(clippy::enum_variant_names)]
#![warn(clippy::enum_variant_names, clippy::pub_enum_variant_names)]
#![allow(non_camel_case_types, clippy::upper_case_acronyms)] #![allow(non_camel_case_types, clippy::upper_case_acronyms)]
enum FakeCallType { enum FakeCallType {
@ -97,8 +96,8 @@ pub enum PubSeall {
WithOut, WithOut,
} }
#[allow(clippy::pub_enum_variant_names)] #[allow(clippy::enum_variant_names)]
mod allowed { pub mod allowed {
pub enum PubAllowed { pub enum PubAllowed {
SomeThis, SomeThis,
SomeThat, SomeThat,

View file

@ -1,5 +1,5 @@
error: variant name ends with the enum's name error: variant name ends with the enum's name
--> $DIR/enum_variants.rs:16:5 --> $DIR/enum_variants.rs:15:5
| |
LL | cFoo, LL | cFoo,
| ^^^^ | ^^^^
@ -7,25 +7,25 @@ LL | cFoo,
= note: `-D clippy::enum-variant-names` implied by `-D warnings` = note: `-D clippy::enum-variant-names` implied by `-D warnings`
error: variant name starts with the enum's name error: variant name starts with the enum's name
--> $DIR/enum_variants.rs:27:5 --> $DIR/enum_variants.rs:26:5
| |
LL | FoodGood, LL | FoodGood,
| ^^^^^^^^ | ^^^^^^^^
error: variant name starts with the enum's name error: variant name starts with the enum's name
--> $DIR/enum_variants.rs:28:5 --> $DIR/enum_variants.rs:27:5
| |
LL | FoodMiddle, LL | FoodMiddle,
| ^^^^^^^^^^ | ^^^^^^^^^^
error: variant name starts with the enum's name error: variant name starts with the enum's name
--> $DIR/enum_variants.rs:29:5 --> $DIR/enum_variants.rs:28:5
| |
LL | FoodBad, LL | FoodBad,
| ^^^^^^^ | ^^^^^^^
error: all variants have the same prefix: `Food` error: all variants have the same prefix: `Food`
--> $DIR/enum_variants.rs:26:1 --> $DIR/enum_variants.rs:25:1
| |
LL | / enum Food { LL | / enum Food {
LL | | FoodGood, LL | | FoodGood,
@ -37,7 +37,7 @@ LL | | }
= help: remove the prefixes and use full paths to the variants instead of glob imports = help: remove the prefixes and use full paths to the variants instead of glob imports
error: all variants have the same prefix: `CallType` error: all variants have the same prefix: `CallType`
--> $DIR/enum_variants.rs:36:1 --> $DIR/enum_variants.rs:35:1
| |
LL | / enum BadCallType { LL | / enum BadCallType {
LL | | CallTypeCall, LL | | CallTypeCall,
@ -49,7 +49,7 @@ LL | | }
= help: remove the prefixes and use full paths to the variants instead of glob imports = help: remove the prefixes and use full paths to the variants instead of glob imports
error: all variants have the same prefix: `Constant` error: all variants have the same prefix: `Constant`
--> $DIR/enum_variants.rs:48:1 --> $DIR/enum_variants.rs:47:1
| |
LL | / enum Consts { LL | / enum Consts {
LL | | ConstantInt, LL | | ConstantInt,
@ -61,7 +61,7 @@ LL | | }
= help: remove the prefixes and use full paths to the variants instead of glob imports = help: remove the prefixes and use full paths to the variants instead of glob imports
error: all variants have the same prefix: `With` error: all variants have the same prefix: `With`
--> $DIR/enum_variants.rs:82:1 --> $DIR/enum_variants.rs:81:1
| |
LL | / enum Seallll { LL | / enum Seallll {
LL | | WithOutCake, LL | | WithOutCake,
@ -73,7 +73,7 @@ LL | | }
= help: remove the prefixes and use full paths to the variants instead of glob imports = help: remove the prefixes and use full paths to the variants instead of glob imports
error: all variants have the same prefix: `Prefix` error: all variants have the same prefix: `Prefix`
--> $DIR/enum_variants.rs:88:1 --> $DIR/enum_variants.rs:87:1
| |
LL | / enum NonCaps { LL | / enum NonCaps {
LL | | Prefix的, LL | | Prefix的,
@ -84,21 +84,8 @@ LL | | }
| |
= help: remove the prefixes and use full paths to the variants instead of glob imports = help: remove the prefixes and use full paths to the variants instead of glob imports
error: all variants have the same prefix: `With`
--> $DIR/enum_variants.rs:94:1
|
LL | / pub enum PubSeall {
LL | | WithOutCake,
LL | | WithOutTea,
LL | | WithOut,
LL | | }
| |_^
|
= note: `-D clippy::pub-enum-variant-names` implied by `-D warnings`
= help: remove the prefixes and use full paths to the variants instead of glob imports
error: all variants have the same postfix: `IData` error: all variants have the same postfix: `IData`
--> $DIR/enum_variants.rs:137:1 --> $DIR/enum_variants.rs:136:1
| |
LL | / enum IDataRequest { LL | / enum IDataRequest {
LL | | PutIData(String), LL | | PutIData(String),
@ -110,7 +97,7 @@ LL | | }
= help: remove the postfixes and use full paths to the variants instead of glob imports = help: remove the postfixes and use full paths to the variants instead of glob imports
error: all variants have the same postfix: `HIData` error: all variants have the same postfix: `HIData`
--> $DIR/enum_variants.rs:143:1 --> $DIR/enum_variants.rs:142:1
| |
LL | / enum HIDataRequest { LL | / enum HIDataRequest {
LL | | PutHIData(String), LL | | PutHIData(String),
@ -121,5 +108,5 @@ LL | | }
| |
= help: remove the postfixes and use full paths to the variants instead of glob imports = help: remove the postfixes and use full paths to the variants instead of glob imports
error: aborting due to 12 previous errors error: aborting due to 11 previous errors

View file

@ -15,12 +15,4 @@ mod foo {
pub struct Foobar; pub struct Foobar;
} }
#[cfg(test)]
mod test {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
fn main() {} fn main() {}

View file

@ -88,12 +88,6 @@ error: this argument (N byte) is passed by reference, but would be more efficien
LL | fn trait_method(&self, _foo: &Foo); LL | fn trait_method(&self, _foo: &Foo);
| ^^^^ help: consider passing by value instead: `Foo` | ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
--> $DIR/trivially_copy_pass_by_ref.rs:80:37
|
LL | fn trait_method2(&self, _color: &Color);
| ^^^^^^ help: consider passing by value instead: `Color`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
--> $DIR/trivially_copy_pass_by_ref.rs:108:21 --> $DIR/trivially_copy_pass_by_ref.rs:108:21
| |
@ -106,5 +100,5 @@ error: this argument (N byte) is passed by reference, but would be more efficien
LL | fn foo(x: &i32) { LL | fn foo(x: &i32) {
| ^^^^ help: consider passing by value instead: `i32` | ^^^^ help: consider passing by value instead: `i32`
error: aborting due to 17 previous errors error: aborting due to 16 previous errors

View file

@ -65,7 +65,7 @@ fn func10() -> Option<()> {
unimplemented!() unimplemented!()
} }
struct A; pub struct A;
impl A { impl A {
// should not be linted // should not be linted

View file

@ -1,6 +1,5 @@
// edition:2018 // edition:2018
#![warn(clippy::wrong_self_convention)] #![warn(clippy::wrong_self_convention)]
#![warn(clippy::wrong_pub_self_convention)]
#![allow(dead_code)] #![allow(dead_code)]
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:18:17 --> $DIR/wrong_self_convention.rs:17:17
| |
LL | fn from_i32(self) {} LL | fn from_i32(self) {}
| ^^^^ | ^^^^
@ -8,7 +8,7 @@ LL | fn from_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:24:21 --> $DIR/wrong_self_convention.rs:23:21
| |
LL | pub fn from_i64(self) {} LL | pub fn from_i64(self) {}
| ^^^^ | ^^^^
@ -16,7 +16,7 @@ LL | pub fn from_i64(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
--> $DIR/wrong_self_convention.rs:36:15 --> $DIR/wrong_self_convention.rs:35:15
| |
LL | fn as_i32(self) {} LL | fn as_i32(self) {}
| ^^^^ | ^^^^
@ -24,7 +24,7 @@ LL | fn as_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value error: methods called `into_*` usually take `self` by value
--> $DIR/wrong_self_convention.rs:38:17 --> $DIR/wrong_self_convention.rs:37:17
| |
LL | fn into_i32(&self) {} LL | fn into_i32(&self) {}
| ^^^^^ | ^^^^^
@ -32,7 +32,7 @@ LL | fn into_i32(&self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self` error: methods called `is_*` usually take `self` by reference or no `self`
--> $DIR/wrong_self_convention.rs:40:15 --> $DIR/wrong_self_convention.rs:39:15
| |
LL | fn is_i32(self) {} LL | fn is_i32(self) {}
| ^^^^ | ^^^^
@ -40,7 +40,7 @@ LL | fn is_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
--> $DIR/wrong_self_convention.rs:42:15 --> $DIR/wrong_self_convention.rs:41:15
| |
LL | fn to_i32(self) {} LL | fn to_i32(self) {}
| ^^^^ | ^^^^
@ -48,7 +48,7 @@ LL | fn to_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:44:17 --> $DIR/wrong_self_convention.rs:43:17
| |
LL | fn from_i32(self) {} LL | fn from_i32(self) {}
| ^^^^ | ^^^^
@ -56,7 +56,7 @@ LL | fn from_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
--> $DIR/wrong_self_convention.rs:46:19 --> $DIR/wrong_self_convention.rs:45:19
| |
LL | pub fn as_i64(self) {} LL | pub fn as_i64(self) {}
| ^^^^ | ^^^^
@ -64,7 +64,7 @@ LL | pub fn as_i64(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value error: methods called `into_*` usually take `self` by value
--> $DIR/wrong_self_convention.rs:47:21 --> $DIR/wrong_self_convention.rs:46:21
| |
LL | pub fn into_i64(&self) {} LL | pub fn into_i64(&self) {}
| ^^^^^ | ^^^^^
@ -72,7 +72,7 @@ LL | pub fn into_i64(&self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self` error: methods called `is_*` usually take `self` by reference or no `self`
--> $DIR/wrong_self_convention.rs:48:19 --> $DIR/wrong_self_convention.rs:47:19
| |
LL | pub fn is_i64(self) {} LL | pub fn is_i64(self) {}
| ^^^^ | ^^^^
@ -80,7 +80,7 @@ LL | pub fn is_i64(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
--> $DIR/wrong_self_convention.rs:49:19 --> $DIR/wrong_self_convention.rs:48:19
| |
LL | pub fn to_i64(self) {} LL | pub fn to_i64(self) {}
| ^^^^ | ^^^^
@ -88,7 +88,7 @@ LL | pub fn to_i64(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:50:21 --> $DIR/wrong_self_convention.rs:49:21
| |
LL | pub fn from_i64(self) {} LL | pub fn from_i64(self) {}
| ^^^^ | ^^^^
@ -96,7 +96,7 @@ LL | pub fn from_i64(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
--> $DIR/wrong_self_convention.rs:95:19 --> $DIR/wrong_self_convention.rs:94:19
| |
LL | fn as_i32(self) {} LL | fn as_i32(self) {}
| ^^^^ | ^^^^
@ -104,7 +104,7 @@ LL | fn as_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value error: methods called `into_*` usually take `self` by value
--> $DIR/wrong_self_convention.rs:98:25 --> $DIR/wrong_self_convention.rs:97:25
| |
LL | fn into_i32_ref(&self) {} LL | fn into_i32_ref(&self) {}
| ^^^^^ | ^^^^^
@ -112,7 +112,7 @@ LL | fn into_i32_ref(&self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self` error: methods called `is_*` usually take `self` by reference or no `self`
--> $DIR/wrong_self_convention.rs:100:19 --> $DIR/wrong_self_convention.rs:99:19
| |
LL | fn is_i32(self) {} LL | fn is_i32(self) {}
| ^^^^ | ^^^^
@ -120,7 +120,7 @@ LL | fn is_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:104:21 --> $DIR/wrong_self_convention.rs:103:21
| |
LL | fn from_i32(self) {} LL | fn from_i32(self) {}
| ^^^^ | ^^^^
@ -128,7 +128,7 @@ LL | fn from_i32(self) {}
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
--> $DIR/wrong_self_convention.rs:119:19 --> $DIR/wrong_self_convention.rs:118:19
| |
LL | fn as_i32(self); LL | fn as_i32(self);
| ^^^^ | ^^^^
@ -136,7 +136,7 @@ LL | fn as_i32(self);
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value error: methods called `into_*` usually take `self` by value
--> $DIR/wrong_self_convention.rs:122:25 --> $DIR/wrong_self_convention.rs:121:25
| |
LL | fn into_i32_ref(&self); LL | fn into_i32_ref(&self);
| ^^^^^ | ^^^^^
@ -144,7 +144,7 @@ LL | fn into_i32_ref(&self);
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self` error: methods called `is_*` usually take `self` by reference or no `self`
--> $DIR/wrong_self_convention.rs:124:19 --> $DIR/wrong_self_convention.rs:123:19
| |
LL | fn is_i32(self); LL | fn is_i32(self);
| ^^^^ | ^^^^
@ -152,7 +152,7 @@ LL | fn is_i32(self);
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:128:21 --> $DIR/wrong_self_convention.rs:127:21
| |
LL | fn from_i32(self); LL | fn from_i32(self);
| ^^^^ | ^^^^
@ -160,7 +160,7 @@ LL | fn from_i32(self);
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value error: methods called `into_*` usually take `self` by value
--> $DIR/wrong_self_convention.rs:146:25 --> $DIR/wrong_self_convention.rs:145:25
| |
LL | fn into_i32_ref(&self); LL | fn into_i32_ref(&self);
| ^^^^^ | ^^^^^
@ -168,7 +168,7 @@ LL | fn into_i32_ref(&self);
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:152:21 --> $DIR/wrong_self_convention.rs:151:21
| |
LL | fn from_i32(self); LL | fn from_i32(self);
| ^^^^ | ^^^^
@ -176,7 +176,7 @@ LL | fn from_i32(self);
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
--> $DIR/wrong_self_convention.rs:176:22 --> $DIR/wrong_self_convention.rs:175:22
| |
LL | fn to_u64_v2(&self) -> u64 { LL | fn to_u64_v2(&self) -> u64 {
| ^^^^^ | ^^^^^
@ -184,7 +184,7 @@ LL | fn to_u64_v2(&self) -> u64 {
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
--> $DIR/wrong_self_convention.rs:185:19 --> $DIR/wrong_self_convention.rs:184:19
| |
LL | fn to_u64(self) -> u64 { LL | fn to_u64(self) -> u64 {
| ^^^^ | ^^^^

View file

@ -1,6 +1,5 @@
// edition:2018 // edition:2018
#![warn(clippy::wrong_self_convention)] #![warn(clippy::wrong_self_convention)]
#![warn(clippy::wrong_pub_self_convention)]
#![allow(dead_code)] #![allow(dead_code)]
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention2.rs:56:29 --> $DIR/wrong_self_convention2.rs:55:29
| |
LL | pub fn from_be_self(self) -> Self { LL | pub fn from_be_self(self) -> Self {
| ^^^^ | ^^^^
@ -8,7 +8,7 @@ LL | pub fn from_be_self(self) -> Self {
= help: consider choosing a less ambiguous name = help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self` error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention2.rs:65:25 --> $DIR/wrong_self_convention2.rs:64:25
| |
LL | fn from_be_self(self) -> Self; LL | fn from_be_self(self) -> Self;
| ^^^^ | ^^^^