Merge commit '7ea7cd165a' into clippyup2
This commit is contained in:
parent
e820a03d1c
commit
a0e9f9bd0d
84 changed files with 1552 additions and 435 deletions
|
|
@ -248,7 +248,6 @@ declare_lint_pass!(Attributes => [
|
|||
INLINE_ALWAYS,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||
UNKNOWN_CLIPPY_LINTS,
|
||||
]);
|
||||
|
||||
|
|
@ -480,36 +479,6 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib
|
|||
}
|
||||
|
||||
for attr in attrs {
|
||||
let attr_item = if let AttrKind::Normal(ref attr) = attr.kind {
|
||||
attr
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if attr.style == AttrStyle::Outer {
|
||||
if attr_item.args.inner_tokens().is_empty() || !is_present_in_source(cx, attr.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
let begin_of_attr_to_item = Span::new(attr.span.lo(), span.lo(), span.ctxt());
|
||||
let end_of_attr_to_item = Span::new(attr.span.hi(), span.lo(), span.ctxt());
|
||||
|
||||
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
|
||||
let lines = snippet.split('\n').collect::<Vec<_>>();
|
||||
let lines = without_block_comments(lines);
|
||||
|
||||
if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
|
||||
span_lint(
|
||||
cx,
|
||||
EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||
begin_of_attr_to_item,
|
||||
"Found an empty line after an outer attribute. \
|
||||
Perhaps you forgot to add a `!` to make it an inner attribute?",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(values) = attr.meta_item_list() {
|
||||
if values.len() != 1 || !attr.check_name(sym!(inline)) {
|
||||
continue;
|
||||
|
|
@ -551,15 +520,57 @@ fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
declare_lint_pass!(EarlyAttributes => [DEPRECATED_CFG_ATTR, MISMATCHED_TARGET_OS]);
|
||||
declare_lint_pass!(EarlyAttributes => [
|
||||
DEPRECATED_CFG_ATTR,
|
||||
MISMATCHED_TARGET_OS,
|
||||
EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||
]);
|
||||
|
||||
impl EarlyLintPass for EarlyAttributes {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) {
|
||||
check_empty_line_after_outer_attr(cx, item);
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
check_deprecated_cfg_attr(cx, attr);
|
||||
check_mismatched_target_os(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::ast::Item) {
|
||||
for attr in &item.attrs {
|
||||
let attr_item = if let AttrKind::Normal(ref attr) = attr.kind {
|
||||
attr
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
if attr.style == AttrStyle::Outer {
|
||||
if attr_item.args.inner_tokens().is_empty() || !is_present_in_source(cx, attr.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt());
|
||||
let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt());
|
||||
|
||||
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
|
||||
let lines = snippet.split('\n').collect::<Vec<_>>();
|
||||
let lines = without_block_comments(lines);
|
||||
|
||||
if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
|
||||
span_lint(
|
||||
cx,
|
||||
EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||
begin_of_attr_to_item,
|
||||
"Found an empty line after an outer attribute. \
|
||||
Perhaps you forgot to add a `!` to make it an inner attribute?",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if_chain! {
|
||||
// check cfg_attr
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ declare_clippy_lint! {
|
|||
/// [package]
|
||||
/// name = "clippy"
|
||||
/// version = "0.0.212"
|
||||
/// authors = ["Someone <someone@rust-lang.org>"]
|
||||
/// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
/// repository = "https://github.com/rust-lang/rust-clippy"
|
||||
/// readme = "README.md"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatLiteral {
|
|||
let type_suffix = match lit_float_ty {
|
||||
LitFloatType::Suffixed(FloatTy::F32) => Some("f32"),
|
||||
LitFloatType::Suffixed(FloatTy::F64) => Some("f64"),
|
||||
_ => None
|
||||
LitFloatType::Unsuffixed => None
|
||||
};
|
||||
let (is_whole, mut float_str) = match fty {
|
||||
FloatTy::F32 => {
|
||||
|
|
|
|||
|
|
@ -346,13 +346,8 @@ mod reexport {
|
|||
/// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
|
||||
///
|
||||
/// Used in `./src/driver.rs`.
|
||||
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &Conf) {
|
||||
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
|
||||
store.register_pre_expansion_pass(|| box write::Write::default());
|
||||
store.register_pre_expansion_pass(|| box redundant_field_names::RedundantFieldNames);
|
||||
let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
|
||||
store.register_pre_expansion_pass(move || box non_expressive_names::NonExpressiveNames {
|
||||
single_char_binding_names_threshold,
|
||||
});
|
||||
store.register_pre_expansion_pass(|| box attrs::EarlyAttributes);
|
||||
store.register_pre_expansion_pass(|| box dbg_macro::DbgMacro);
|
||||
}
|
||||
|
|
@ -638,6 +633,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&matches::MATCH_OVERLAPPING_ARM,
|
||||
&matches::MATCH_REF_PATS,
|
||||
&matches::MATCH_SINGLE_BINDING,
|
||||
&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
||||
&matches::MATCH_WILD_ERR_ARM,
|
||||
&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
|
||||
&matches::SINGLE_MATCH,
|
||||
|
|
@ -1065,6 +1061,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
|
||||
store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
|
||||
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
|
||||
store.register_early_pass(|| box redundant_field_names::RedundantFieldNames);
|
||||
let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
|
||||
store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
|
||||
single_char_binding_names_threshold,
|
||||
});
|
||||
|
||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
|
||||
|
|
@ -1139,6 +1140,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(¯o_use::MACRO_USE_IMPORTS),
|
||||
LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
|
||||
LintId::of(&matches::MATCH_BOOL),
|
||||
LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
|
||||
LintId::of(&matches::MATCH_WILD_ERR_ARM),
|
||||
LintId::of(&matches::SINGLE_MATCH_ELSE),
|
||||
LintId::of(&methods::FILTER_MAP),
|
||||
LintId::of(&methods::FILTER_MAP_NEXT),
|
||||
|
|
@ -1283,7 +1286,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(&matches::MATCH_OVERLAPPING_ARM),
|
||||
LintId::of(&matches::MATCH_REF_PATS),
|
||||
LintId::of(&matches::MATCH_SINGLE_BINDING),
|
||||
LintId::of(&matches::MATCH_WILD_ERR_ARM),
|
||||
LintId::of(&matches::SINGLE_MATCH),
|
||||
LintId::of(&matches::WILDCARD_IN_OR_PATTERNS),
|
||||
LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
|
||||
|
|
@ -1474,7 +1476,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
|
||||
LintId::of(&matches::MATCH_OVERLAPPING_ARM),
|
||||
LintId::of(&matches::MATCH_REF_PATS),
|
||||
LintId::of(&matches::MATCH_WILD_ERR_ARM),
|
||||
LintId::of(&matches::SINGLE_MATCH),
|
||||
LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
|
||||
LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ declare_clippy_lint! {
|
|||
/// **What it does:** Checks for arm which matches all errors with `Err(_)`
|
||||
/// and take drastic actions like `panic!`.
|
||||
///
|
||||
/// **Why is this bad?** It is generally a bad practice, just like
|
||||
/// **Why is this bad?** It is generally a bad practice, similar to
|
||||
/// catching all exceptions in java with `catch(Exception)`
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
|
|
@ -182,7 +182,7 @@ declare_clippy_lint! {
|
|||
/// }
|
||||
/// ```
|
||||
pub MATCH_WILD_ERR_ARM,
|
||||
style,
|
||||
pedantic,
|
||||
"a `match` with `Err(_)` arm and take drastic actions"
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ declare_clippy_lint! {
|
|||
/// # enum Foo { A(usize), B(usize) }
|
||||
/// # let x = Foo::B(1);
|
||||
/// match x {
|
||||
/// A => {},
|
||||
/// Foo::A(_) => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// ```
|
||||
|
|
@ -229,6 +229,40 @@ declare_clippy_lint! {
|
|||
"a wildcard enum match arm using `_`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for wildcard enum matches for a single variant.
|
||||
///
|
||||
/// **Why is this bad?** New enum variants added by library updates can be missed.
|
||||
///
|
||||
/// **Known problems:** Suggested replacements may not use correct path to enum
|
||||
/// if it's not present in the current scope.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// # enum Foo { A, B, C }
|
||||
/// # let x = Foo::B;
|
||||
/// match x {
|
||||
/// Foo::A => {},
|
||||
/// Foo::B => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// # enum Foo { A, B, C }
|
||||
/// # let x = Foo::B;
|
||||
/// match x {
|
||||
/// Foo::A => {},
|
||||
/// Foo::B => {},
|
||||
/// Foo::C => {},
|
||||
/// }
|
||||
/// ```
|
||||
pub MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
||||
pedantic,
|
||||
"a wildcard enum match for a single variant"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for wildcard pattern used with others patterns in same match arm.
|
||||
///
|
||||
|
|
@ -356,6 +390,7 @@ impl_lint_pass!(Matches => [
|
|||
MATCH_WILD_ERR_ARM,
|
||||
MATCH_AS_REF,
|
||||
WILDCARD_ENUM_MATCH_ARM,
|
||||
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
||||
WILDCARD_IN_OR_PATTERNS,
|
||||
MATCH_SINGLE_BINDING,
|
||||
INFALLIBLE_DESTRUCTURING_MATCH,
|
||||
|
|
@ -676,7 +711,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>])
|
|||
arm.pat.span,
|
||||
&format!("`Err({})` matches all errors", &ident_bind_name),
|
||||
None,
|
||||
"match each error separately or use the error output",
|
||||
"match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -729,9 +764,21 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_
|
|||
if let QPath::Resolved(_, p) = path {
|
||||
missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
|
||||
}
|
||||
} else if let PatKind::TupleStruct(ref path, ..) = arm.pat.kind {
|
||||
} else if let PatKind::TupleStruct(ref path, ref patterns, ..) = arm.pat.kind {
|
||||
if let QPath::Resolved(_, p) = path {
|
||||
missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
|
||||
// Some simple checks for exhaustive patterns.
|
||||
// There is a room for improvements to detect more cases,
|
||||
// but it can be more expensive to do so.
|
||||
let is_pattern_exhaustive = |pat: &&Pat<'_>| {
|
||||
if let PatKind::Wild | PatKind::Binding(.., None) = pat.kind {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
if patterns.iter().all(is_pattern_exhaustive) {
|
||||
missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -766,6 +813,19 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_
|
|||
}
|
||||
}
|
||||
|
||||
if suggestion.len() == 1 {
|
||||
// No need to check for non-exhaustive enum as in that case len would be greater than 1
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
||||
wildcard_span,
|
||||
message,
|
||||
"try this",
|
||||
suggestion[0].clone(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
WILDCARD_ENUM_MATCH_ARM,
|
||||
|
|
@ -773,7 +833,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_
|
|||
message,
|
||||
"try this",
|
||||
suggestion.join(" | "),
|
||||
Applicability::MachineApplicable,
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1496,17 +1496,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
|
|||
if let ty::Opaque(def_id, _) = ret_ty.kind {
|
||||
// one of the associated types must be Self
|
||||
for predicate in cx.tcx.predicates_of(def_id).predicates {
|
||||
match predicate.0.kind() {
|
||||
ty::PredicateKind::Projection(poly_projection_predicate) => {
|
||||
let binder = poly_projection_predicate.ty();
|
||||
let associated_type = binder.skip_binder();
|
||||
if let ty::PredicateKind::Projection(poly_projection_predicate) = predicate.0.kind() {
|
||||
let binder = poly_projection_predicate.ty();
|
||||
let associated_type = binder.skip_binder();
|
||||
|
||||
// walk the associated type and check for Self
|
||||
if contains_self_ty(associated_type) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
// walk the associated type and check for Self
|
||||
if contains_self_ty(associated_type) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1617,6 +1614,21 @@ fn lint_or_fun_call<'a, 'tcx>(
|
|||
or_has_args: bool,
|
||||
span: Span,
|
||||
) {
|
||||
if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.kind {
|
||||
if path.ident.as_str() == "len" {
|
||||
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
|
||||
|
||||
match ty.kind {
|
||||
ty::Slice(_) | ty::Array(_, _) => return,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if match_type(cx, ty, &paths::VEC) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (path, fn_has_argument, methods, suffix)
|
||||
let know_types: &[(&[_], _, &[_], _)] = &[
|
||||
(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ impl EarlyLintPass for MiscEarlyLints {
|
|||
let left_binding = match left {
|
||||
BindingMode::ByRef(Mutability::Mut) => "ref mut ",
|
||||
BindingMode::ByRef(Mutability::Not) => "ref ",
|
||||
_ => "",
|
||||
BindingMode::ByValue(..) => "",
|
||||
};
|
||||
|
||||
if let PatKind::Wild = right.kind {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn {
|
|||
return;
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
FnKind::Closure(..) => return,
|
||||
}
|
||||
|
||||
let mir = cx.tcx.optimized_mir(def_id);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
//! lint on multiple versions of a crate being used
|
||||
|
||||
use crate::utils::{run_lints, span_lint};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_hir::{Crate, CRATE_HIR_ID};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
|
||||
use cargo_metadata::{DependencyKind, MetadataCommand, Node, Package, PackageId};
|
||||
use if_chain::if_chain;
|
||||
use itertools::Itertools;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -39,30 +42,61 @@ impl LateLintPass<'_, '_> for MultipleCrateVersions {
|
|||
return;
|
||||
}
|
||||
|
||||
let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().exec() {
|
||||
let metadata = if let Ok(metadata) = MetadataCommand::new().exec() {
|
||||
metadata
|
||||
} else {
|
||||
span_lint(cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, "could not read cargo metadata");
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
let local_name = cx.tcx.crate_name(LOCAL_CRATE).as_str();
|
||||
let mut packages = metadata.packages;
|
||||
packages.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
|
||||
for (name, group) in &packages.into_iter().group_by(|p| p.name.clone()) {
|
||||
let group: Vec<cargo_metadata::Package> = group.collect();
|
||||
if_chain! {
|
||||
if let Some(resolve) = &metadata.resolve;
|
||||
if let Some(local_id) = packages
|
||||
.iter()
|
||||
.find_map(|p| if p.name == *local_name { Some(&p.id) } else { None });
|
||||
then {
|
||||
for (name, group) in &packages.iter().group_by(|p| p.name.clone()) {
|
||||
let group: Vec<&Package> = group.collect();
|
||||
|
||||
if group.len() > 1 {
|
||||
let versions = group.into_iter().map(|p| p.version).join(", ");
|
||||
if group.len() <= 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
span_lint(
|
||||
cx,
|
||||
MULTIPLE_CRATE_VERSIONS,
|
||||
DUMMY_SP,
|
||||
&format!("multiple versions for dependency `{}`: {}", name, versions),
|
||||
);
|
||||
if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) {
|
||||
let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect();
|
||||
versions.sort();
|
||||
let versions = versions.iter().join(", ");
|
||||
|
||||
span_lint(
|
||||
cx,
|
||||
MULTIPLE_CRATE_VERSIONS,
|
||||
DUMMY_SP,
|
||||
&format!("multiple versions for dependency `{}`: {}", name, versions),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_normal_dep(nodes: &[Node], local_id: &PackageId, dep_id: &PackageId) -> bool {
|
||||
fn depends_on(node: &Node, dep_id: &PackageId) -> bool {
|
||||
node.deps.iter().any(|dep| {
|
||||
dep.pkg == *dep_id
|
||||
&& dep
|
||||
.dep_kinds
|
||||
.iter()
|
||||
.any(|info| matches!(info.kind, DependencyKind::Normal))
|
||||
})
|
||||
}
|
||||
|
||||
nodes
|
||||
.iter()
|
||||
.filter(|node| depends_on(node, dep_id))
|
||||
.any(|node| node.id == *local_id || is_normal_dep(nodes, local_id, &node.id))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty};
|
|||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Detects giving a mutable reference to a function that only
|
||||
/// **What it does:** Detects passing a mutable reference to a function that only
|
||||
/// requires an immutable reference.
|
||||
///
|
||||
/// **Why is this bad?** The immutable reference rules out all other references
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||
}
|
||||
},
|
||||
FnKind::Method(..) => (),
|
||||
_ => return,
|
||||
FnKind::Closure(..) => return,
|
||||
}
|
||||
|
||||
// Exclude non-inherent impls
|
||||
|
|
|
|||
|
|
@ -1,27 +1,20 @@
|
|||
use crate::utils::paths;
|
||||
use crate::utils::sugg::DiagnosticBuilderExt;
|
||||
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then};
|
||||
use crate::utils::{get_trait_def_id, return_ty, same_tys, span_lint_hir_and_then};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::HirIdSet;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
|
||||
/// implementation of
|
||||
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
|
||||
///
|
||||
/// It detects both the case when a manual
|
||||
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
|
||||
/// implementation is required and also when it can be created with
|
||||
/// `#[derive(Default)]`
|
||||
///
|
||||
/// **Why is this bad?** The user might expect to be able to use
|
||||
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
|
||||
/// type can be constructed without arguments.
|
||||
|
|
@ -40,46 +33,17 @@ declare_clippy_lint! {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Instead, use:
|
||||
/// To fix the lint, and a `Default` implementation that delegates to `new`:
|
||||
///
|
||||
/// ```ignore
|
||||
/// struct Foo(Bar);
|
||||
///
|
||||
/// impl Default for Foo {
|
||||
/// fn default() -> Self {
|
||||
/// Foo(Bar::new())
|
||||
/// Foo::new()
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Or, if
|
||||
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
|
||||
/// can be derived by `#[derive(Default)]`:
|
||||
///
|
||||
/// ```rust
|
||||
/// struct Foo;
|
||||
///
|
||||
/// impl Foo {
|
||||
/// fn new() -> Self {
|
||||
/// Foo
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Instead, use:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[derive(Default)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// impl Foo {
|
||||
/// fn new() -> Self {
|
||||
/// Foo
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// You can also have `new()` call `Default::default()`.
|
||||
pub NEW_WITHOUT_DEFAULT,
|
||||
style,
|
||||
"`fn new() -> Self` method without `Default` implementation"
|
||||
|
|
@ -126,8 +90,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||
return;
|
||||
}
|
||||
if sig.decl.inputs.is_empty() && name == sym!(new) && cx.access_levels.is_reachable(id) {
|
||||
let self_did = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id));
|
||||
let self_ty = cx.tcx.type_of(self_did);
|
||||
let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id));
|
||||
let self_ty = cx.tcx.type_of(self_def_id);
|
||||
if_chain! {
|
||||
if same_tys(cx, self_ty, return_ty(cx, id));
|
||||
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
|
||||
|
|
@ -148,56 +112,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||
// generics
|
||||
if_chain! {
|
||||
if let Some(ref impling_types) = self.impling_types;
|
||||
if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def();
|
||||
if let Some(self_def_id) = self_def.did.as_local();
|
||||
if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def();
|
||||
if let Some(self_local_did) = self_def.did.as_local();
|
||||
then {
|
||||
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def_id);
|
||||
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
|
||||
if impling_types.contains(&self_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
NEW_WITHOUT_DEFAULT,
|
||||
id,
|
||||
impl_item.span,
|
||||
&format!(
|
||||
"you should consider deriving a `Default` implementation for `{}`",
|
||||
self_ty
|
||||
),
|
||||
|diag| {
|
||||
diag.suggest_item_with_attr(
|
||||
cx,
|
||||
sp,
|
||||
"try this",
|
||||
"#[derive(Default)]",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
NEW_WITHOUT_DEFAULT,
|
||||
id,
|
||||
impl_item.span,
|
||||
&format!(
|
||||
"you should consider adding a `Default` implementation for `{}`",
|
||||
self_ty
|
||||
),
|
||||
|diag| {
|
||||
diag.suggest_prepend_item(
|
||||
cx,
|
||||
item.span,
|
||||
"try this",
|
||||
&create_new_without_default_suggest_msg(self_ty),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
NEW_WITHOUT_DEFAULT,
|
||||
id,
|
||||
impl_item.span,
|
||||
&format!(
|
||||
"you should consider adding a `Default` implementation for `{}`",
|
||||
self_ty
|
||||
),
|
||||
|diag| {
|
||||
diag.suggest_prepend_item(
|
||||
cx,
|
||||
item.span,
|
||||
"try this",
|
||||
&create_new_without_default_suggest_msg(self_ty),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -217,18 +160,3 @@ fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String {
|
|||
}}
|
||||
}}", ty)
|
||||
}
|
||||
|
||||
fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
|
||||
match ty.kind {
|
||||
ty::Adt(adt_def, substs) if adt_def.is_struct() => {
|
||||
for field in adt_def.all_fields() {
|
||||
let f_ty = field.ty(cx.tcx, substs);
|
||||
if !implements_trait(cx, f_ty, default_trait_id, &[]) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(cx.tcx.def_span(adt_def.did))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use rustc_ast::ast::{
|
|||
use rustc_ast::attr;
|
||||
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::{Ident, SymbolStr};
|
||||
|
|
@ -131,7 +132,11 @@ struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a
|
|||
impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> {
|
||||
fn visit_pat(&mut self, pat: &'tcx Pat) {
|
||||
match pat.kind {
|
||||
PatKind::Ident(_, ident, _) => self.check_ident(ident),
|
||||
PatKind::Ident(_, ident, _) => {
|
||||
if !pat.span.from_expansion() {
|
||||
self.check_ident(ident);
|
||||
}
|
||||
},
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
for field in fields {
|
||||
if !field.is_shorthand {
|
||||
|
|
@ -354,12 +359,20 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
|
|||
|
||||
impl EarlyLintPass for NonExpressiveNames {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if in_external_macro(cx.sess, item.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind {
|
||||
do_check(self, cx, &item.attrs, &sig.decl, blk);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) {
|
||||
if in_external_macro(cx.sess, item.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let AssocItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind {
|
||||
do_check(self, cx, &item.attrs, &sig.decl, blk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::utils::ptr::get_spans;
|
||||
use crate::utils::{
|
||||
is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg,
|
||||
is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg,
|
||||
span_lint_and_then, walk_ptrs_hir_ty,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
|
|
@ -150,8 +150,16 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_
|
|||
let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
|
||||
let sig = cx.tcx.fn_sig(fn_def_id);
|
||||
let fn_ty = sig.skip_binder();
|
||||
let body = opt_body_id.map(|id| cx.tcx.hir().body(id));
|
||||
|
||||
for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
|
||||
// Honor the allow attribute on parameters. See issue 5644.
|
||||
if let Some(body) = &body {
|
||||
if is_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let ty::Ref(_, ty, Mutability::Not) = ty.kind {
|
||||
if is_type_diagnostic_item(cx, ty, sym!(vec_type)) {
|
||||
let mut ty_snippet = None;
|
||||
|
|
|
|||
|
|
@ -241,14 +241,14 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
|||
}
|
||||
|
||||
fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
||||
fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
|
||||
matches!(
|
||||
get_parent_expr(cx, expr),
|
||||
Some(Expr {
|
||||
fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> Option<&'a Expr<'a>> {
|
||||
match get_parent_expr(cx, expr) {
|
||||
parent_expr @ Some(Expr {
|
||||
kind: ExprKind::Index(..),
|
||||
..
|
||||
})
|
||||
)
|
||||
}) => parent_expr,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
|
||||
|
|
@ -267,18 +267,32 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
|||
if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
|
||||
if is_empty_range(limits, ordering);
|
||||
then {
|
||||
if inside_indexing_expr(cx, expr) {
|
||||
if let Some(parent_expr) = inside_indexing_expr(cx, expr) {
|
||||
let (reason, outcome) = if ordering == Ordering::Equal {
|
||||
("empty", "always yield an empty slice")
|
||||
} else {
|
||||
("reversed", "panic at run-time")
|
||||
};
|
||||
|
||||
span_lint(
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
REVERSED_EMPTY_RANGES,
|
||||
expr.span,
|
||||
&format!("this range is {} and using it to index a slice will {}", reason, outcome),
|
||||
|diag| {
|
||||
if_chain! {
|
||||
if ordering == Ordering::Equal;
|
||||
if let ty::Slice(slice_ty) = cx.tables.expr_ty(parent_expr).kind;
|
||||
then {
|
||||
diag.span_suggestion(
|
||||
parent_expr.span,
|
||||
"if you want an empty slice, use",
|
||||
format!("[] as &[{}]", slice_ty),
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
span_lint_and_then(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::utils::span_lint_and_sugg;
|
|||
use rustc_ast::ast::{Expr, ExprKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -36,6 +37,9 @@ declare_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]);
|
|||
|
||||
impl EarlyLintPass for RedundantFieldNames {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
if in_external_macro(cx.sess, expr.span) {
|
||||
return;
|
||||
}
|
||||
if let ExprKind::Struct(_, ref fields, _) = expr.kind {
|
||||
for field in fields {
|
||||
if field.is_shorthand {
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
|
|||
}
|
||||
},
|
||||
FnKind::Method(..) => (),
|
||||
_ => return,
|
||||
FnKind::Closure(..) => return,
|
||||
}
|
||||
|
||||
// Exclude non-inherent impls
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
use crate::utils::{
|
||||
match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_sugg,
|
||||
is_type_diagnostic_item, match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite,
|
||||
span_lint_and_help, span_lint_and_sugg,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `Into`/`From`/`IntoIter` calls that useless converts
|
||||
/// to the same type as caller.
|
||||
/// **What it does:** Checks for `Into`, `TryInto`, `From`, `TryFrom`,`IntoIter` calls
|
||||
/// that useless converts to the same type as caller.
|
||||
///
|
||||
/// **Why is this bad?** Redundant code.
|
||||
///
|
||||
|
|
@ -26,7 +29,7 @@ declare_clippy_lint! {
|
|||
/// ```
|
||||
pub USELESS_CONVERSION,
|
||||
complexity,
|
||||
"calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type"
|
||||
"calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type"
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -36,6 +39,7 @@ pub struct UselessConversion {
|
|||
|
||||
impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]);
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
|
||||
if e.span.from_expansion() {
|
||||
|
|
@ -63,12 +67,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
|
|||
let b = cx.tables.expr_ty(&args[0]);
|
||||
if same_tys(cx, a, b) {
|
||||
let sugg = snippet_with_macro_callsite(cx, args[0].span, "<expr>").to_string();
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
USELESS_CONVERSION,
|
||||
e.span,
|
||||
"useless conversion",
|
||||
"useless conversion to the same type",
|
||||
"consider removing `.into()`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
|
|
@ -84,22 +87,70 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
|
|||
cx,
|
||||
USELESS_CONVERSION,
|
||||
e.span,
|
||||
"useless conversion",
|
||||
"useless conversion to the same type",
|
||||
"consider removing `.into_iter()`",
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
}
|
||||
}
|
||||
if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into" {
|
||||
if_chain! {
|
||||
let a = cx.tables.expr_ty(e);
|
||||
let b = cx.tables.expr_ty(&args[0]);
|
||||
if is_type_diagnostic_item(cx, a, sym!(result_type));
|
||||
if let ty::Adt(_, substs) = a.kind;
|
||||
if let Some(a_type) = substs.types().next();
|
||||
if same_tys(cx, a_type, b);
|
||||
|
||||
then {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
USELESS_CONVERSION,
|
||||
e.span,
|
||||
"useless conversion to the same type",
|
||||
None,
|
||||
"consider removing `.try_into()`",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ExprKind::Call(ref path, ref args) => {
|
||||
if let ExprKind::Path(ref qpath) = path.kind {
|
||||
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id() {
|
||||
if match_def_path(cx, def_id, &paths::FROM_FROM) {
|
||||
let a = cx.tables.expr_ty(e);
|
||||
let b = cx.tables.expr_ty(&args[0]);
|
||||
if same_tys(cx, a, b) {
|
||||
if_chain! {
|
||||
if args.len() == 1;
|
||||
if let ExprKind::Path(ref qpath) = path.kind;
|
||||
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id();
|
||||
let a = cx.tables.expr_ty(e);
|
||||
let b = cx.tables.expr_ty(&args[0]);
|
||||
|
||||
then {
|
||||
if_chain! {
|
||||
if match_def_path(cx, def_id, &paths::TRY_FROM);
|
||||
if is_type_diagnostic_item(cx, a, sym!(result_type));
|
||||
if let ty::Adt(_, substs) = a.kind;
|
||||
if let Some(a_type) = substs.types().next();
|
||||
if same_tys(cx, a_type, b);
|
||||
|
||||
then {
|
||||
let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from"));
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
USELESS_CONVERSION,
|
||||
e.span,
|
||||
"useless conversion to the same type",
|
||||
None,
|
||||
&hint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if match_def_path(cx, def_id, &paths::FROM_FROM);
|
||||
if same_tys(cx, a, b);
|
||||
|
||||
then {
|
||||
let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned();
|
||||
let sugg_msg =
|
||||
format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
|
||||
|
|
@ -107,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
|
|||
cx,
|
||||
USELESS_CONVERSION,
|
||||
e.span,
|
||||
"useless conversion",
|
||||
"useless conversion to the same type",
|
||||
&sugg_msg,
|
||||
sugg,
|
||||
Applicability::MachineApplicable, // snippet
|
||||
|
|
|
|||
|
|
@ -120,10 +120,12 @@ define_Conf! {
|
|||
"GPLv2", "GPLv3",
|
||||
"GitHub", "GitLab",
|
||||
"IPv4", "IPv6",
|
||||
"JavaScript",
|
||||
"ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript",
|
||||
"NaN", "NaNs",
|
||||
"OAuth",
|
||||
"OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap",
|
||||
"OCaml",
|
||||
"OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap",
|
||||
"TensorFlow",
|
||||
"TrueType",
|
||||
"iOS", "macOS",
|
||||
"TeX", "LaTeX", "BibTeX", "BibLaTeX",
|
||||
|
|
|
|||
|
|
@ -289,21 +289,21 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) {
|
|||
println!("{}operands:", ind);
|
||||
for op in asm.operands {
|
||||
match op {
|
||||
hir::InlineAsmOperand::In { expr, .. } => print_expr(cx, expr, indent + 1),
|
||||
hir::InlineAsmOperand::In { expr, .. }
|
||||
| hir::InlineAsmOperand::InOut { expr, .. }
|
||||
| hir::InlineAsmOperand::Const { expr }
|
||||
| hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1),
|
||||
hir::InlineAsmOperand::Out { expr, .. } => {
|
||||
if let Some(expr) = expr {
|
||||
print_expr(cx, expr, indent + 1);
|
||||
}
|
||||
},
|
||||
hir::InlineAsmOperand::InOut { expr, .. } => print_expr(cx, expr, indent + 1),
|
||||
hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
|
||||
print_expr(cx, in_expr, indent + 1);
|
||||
if let Some(out_expr) = out_expr {
|
||||
print_expr(cx, out_expr, indent + 1);
|
||||
}
|
||||
},
|
||||
hir::InlineAsmOperand::Const { expr } => print_expr(cx, expr, indent + 1),
|
||||
hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'_, 'tcx>, hir_id: HirId) -> O
|
|||
pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
match ty.ty_adt_def() {
|
||||
Some(def) => def.has_dtor(cx.tcx),
|
||||
_ => false,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,10 @@ pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"
|
|||
pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];
|
||||
pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
|
||||
pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
|
||||
pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
|
||||
pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"];
|
||||
pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
|
||||
pub const TRY_INTO_TRAIT: [&str; 3] = ["core", "convert", "TryInto"];
|
||||
pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
|
||||
pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
|
||||
pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ pub trait DiagnosticBuilderExt<'a, T: LintContext> {
|
|||
|
||||
/// Suggest to add an item before another.
|
||||
///
|
||||
/// The item should not be indented (expect for inner indentation).
|
||||
/// The item should not be indented (except for inner indentation).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue