mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 07:00:55 +00:00
Merge branch 'master' into clippy_dev_toolchain
This commit is contained in:
commit
a9d002c8a5
57 changed files with 701 additions and 374 deletions
|
@ -47,7 +47,8 @@ rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"}
|
|||
[dev-dependencies]
|
||||
clippy_dev = { version = "0.0.1", path = "clippy_dev" }
|
||||
cargo_metadata = "0.7.1"
|
||||
compiletest_rs = "0.3.19"
|
||||
compiletest_rs = { version = "=0.3.19", features = ["tmp", "stable"] }
|
||||
libtest = "0.0.1"
|
||||
lazy_static = "1.0"
|
||||
serde_derive = "1.0"
|
||||
clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc::ty::{self, TyCtxt};
|
|||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
use semver::Version;
|
||||
use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
|
||||
use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
||||
use syntax::source_map::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -208,22 +208,24 @@ impl LintPass for AttrPass {
|
|||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
|
||||
fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
match &*attr.name().as_str() {
|
||||
"allow" | "warn" | "deny" | "forbid" => {
|
||||
check_clippy_lint_names(cx, items);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
if items.is_empty() || attr.name() != "deprecated" {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if_chain! {
|
||||
if let NestedMetaItemKind::MetaItem(mi) = &item.node;
|
||||
if let MetaItemKind::NameValue(lit) = &mi.node;
|
||||
if mi.name() == "since";
|
||||
then {
|
||||
check_semver(cx, item.span, lit);
|
||||
if let Some(ident) = attr.ident() {
|
||||
match &*ident.as_str() {
|
||||
"allow" | "warn" | "deny" | "forbid" => {
|
||||
check_clippy_lint_names(cx, items);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
if items.is_empty() || !attr.check_name("deprecated") {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if_chain! {
|
||||
if let NestedMetaItem::MetaItem(mi) = &item;
|
||||
if let MetaItemKind::NameValue(lit) = &mi.node;
|
||||
if mi.check_name("since");
|
||||
then {
|
||||
check_semver(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,55 +238,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
|
|||
}
|
||||
match item.node {
|
||||
ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
|
||||
let skip_unused_imports = item.attrs.iter().any(|attr| attr.name() == "macro_use");
|
||||
let skip_unused_imports = item.attrs.iter().any(|attr| attr.check_name("macro_use"));
|
||||
|
||||
for attr in &item.attrs {
|
||||
if let Some(lint_list) = &attr.meta_item_list() {
|
||||
match &*attr.name().as_str() {
|
||||
"allow" | "warn" | "deny" | "forbid" => {
|
||||
// whitelist `unused_imports` and `deprecated` for `use` items
|
||||
// and `unused_imports` for `extern crate` items with `macro_use`
|
||||
for lint in lint_list {
|
||||
match item.node {
|
||||
ItemKind::Use(..) => {
|
||||
if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
|
||||
return;
|
||||
}
|
||||
},
|
||||
ItemKind::ExternCrate(..) => {
|
||||
if is_word(lint, "unused_imports") && skip_unused_imports {
|
||||
return;
|
||||
}
|
||||
if is_word(lint, "unused_extern_crates") {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
let line_span = last_line_of_span(cx, attr.span);
|
||||
|
||||
if let Some(mut sugg) = snippet_opt(cx, line_span) {
|
||||
if sugg.contains("#[") {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
USELESS_ATTRIBUTE,
|
||||
line_span,
|
||||
"useless lint attribute",
|
||||
|db| {
|
||||
sugg = sugg.replacen("#[", "#![", 1);
|
||||
db.span_suggestion(
|
||||
line_span,
|
||||
"if you just forgot a `!`, use",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if let Some(ident) = attr.ident() {
|
||||
match &*ident.as_str() {
|
||||
"allow" | "warn" | "deny" | "forbid" => {
|
||||
// whitelist `unused_imports` and `deprecated` for `use` items
|
||||
// and `unused_imports` for `extern crate` items with `macro_use`
|
||||
for lint in lint_list {
|
||||
match item.node {
|
||||
ItemKind::Use(..) => {
|
||||
if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
|
||||
return;
|
||||
}
|
||||
},
|
||||
);
|
||||
ItemKind::ExternCrate(..) => {
|
||||
if is_word(lint, "unused_imports") && skip_unused_imports {
|
||||
return;
|
||||
}
|
||||
if is_word(lint, "unused_extern_crates") {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
let line_span = last_line_of_span(cx, attr.span);
|
||||
|
||||
if let Some(mut sugg) = snippet_opt(cx, line_span) {
|
||||
if sugg.contains("#[") {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
USELESS_ATTRIBUTE,
|
||||
line_span,
|
||||
"useless lint attribute",
|
||||
|db| {
|
||||
sugg = sugg.replacen("#[", "#![", 1);
|
||||
db.span_suggestion(
|
||||
line_span,
|
||||
"if you just forgot a `!`, use",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,10 +315,11 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
|
|||
let lint_store = cx.lints();
|
||||
for lint in items {
|
||||
if_chain! {
|
||||
if let Some(word) = lint.word();
|
||||
if let Some(tool_name) = word.is_scoped();
|
||||
if let Some(meta_item) = lint.meta_item();
|
||||
if meta_item.path.segments.len() > 1;
|
||||
if let tool_name = meta_item.path.segments[0].ident;
|
||||
if tool_name.as_str() == "clippy";
|
||||
let name = word.name();
|
||||
let name = meta_item.path.segments.last().unwrap().ident.name;
|
||||
if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name(
|
||||
&name.as_str(),
|
||||
Some(tool_name.as_str()),
|
||||
|
@ -323,7 +328,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
|
|||
span_lint_and_then(
|
||||
cx,
|
||||
UNKNOWN_CLIPPY_LINTS,
|
||||
lint.span,
|
||||
lint.span(),
|
||||
&format!("unknown clippy lint: clippy::{}", name),
|
||||
|db| {
|
||||
if name.as_str().chars().any(char::is_uppercase) {
|
||||
|
@ -337,7 +342,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
|
|||
CheckLintNameResult::NoLint(None) => (),
|
||||
_ => {
|
||||
db.span_suggestion(
|
||||
lint.span,
|
||||
lint.span(),
|
||||
"lowercase the lint name",
|
||||
name_lower,
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -352,7 +357,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool {
|
||||
fn is_relevant_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &Item) -> bool {
|
||||
if let ItemKind::Fn(_, _, _, eid) = item.node {
|
||||
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value)
|
||||
} else {
|
||||
|
@ -360,14 +365,14 @@ fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_relevant_impl(tcx: TyCtxt<'_, '_, '_>, item: &ImplItem) -> bool {
|
||||
fn is_relevant_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &ImplItem) -> bool {
|
||||
match item.node {
|
||||
ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir().body(eid).value),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
|
||||
fn is_relevant_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &TraitItem) -> bool {
|
||||
match item.node {
|
||||
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
|
||||
TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
|
||||
|
@ -377,7 +382,7 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
|
||||
fn is_relevant_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
|
||||
if let Some(stmt) = block.stmts.first() {
|
||||
match &stmt.node {
|
||||
StmtKind::Local(_) => true,
|
||||
|
@ -389,7 +394,7 @@ fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, blo
|
|||
}
|
||||
}
|
||||
|
||||
fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool {
|
||||
fn is_relevant_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool {
|
||||
match &expr.node {
|
||||
ExprKind::Block(block, _) => is_relevant_block(tcx, tables, block),
|
||||
ExprKind::Ret(Some(e)) => is_relevant_expr(tcx, tables, e),
|
||||
|
@ -443,7 +448,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib
|
|||
}
|
||||
|
||||
if let Some(values) = attr.meta_item_list() {
|
||||
if values.len() != 1 || attr.name() != "inline" {
|
||||
if values.len() != 1 || !attr.check_name("inline") {
|
||||
continue;
|
||||
}
|
||||
if is_word(&values[0], "always") {
|
||||
|
@ -476,8 +481,8 @@ fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) {
|
|||
}
|
||||
|
||||
fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool {
|
||||
if let NestedMetaItemKind::MetaItem(mi) = &nmi.node {
|
||||
mi.is_word() && mi.name() == expected
|
||||
if let NestedMetaItem::MetaItem(mi) = &nmi {
|
||||
mi.is_word() && mi.check_name(expected)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -514,15 +519,16 @@ impl EarlyLintPass for CfgAttrPass {
|
|||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if_chain! {
|
||||
// check cfg_attr
|
||||
if attr.name() == "cfg_attr";
|
||||
if attr.check_name("cfg_attr");
|
||||
if let Some(items) = attr.meta_item_list();
|
||||
if items.len() == 2;
|
||||
// check for `rustfmt`
|
||||
if let Some(feature_item) = items[0].meta_item();
|
||||
if feature_item.name() == "rustfmt";
|
||||
if feature_item.check_name("rustfmt");
|
||||
// check for `rustfmt_skip` and `rustfmt::skip`
|
||||
if let Some(skip_item) = &items[1].meta_item();
|
||||
if skip_item.name() == "rustfmt_skip" || skip_item.name() == "skip";
|
||||
if skip_item.check_name("rustfmt_skip") ||
|
||||
skip_item.path.segments.last().expect("empty path in attribute").ident.name == "skip";
|
||||
// Only lint outer attributes, because custom inner attributes are unstable
|
||||
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
|
||||
if let AttrStyle::Outer = attr.style;
|
||||
|
|
|
@ -117,7 +117,7 @@ impl Hash for Constant {
|
|||
}
|
||||
|
||||
impl Constant {
|
||||
pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: ty::Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
|
||||
pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
|
||||
match (left, right) {
|
||||
(&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)),
|
||||
(&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)),
|
||||
|
@ -268,7 +268,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
|||
}
|
||||
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
fn constant_not(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
|
||||
fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
|
||||
use self::Constant::*;
|
||||
match *o {
|
||||
Bool(b) => Some(Bool(!b)),
|
||||
|
@ -284,7 +284,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
|||
}
|
||||
}
|
||||
|
||||
fn constant_negate(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
|
||||
fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
|
||||
use self::Constant::*;
|
||||
match *o {
|
||||
Int(value) => {
|
||||
|
|
|
@ -152,7 +152,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>,
|
|||
spans.extend_from_slice(¤t_spans);
|
||||
doc.push_str(¤t);
|
||||
}
|
||||
} else if attr.name() == "doc" {
|
||||
} else if attr.check_name("doc") {
|
||||
// ignore mix of sugared and non-sugared doc
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,10 @@ impl LintPass for EnumGlobUse {
|
|||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse {
|
||||
fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: HirId) {
|
||||
let map = cx.tcx.hir();
|
||||
// only check top level `use` statements
|
||||
for item in &m.item_ids {
|
||||
self.lint_item(cx, cx.tcx.hir().expect_item(item.id));
|
||||
self.lint_item(cx, map.expect_item(map.hir_to_node_id(item.id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use if_chain::if_chain;
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
|
||||
|
@ -129,27 +129,27 @@ fn get_ufcs_type_name(
|
|||
method_def_id: def_id::DefId,
|
||||
self_arg: &Expr,
|
||||
) -> std::option::Option<String> {
|
||||
let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0].sty;
|
||||
let actual_type_of_self = &cx.tables.node_type(self_arg.hir_id).sty;
|
||||
let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0];
|
||||
let actual_type_of_self = &cx.tables.node_type(self_arg.hir_id);
|
||||
|
||||
if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) {
|
||||
if match_borrow_depth(expected_type_of_self, actual_type_of_self) {
|
||||
return Some(cx.tcx.item_path_str(trait_id));
|
||||
if match_borrow_depth(expected_type_of_self, &actual_type_of_self) {
|
||||
return Some(cx.tcx.def_path_str(trait_id));
|
||||
}
|
||||
}
|
||||
|
||||
cx.tcx.impl_of_method(method_def_id).and_then(|_| {
|
||||
//a type may implicitly implement other type's methods (e.g. Deref)
|
||||
if match_types(expected_type_of_self, actual_type_of_self) {
|
||||
if match_types(expected_type_of_self, &actual_type_of_self) {
|
||||
return Some(get_type_name(cx, &actual_type_of_self));
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
fn match_borrow_depth(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(ty::Ref(_, t1, _), ty::Ref(_, t2, _)) => match_borrow_depth(&t1.sty, &t2.sty),
|
||||
fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
|
||||
match (&lhs.sty, &rhs.sty) {
|
||||
(ty::Ref(_, t1, _), ty::Ref(_, t2, _)) => match_borrow_depth(&t1, &t2),
|
||||
(l, r) => match (l, r) {
|
||||
(ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _)) => false,
|
||||
(_, _) => true,
|
||||
|
@ -157,8 +157,8 @@ fn match_borrow_depth(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn match_types(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
|
||||
match (lhs, rhs) {
|
||||
fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
|
||||
match (&lhs.sty, &rhs.sty) {
|
||||
(ty::Bool, ty::Bool)
|
||||
| (ty::Char, ty::Char)
|
||||
| (ty::Int(_), ty::Int(_))
|
||||
|
@ -166,17 +166,17 @@ fn match_types(lhs: &ty::TyKind<'_>, rhs: &ty::TyKind<'_>) -> bool {
|
|||
| (ty::Str, ty::Str) => true,
|
||||
(ty::Ref(_, t1, _), ty::Ref(_, t2, _))
|
||||
| (ty::Array(t1, _), ty::Array(t2, _))
|
||||
| (ty::Slice(t1), ty::Slice(t2)) => match_types(&t1.sty, &t2.sty),
|
||||
| (ty::Slice(t1), ty::Slice(t2)) => match_types(t1, t2),
|
||||
(ty::Adt(def1, _), ty::Adt(def2, _)) => def1 == def2,
|
||||
(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_name(cx: &LateContext<'_, '_>, kind: &ty::TyKind<'_>) -> String {
|
||||
match kind {
|
||||
ty::Adt(t, _) => cx.tcx.item_path_str(t.did),
|
||||
ty::Ref(_, r, _) => get_type_name(cx, &r.sty),
|
||||
_ => kind.to_string(),
|
||||
fn get_type_name(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> String {
|
||||
match ty.sty {
|
||||
ty::Adt(t, _) => cx.tcx.def_path_str(t.did),
|
||||
ty::Ref(_, r, _) => get_type_name(cx, &r),
|
||||
_ => ty.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_
|
|||
use if_chain::if_chain;
|
||||
use rustc::hir;
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
@ -132,7 +132,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
|
|||
}
|
||||
}
|
||||
|
||||
fn match_type(tcx: ty::TyCtxt<'_, '_, '_>, ty: ty::Ty<'_>, path: &[&str]) -> bool {
|
||||
fn match_type<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'_>, path: &[&str]) -> bool {
|
||||
match ty.sty {
|
||||
ty::Adt(adt, _) => match_def_path(tcx, adt.did, path),
|
||||
_ => false,
|
||||
|
|
|
@ -256,8 +256,7 @@ impl<'a, 'tcx> Functions {
|
|||
hir_id: hir::HirId,
|
||||
) {
|
||||
let expr = &body.value;
|
||||
let node_id = cx.tcx.hir().hir_to_node_id(hir_id);
|
||||
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(node_id) {
|
||||
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
|
||||
let raw_ptrs = iter_input_pats(decl, body)
|
||||
.zip(decl.inputs.iter())
|
||||
.filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
|
||||
|
|
|
@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
|
||||
fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if attr.name() != "inline" {
|
||||
if !attr.check_name("inline") {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,9 +148,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items
|
|||
}
|
||||
}
|
||||
|
||||
let trait_node_id = cx.tcx.hir().hir_to_node_id(visited_trait.hir_id);
|
||||
|
||||
if cx.access_levels.is_exported(trait_node_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
|
||||
if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
|
||||
let mut current_and_super_traits = FxHashSet::default();
|
||||
let visited_trait_def_id = cx.tcx.hir().local_def_id_from_hir_id(visited_trait.hir_id);
|
||||
fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);
|
||||
|
@ -193,10 +191,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte
|
|||
}
|
||||
|
||||
let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
|
||||
if cx
|
||||
.access_levels
|
||||
.is_exported(cx.tcx.hir().hir_to_node_id(is_empty.id.hir_id))
|
||||
{
|
||||
if cx.access_levels.is_exported(is_empty.id.hir_id) {
|
||||
return;
|
||||
} else {
|
||||
"a private"
|
||||
|
@ -206,7 +201,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte
|
|||
};
|
||||
|
||||
if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
|
||||
if cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(i.id.hir_id)) {
|
||||
if cx.access_levels.is_exported(i.id.hir_id) {
|
||||
let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
|
||||
let ty = cx.tcx.type_of(def_id);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// error-pattern:cargo-clippy
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(range_contains)]
|
||||
#![allow(clippy::missing_docs_in_private_items)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
|
||||
|
|
|
@ -356,7 +356,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
|||
self.collect_anonymous_lifetimes(path, ty);
|
||||
},
|
||||
TyKind::Def(item, _) => {
|
||||
if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir().expect_item(item.id).node {
|
||||
let map = self.cx.tcx.hir();
|
||||
if let ItemKind::Existential(ref exist_ty) = map.expect_item(map.hir_to_node_id(item.id)).node {
|
||||
for bound in &exist_ty.bounds {
|
||||
if let GenericBound::Outlives(_) = *bound {
|
||||
self.record(&None);
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, sni
|
|||
use if_chain::if_chain;
|
||||
use rustc::hir;
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
use syntax::source_map::Span;
|
||||
|
@ -87,7 +87,7 @@ impl LintPass for Pass {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_unit_type(ty: ty::Ty<'_>) -> bool {
|
||||
fn is_unit_type(ty: Ty<'_>) -> bool {
|
||||
match ty.sty {
|
||||
ty::Tuple(slice) => slice.is_empty(),
|
||||
ty::Never => true,
|
||||
|
|
|
@ -516,11 +516,11 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
|
|||
for pat in &arm.pats {
|
||||
if let PatKind::Path(ref path) = pat.deref().node {
|
||||
if let QPath::Resolved(_, p) = path {
|
||||
missing_variants.retain(|e| e.did != p.def.def_id());
|
||||
missing_variants.retain(|e| e.ctor_def_id != Some(p.def.def_id()));
|
||||
}
|
||||
} else if let PatKind::TupleStruct(ref path, ..) = pat.deref().node {
|
||||
if let QPath::Resolved(_, p) = path {
|
||||
missing_variants.retain(|e| e.did != p.def.def_id());
|
||||
missing_variants.retain(|e| e.ctor_def_id != Some(p.def.def_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
|
|||
String::new()
|
||||
};
|
||||
// This path assumes that the enum type is imported into scope.
|
||||
format!("{}{}{}", ident_str, cx.tcx.item_path_str(v.did), suffix)
|
||||
format!("{}{}{}", ident_str, cx.tcx.def_path_str(v.def_id), suffix)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -918,8 +918,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next();
|
||||
if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node;
|
||||
then {
|
||||
let node_id = cx.tcx.hir().hir_to_node_id(implitem.hir_id);
|
||||
if cx.access_levels.is_exported(node_id) {
|
||||
if cx.access_levels.is_exported(implitem.hir_id) {
|
||||
// check missing trait implementations
|
||||
for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
|
||||
if name == method_name &&
|
||||
|
@ -2196,7 +2195,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re
|
|||
|
||||
fn ty_has_iter_method(
|
||||
cx: &LateContext<'_, '_>,
|
||||
self_ref_ty: ty::Ty<'_>,
|
||||
self_ref_ty: Ty<'_>,
|
||||
) -> Option<(&'static Lint, &'static str, &'static str)> {
|
||||
if let Some(ty_name) = has_iter_method(cx, self_ref_ty) {
|
||||
let lint = match ty_name {
|
||||
|
@ -2217,7 +2216,7 @@ fn ty_has_iter_method(
|
|||
}
|
||||
}
|
||||
|
||||
fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: ty::Ty<'_>, method_span: Span) {
|
||||
fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: Ty<'_>, method_span: Span) {
|
||||
if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
//
|
||||
|
||||
use crate::utils::{in_macro, span_lint};
|
||||
use if_chain::if_chain;
|
||||
use rustc::hir;
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::ty;
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use syntax::ast;
|
||||
use syntax::ast::{self, MetaItem, MetaItemKind};
|
||||
use syntax::attr;
|
||||
use syntax::source_map::Span;
|
||||
|
||||
|
@ -52,6 +53,20 @@ impl MissingDoc {
|
|||
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
|
||||
}
|
||||
|
||||
fn has_include(meta: Option<MetaItem>) -> bool {
|
||||
if_chain! {
|
||||
if let Some(meta) = meta;
|
||||
if let MetaItemKind::List(list) = meta.node;
|
||||
if let Some(meta) = list.get(0);
|
||||
if let Some(name) = meta.ident();
|
||||
then {
|
||||
name.as_str() == "include"
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_missing_docs_attrs(
|
||||
&self,
|
||||
cx: &LateContext<'_, '_>,
|
||||
|
@ -74,7 +89,9 @@ impl MissingDoc {
|
|||
return;
|
||||
}
|
||||
|
||||
let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
|
||||
let has_doc = attrs
|
||||
.iter()
|
||||
.any(|a| a.check_name("doc") && (a.is_value_str() || Self::has_include(a.meta())));
|
||||
if !has_doc {
|
||||
span_lint(
|
||||
cx,
|
||||
|
|
|
@ -59,7 +59,7 @@ declare_clippy_lint! {
|
|||
pub struct MissingInline;
|
||||
|
||||
fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
|
||||
let has_inline = attrs.iter().any(|a| a.name() == "inline");
|
||||
let has_inline = attrs.iter().any(|a| a.check_name("inline"));
|
||||
if !has_inline {
|
||||
span_lint(
|
||||
cx,
|
||||
|
@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
|
|||
return;
|
||||
}
|
||||
|
||||
if !cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(it.hir_id)) {
|
||||
if !cx.access_levels.is_exported(it.hir_id) {
|
||||
return;
|
||||
}
|
||||
match it.node {
|
||||
|
@ -146,8 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
|
|||
}
|
||||
|
||||
// If the item being implemented is not exported, then we don't need #[inline]
|
||||
let node_id = cx.tcx.hir().hir_to_node_id(impl_item.hir_id);
|
||||
if !cx.access_levels.is_exported(node_id) {
|
||||
if !cx.access_levels.is_exported(impl_item.hir_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -163,12 +162,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
|
|||
};
|
||||
|
||||
if let Some(trait_def_id) = trait_def_id {
|
||||
if let Some(n) = cx.tcx.hir().as_local_node_id(trait_def_id) {
|
||||
if !cx.access_levels.is_exported(n) {
|
||||
// If a trait is being implemented for an item, and the
|
||||
// trait is not exported, we don't need #[inline]
|
||||
return;
|
||||
}
|
||||
if cx.tcx.hir().as_local_node_id(trait_def_id).is_some() && !cx.access_levels.is_exported(impl_item.hir_id)
|
||||
{
|
||||
// If a trait is being implemented for an item, and the
|
||||
// trait is not exported, we don't need #[inline]
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -324,7 +324,7 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool {
|
|||
attrs.iter().any(|attr| {
|
||||
["proc_macro", "proc_macro_attribute", "proc_macro_derive"]
|
||||
.iter()
|
||||
.any(|&allow| attr.name() == allow)
|
||||
.any(|&allow| attr.check_name(allow))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
let name = impl_item.ident.name;
|
||||
let id = impl_item.hir_id;
|
||||
let node_id = cx.tcx.hir().hir_to_node_id(id);
|
||||
if sig.header.constness == hir::Constness::Const {
|
||||
// can't be implemented by default
|
||||
return;
|
||||
|
@ -129,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
|||
// impl of `Default`
|
||||
return;
|
||||
}
|
||||
if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(node_id) {
|
||||
if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
|
||||
let self_did = cx.tcx.hir().local_def_id_from_hir_id(cx.tcx.hir().get_parent_item(id));
|
||||
let self_ty = cx.tcx.type_of(self_did);
|
||||
if_chain! {
|
||||
|
|
|
@ -72,7 +72,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
|
|||
if let ExprKind::Path(ref qpath) = callee.node {
|
||||
let def = cx.tables.qpath_def(qpath, callee.hir_id);
|
||||
match def {
|
||||
Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => {
|
||||
Def::Struct(..) | Def::Variant(..) | Def::Ctor(..) => {
|
||||
!has_drop(cx, cx.tables.expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg))
|
||||
},
|
||||
_ => false,
|
||||
|
@ -166,9 +166,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<Vec
|
|||
if let ExprKind::Path(ref qpath) = callee.node {
|
||||
let def = cx.tables.qpath_def(qpath, callee.hir_id);
|
||||
match def {
|
||||
Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..)
|
||||
if !has_drop(cx, cx.tables.expr_ty(expr)) =>
|
||||
{
|
||||
Def::Struct(..) | Def::Variant(..) | Def::Ctor(..) if !has_drop(cx, cx.tables.expr_ty(expr)) => {
|
||||
Some(args.iter().collect())
|
||||
},
|
||||
_ => None,
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc::hir::def::Def;
|
|||
use rustc::hir::*;
|
||||
use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
|
||||
use rustc::ty::adjustment::Adjust;
|
||||
use rustc::ty::{self, TypeFlags};
|
||||
use rustc::ty::{Ty, TypeFlags};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
|
@ -108,7 +108,7 @@ impl Source {
|
|||
}
|
||||
}
|
||||
|
||||
fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, source: Source) {
|
||||
fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: Source) {
|
||||
if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) {
|
||||
// An `UnsafeCell` is `!Copy`, and an `UnsafeCell` is also the only type which
|
||||
// is `!Freeze`, thus if our type is `Copy` we can be sure it must be `Freeze`
|
||||
|
|
|
@ -128,7 +128,7 @@ impl Pass {
|
|||
},
|
||||
ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
|
||||
ExprKind::Path(ref qp) => {
|
||||
if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) {
|
||||
if let Def::Ctor(def_id, def::CtorOf::Variant, _) = cx.tables.qpath_def(qp, expression.hir_id) {
|
||||
return match_def_path(cx.tcx, def_id, &OPTION_NONE);
|
||||
}
|
||||
|
||||
|
|
|
@ -157,25 +157,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
}) = higher::range(cx, expr);
|
||||
if let Some(y) = y_plus_one(end);
|
||||
then {
|
||||
let span = expr.span
|
||||
.ctxt()
|
||||
.outer()
|
||||
.expn_info()
|
||||
.map_or(expr.span, |info| info.call_site);
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
RANGE_PLUS_ONE,
|
||||
expr.span,
|
||||
span,
|
||||
"an inclusive range would be more readable",
|
||||
|db| {
|
||||
let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string());
|
||||
let end = Sugg::hir(cx, y, "y");
|
||||
if let Some(is_wrapped) = &snippet_opt(cx, expr.span) {
|
||||
if let Some(is_wrapped) = &snippet_opt(cx, span) {
|
||||
if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
|
||||
db.span_suggestion(
|
||||
expr.span,
|
||||
span,
|
||||
"use",
|
||||
format!("({}..={})", start, end),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
db.span_suggestion(
|
||||
expr.span,
|
||||
span,
|
||||
"use",
|
||||
format!("{}..={}", start, end),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
|
|
|
@ -12,7 +12,7 @@ use rustc::mir::{
|
|||
visit::{MutatingUseContext, PlaceContext, Visitor},
|
||||
TerminatorKind,
|
||||
};
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
use std::convert::TryFrom;
|
||||
|
@ -225,7 +225,7 @@ fn is_call_with_ref_arg<'tcx>(
|
|||
cx: &LateContext<'_, 'tcx>,
|
||||
mir: &'tcx mir::Mir<'tcx>,
|
||||
kind: &'tcx mir::TerminatorKind<'tcx>,
|
||||
) -> Option<(def_id::DefId, mir::Local, ty::Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> {
|
||||
) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> {
|
||||
if_chain! {
|
||||
if let TerminatorKind::Call { func, args, destination, .. } = kind;
|
||||
if args.len() == 1;
|
||||
|
@ -299,7 +299,7 @@ fn base_local_and_movability<'tcx>(
|
|||
place = &proj.base;
|
||||
deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref);
|
||||
if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) {
|
||||
field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).to_ty(cx.tcx));
|
||||
field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty);
|
||||
}
|
||||
},
|
||||
_ => return None,
|
||||
|
|
|
@ -263,7 +263,7 @@ impl EarlyLintPass for ReturnPass {
|
|||
}
|
||||
|
||||
fn attr_is_cfg(attr: &ast::Attribute) -> bool {
|
||||
attr.meta_item_list().is_some() && attr.name() == "cfg"
|
||||
attr.meta_item_list().is_some() && attr.check_name("cfg")
|
||||
}
|
||||
|
||||
// get the def site
|
||||
|
|
|
@ -347,7 +347,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||
|db| {
|
||||
let arg = sugg::Sugg::hir(cx, &args[0], "..");
|
||||
let arg = if let ty::Int(_) = from_ty.sty {
|
||||
arg.as_ty(ty::Uint(ast::UintTy::U32))
|
||||
arg.as_ty(ast::UintTy::U32)
|
||||
} else {
|
||||
arg
|
||||
};
|
||||
|
|
|
@ -176,7 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
|
|||
return;
|
||||
}
|
||||
for a in attrs {
|
||||
if a.meta_item_list().is_some() && a.name() == "proc_macro_derive" {
|
||||
if a.meta_item_list().is_some() && a.check_name("proc_macro_derive") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito
|
|||
use rustc::hir::*;
|
||||
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc::ty::print::Printer;
|
||||
use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -24,7 +25,7 @@ use crate::utils::paths;
|
|||
use crate::utils::{
|
||||
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
|
||||
match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
|
||||
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathBuffer,
|
||||
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, AbsolutePathPrinter,
|
||||
};
|
||||
|
||||
/// Handles all the linting of funky types
|
||||
|
@ -1135,15 +1136,14 @@ impl LintPass for CastPass {
|
|||
|
||||
// Check if the given type is either `core::ffi::c_void` or
|
||||
// one of the platform specific `libc::<platform>::c_void` of libc.
|
||||
fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool {
|
||||
fn is_c_void<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'_>) -> bool {
|
||||
if let ty::Adt(adt, _) = ty.sty {
|
||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||
tcx.push_item_path(&mut apb, adt.did, false);
|
||||
let names = AbsolutePathPrinter { tcx }.print_def_path(adt.did, &[]).unwrap();
|
||||
|
||||
if apb.names.is_empty() {
|
||||
if names.is_empty() {
|
||||
return false;
|
||||
}
|
||||
if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" {
|
||||
if names[0] == "libc" || names[0] == "core" && *names.last().unwrap() == "c_void" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1533,7 +1533,7 @@ impl LintPass for CharLitAsU8 {
|
|||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
use syntax::ast::{LitKind, UintTy};
|
||||
use syntax::ast::LitKind;
|
||||
|
||||
if let ExprKind::Cast(ref e, _) = expr.node {
|
||||
if let ExprKind::Lit(ref l) = e.node {
|
||||
|
@ -1818,7 +1818,6 @@ impl Ord for FullInt {
|
|||
|
||||
fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> {
|
||||
use std::*;
|
||||
use syntax::ast::{IntTy, UintTy};
|
||||
|
||||
if let ExprKind::Cast(ref cast_exp, _) = expr.node {
|
||||
let pre_cast_ty = cx.tables.expr_ty(cast_exp);
|
||||
|
@ -2075,7 +2074,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher {
|
|||
}
|
||||
}
|
||||
|
||||
if !cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(item.hir_id)) {
|
||||
if !cx.access_levels.is_exported(item.hir_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Vi
|
|||
use rustc::hir::*;
|
||||
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::ty;
|
||||
use rustc::ty::DefIdTree;
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
use syntax_pos::symbol::keywords::SelfUpper;
|
||||
|
@ -232,8 +233,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
|
|||
if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() {
|
||||
if self.item_path.def == path.def {
|
||||
span_use_self_lint(self.cx, path);
|
||||
} else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def {
|
||||
if self.item_path.def.opt_def_id() == self.cx.tcx.parent_def_id(ctor_did) {
|
||||
} else if let Def::Ctor(ctor_did, def::CtorOf::Struct, CtorKind::Fn) = path.def {
|
||||
if self.item_path.def.opt_def_id() == self.cx.tcx.parent(ctor_did) {
|
||||
span_use_self_lint(self.cx, path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,9 @@ use syntax::{ast, source_map};
|
|||
use toml;
|
||||
|
||||
/// Gets the configuration file from arguments.
|
||||
pub fn file_from_args(
|
||||
args: &[source_map::Spanned<ast::NestedMetaItemKind>],
|
||||
) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> {
|
||||
for arg in args.iter().filter_map(syntax::source_map::Spanned::meta_item) {
|
||||
if arg.name() == "conf_file" {
|
||||
pub fn file_from_args(args: &[ast::NestedMetaItem]) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> {
|
||||
for arg in args.iter().filter_map(syntax::ast::NestedMetaItem::meta_item) {
|
||||
if arg.check_name("conf_file") {
|
||||
return match arg.node {
|
||||
ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => {
|
||||
Err(("`conf_file` must be a named value", arg.span))
|
||||
|
|
|
@ -24,8 +24,10 @@ use if_chain::if_chain;
|
|||
use matches::matches;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
|
||||
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::{LateContext, Level, Lint, LintContext};
|
||||
|
@ -41,8 +43,7 @@ use rustc_errors::Applicability;
|
|||
use syntax::ast::{self, LitKind};
|
||||
use syntax::attr;
|
||||
use syntax::source_map::{Span, DUMMY_SP};
|
||||
use syntax::symbol;
|
||||
use syntax::symbol::{keywords, Symbol};
|
||||
use syntax::symbol::{keywords, LocalInternedString, Symbol};
|
||||
|
||||
use crate::reexport::*;
|
||||
|
||||
|
@ -97,19 +98,102 @@ pub fn in_macro(span: Span) -> bool {
|
|||
/// Used to store the absolute path to a type.
|
||||
///
|
||||
/// See `match_def_path` for usage.
|
||||
#[derive(Debug)]
|
||||
pub struct AbsolutePathBuffer {
|
||||
pub names: Vec<symbol::LocalInternedString>,
|
||||
pub struct AbsolutePathPrinter<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
|
||||
fn root_mode(&self) -> &ty::item_path::RootMode {
|
||||
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
|
||||
ABSOLUTE
|
||||
use rustc::ty::print::Printer;
|
||||
|
||||
#[allow(clippy::diverging_sub_expression)]
|
||||
impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
|
||||
type Error = !;
|
||||
|
||||
type Path = Vec<LocalInternedString>;
|
||||
type Region = ();
|
||||
type Type = ();
|
||||
type DynExistential = ();
|
||||
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn push(&mut self, text: &str) {
|
||||
self.names.push(symbol::Symbol::intern(text).as_str());
|
||||
fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_dyn_existential(
|
||||
self,
|
||||
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
|
||||
Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
if trait_ref.is_none() {
|
||||
if let ty::Adt(def, substs) = self_ty.sty {
|
||||
return self.print_def_path(def.did, substs);
|
||||
}
|
||||
}
|
||||
|
||||
// This shouldn't ever be needed, but just in case:
|
||||
Ok(vec![match trait_ref {
|
||||
Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(),
|
||||
None => Symbol::intern(&format!("<{}>", self_ty)).as_str(),
|
||||
}])
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
_disambiguated_data: &DisambiguatedDefPathData,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
let mut path = print_prefix(self)?;
|
||||
|
||||
// This shouldn't ever be needed, but just in case:
|
||||
path.push(match trait_ref {
|
||||
Some(trait_ref) => Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str(),
|
||||
None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
|
||||
});
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
let mut path = print_prefix(self)?;
|
||||
|
||||
// Skip `::{{constructor}}` on tuple/unit structs.
|
||||
if let DefPathData::Ctor = disambiguated_data.data {
|
||||
return Ok(path);
|
||||
}
|
||||
|
||||
path.push(disambiguated_data.data.as_interned_str().as_str());
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
_args: &[Kind<'tcx>],
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
print_prefix(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,12 +205,10 @@ impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
|
|||
/// ```
|
||||
///
|
||||
/// See also the `paths` module.
|
||||
pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool {
|
||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||
pub fn match_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, path: &[&str]) -> bool {
|
||||
let names = get_def_path(tcx, def_id);
|
||||
|
||||
tcx.push_item_path(&mut apb, def_id, false);
|
||||
|
||||
apb.names.len() == path.len() && apb.names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
|
||||
names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
|
||||
}
|
||||
|
||||
/// Gets the absolute path of `def_id` as a vector of `&str`.
|
||||
|
@ -138,12 +220,12 @@ pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) ->
|
|||
/// // The given `def_id` is that of an `Option` type
|
||||
/// };
|
||||
/// ```
|
||||
pub fn get_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Vec<&'static str> {
|
||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||
tcx.push_item_path(&mut apb, def_id, false);
|
||||
apb.names
|
||||
pub fn get_def_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Vec<&'static str> {
|
||||
AbsolutePathPrinter { tcx }
|
||||
.print_def_path(def_id, &[])
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(syntax_pos::symbol::LocalInternedString::get)
|
||||
.map(LocalInternedString::get)
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -787,7 +869,7 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool {
|
|||
fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool {
|
||||
matches!(
|
||||
cx.tables.qpath_def(qpath, id),
|
||||
def::Def::Variant(..) | def::Def::VariantCtor(..)
|
||||
def::Def::Variant(..) | def::Def::Ctor(_, def::CtorOf::Variant, _)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1010,7 +1092,7 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_, '_, '_>, node: HirId)
|
|||
}
|
||||
|
||||
/// Returns true if ty has `iter` or `iter_mut` methods
|
||||
pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: ty::Ty<'_>) -> Option<&'static str> {
|
||||
pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Option<&'static str> {
|
||||
// FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
|
||||
// exists and has the desired signature. Unfortunately FnCtxt is not exported
|
||||
// so we can't use its `lookup_method` method.
|
||||
|
|
|
@ -59,6 +59,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
then {
|
||||
// report the error around the `vec!` not inside `<std macros>:`
|
||||
let span = arg.span
|
||||
.ctxt()
|
||||
.outer()
|
||||
.expn_info()
|
||||
.map(|info| info.call_site)
|
||||
.expect("unable to get call_site")
|
||||
.ctxt()
|
||||
.outer()
|
||||
.expn_info()
|
||||
|
|
|
@ -115,7 +115,7 @@ where all the lint code is. We are going to call the file
|
|||
`clippy_lints/src/foo_functions.rs` and import some initial things we need:
|
||||
|
||||
```rust
|
||||
use rustc::lint::{LintArray, LintPass};
|
||||
use rustc::lint::{LintArray, LintPass, EarlyLintPass};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
```
|
||||
|
||||
|
@ -161,6 +161,8 @@ impl LintPass for FooFunctionsPass {
|
|||
"FooFunctions"
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for FooFunctionsPass {}
|
||||
```
|
||||
|
||||
Don't worry about the `name` method here. As long as it includes the name of the
|
||||
|
|
|
@ -93,7 +93,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
|
|||
ls.register_early_pass(Some(sess), true, false, pass);
|
||||
}
|
||||
for pass in late_lint_passes {
|
||||
ls.register_late_pass(Some(sess), true, pass);
|
||||
ls.register_late_pass(Some(sess), true, false, false, pass);
|
||||
}
|
||||
|
||||
for (name, (to, deprecated_name)) in lint_groups {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![feature(test)]
|
||||
|
||||
use compiletest_rs as compiletest;
|
||||
extern crate test;
|
||||
use libtest::TestDescAndFn;
|
||||
|
||||
use std::env::{set_var, var};
|
||||
use std::ffi::OsStr;
|
||||
|
@ -74,15 +74,12 @@ fn run_mode(mode: &str, dir: PathBuf) {
|
|||
compiletest::run_tests(&cfg);
|
||||
}
|
||||
|
||||
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
|
||||
#[warn(clippy::identity_conversion)]
|
||||
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<TestDescAndFn>) -> Result<bool, io::Error> {
|
||||
let mut result = true;
|
||||
let opts = compiletest::test_opts(config);
|
||||
for dir in fs::read_dir(&config.src_base)? {
|
||||
let dir = dir?;
|
||||
if !dir.file_type()?.is_dir() {
|
||||
continue;
|
||||
}
|
||||
let dir_path = dir.path();
|
||||
let dir_path = dir.unwrap().path();
|
||||
set_var("CARGO_MANIFEST_DIR", &dir_path);
|
||||
for file in fs::read_dir(&dir_path)? {
|
||||
let file = file?;
|
||||
|
@ -101,9 +98,25 @@ fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDesc
|
|||
let test_name = compiletest::make_test_name(&config, &paths);
|
||||
let index = tests
|
||||
.iter()
|
||||
.position(|test| test.desc.name == test_name)
|
||||
.position(|test| test.desc.name.to_string() == test_name.to_string())
|
||||
.expect("The test should be in there");
|
||||
result &= test::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
|
||||
let opts = libtest::TestOpts {
|
||||
list: opts.list,
|
||||
filter: opts.filter.clone(),
|
||||
filter_exact: opts.filter_exact,
|
||||
exclude_should_panic: Default::default(),
|
||||
run_ignored: libtest::RunIgnored::No,
|
||||
run_tests: opts.run_tests,
|
||||
bench_benchmarks: opts.bench_benchmarks,
|
||||
logfile: opts.logfile.clone(),
|
||||
nocapture: opts.nocapture,
|
||||
color: libtest::ColorConfig::AutoColor,
|
||||
format: libtest::OutputFormat::Pretty,
|
||||
test_threads: opts.test_threads,
|
||||
skip: opts.skip.clone(),
|
||||
options: libtest::Options::new(),
|
||||
};
|
||||
result &= libtest::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
|
@ -114,6 +127,22 @@ fn run_ui_toml() {
|
|||
let config = config("ui", path);
|
||||
let tests = compiletest::make_tests(&config);
|
||||
|
||||
let tests = tests
|
||||
.into_iter()
|
||||
.map(|test| {
|
||||
libtest::TestDescAndFn {
|
||||
desc: libtest::TestDesc {
|
||||
name: libtest::TestName::DynTestName(test.desc.name.to_string()),
|
||||
ignore: test.desc.ignore,
|
||||
allow_fail: test.desc.allow_fail,
|
||||
should_panic: libtest::ShouldPanic::No,
|
||||
},
|
||||
// oli obk giving up
|
||||
testfn: unsafe { std::mem::transmute(test.testfn) },
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let res = run_ui_toml_tests(&config, tests);
|
||||
match res {
|
||||
Ok(true) => {},
|
||||
|
|
|
@ -198,7 +198,7 @@ error: it is more concise to loop over references to containers instead of using
|
|||
--> $DIR/for_loop.rs:170:15
|
||||
|
|
||||
LL | for _v in vec.iter() {}
|
||||
| ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
|
||||
|
||||
|
@ -206,13 +206,13 @@ error: it is more concise to loop over references to containers instead of using
|
|||
--> $DIR/for_loop.rs:172:15
|
||||
|
|
||||
LL | for _v in vec.iter_mut() {}
|
||||
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over containers instead of using explicit iteration methods`
|
||||
--> $DIR/for_loop.rs:175:15
|
||||
|
|
||||
LL | for _v in out_vec.into_iter() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec`
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
|
||||
|
||||
|
@ -220,61 +220,61 @@ error: it is more concise to loop over references to containers instead of using
|
|||
--> $DIR/for_loop.rs:178:15
|
||||
|
|
||||
LL | for _v in array.into_iter() {}
|
||||
| ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array`
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:183:15
|
||||
|
|
||||
LL | for _v in [1, 2, 3].iter() {}
|
||||
| ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:187:15
|
||||
|
|
||||
LL | for _v in [0; 32].iter() {}
|
||||
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:192:15
|
||||
|
|
||||
LL | for _v in ll.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&ll`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:195:15
|
||||
|
|
||||
LL | for _v in vd.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&vd`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:198:15
|
||||
|
|
||||
LL | for _v in bh.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&bh`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:201:15
|
||||
|
|
||||
LL | for _v in hm.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&hm`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:204:15
|
||||
|
|
||||
LL | for _v in bt.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&bt`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:207:15
|
||||
|
|
||||
LL | for _v in hs.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&hs`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||
--> $DIR/for_loop.rs:210:15
|
||||
|
|
||||
LL | for _v in bs.iter() {}
|
||||
| ^^^^^^^^^ help: to write this more concisely, try: `&bs`
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
|
||||
--> $DIR/for_loop.rs:212:15
|
||||
|
|
|
@ -10,7 +10,7 @@ fn main() {
|
|||
for _ in &[1, 2, 3] {}
|
||||
for _ in vec![X, X] {}
|
||||
for _ in &vec![X, X] {}
|
||||
for _ in [1, 2, 3].iter() {} //~ ERROR equivalent to .iter()
|
||||
for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter()
|
||||
|
||||
let _ = [1, 2, 3].iter(); //~ ERROR equivalent to .iter()
|
||||
let _ = vec![1, 2, 3].into_iter();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: this .into_iter() call is equivalent to .iter() and will not move the array
|
||||
--> $DIR/into_iter_on_ref.rs:13:24
|
||||
--> $DIR/into_iter_on_ref.rs:15:23
|
||||
|
|
||||
LL | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter()
|
||||
| ^^^^^^^^^ help: call directly: `iter`
|
||||
LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter()
|
||||
| ^^^^^^^^^ help: call directly: `iter`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/into_iter_on_ref.rs:4:9
|
||||
|
@ -10,12 +10,6 @@ note: lint level defined here
|
|||
LL | #![deny(clippy::into_iter_on_array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this .into_iter() call is equivalent to .iter() and will not move the array
|
||||
--> $DIR/into_iter_on_ref.rs:15:23
|
||||
|
|
||||
LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter()
|
||||
| ^^^^^^^^^ help: call directly: `iter`
|
||||
|
||||
error: this .into_iter() call is equivalent to .iter() and will not move the Vec
|
||||
--> $DIR/into_iter_on_ref.rs:17:30
|
||||
|
|
||||
|
@ -174,5 +168,5 @@ error: this .into_iter() call is equivalent to .iter() and will not move the Pat
|
|||
LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter()
|
||||
| ^^^^^^^^^ help: call directly: `iter`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 27 previous errors
|
||||
|
||||
|
|
|
@ -37,27 +37,9 @@ fn main() {
|
|||
let ok16 = 0xFE_BAFE_ABAB_ABCD;
|
||||
let ok17 = 0x123_4567_8901_usize;
|
||||
|
||||
let fail9 = 0xabcdef;
|
||||
let fail10 = 0xBAFEBAFE;
|
||||
let fail11 = 0xabcdeff;
|
||||
let fail12 = 0xabcabcabcabcabcabc;
|
||||
let fail13 = 0x1_23456_78901_usize;
|
||||
|
||||
let fail14 = 2_32;
|
||||
let fail15 = 4_64;
|
||||
let fail16 = 7_8;
|
||||
let fail17 = 23_16;
|
||||
let ok18 = 23_128;
|
||||
let fail19 = 12_3456_21;
|
||||
let fail20 = 2__8;
|
||||
let fail21 = 4___16;
|
||||
let fail22 = 3__4___23;
|
||||
let fail23 = 3__16___23;
|
||||
|
||||
let fail24 = 12.34_64;
|
||||
let fail25 = 1E2_32;
|
||||
let fail26 = 43E7_64;
|
||||
let fail27 = 243E17_32;
|
||||
let fail28 = 241251235E723_64;
|
||||
let fail29 = 42279.911_32;
|
||||
}
|
||||
|
|
|
@ -86,133 +86,33 @@ help: if you mean to use an octal constant, use `0o`
|
|||
LL | let fail8 = 0o123;
|
||||
| ^^^^^
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/literals.rs:40:17
|
||||
|
|
||||
LL | let fail9 = 0xabcdef;
|
||||
| ^^^^^^^^ help: consider: `0x00ab_cdef`
|
||||
|
|
||||
= note: `-D clippy::unreadable-literal` implied by `-D warnings`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/literals.rs:41:18
|
||||
|
|
||||
LL | let fail10 = 0xBAFEBAFE;
|
||||
| ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/literals.rs:42:18
|
||||
|
|
||||
LL | let fail11 = 0xabcdeff;
|
||||
| ^^^^^^^^^ help: consider: `0x0abc_deff`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/literals.rs:43:18
|
||||
|
|
||||
LL | let fail12 = 0xabcabcabcabcabcabc;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
|
||||
|
||||
error: digit groups should be smaller
|
||||
--> $DIR/literals.rs:44:18
|
||||
--> $DIR/literals.rs:40:18
|
||||
|
|
||||
LL | let fail13 = 0x1_23456_78901_usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize`
|
||||
|
|
||||
= note: `-D clippy::large-digit-groups` implied by `-D warnings`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:46:18
|
||||
|
|
||||
LL | let fail14 = 2_32;
|
||||
| ^^^^ help: did you mean to write: `2_i32`
|
||||
|
|
||||
= note: #[deny(clippy::mistyped_literal_suffixes)] on by default
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:47:18
|
||||
|
|
||||
LL | let fail15 = 4_64;
|
||||
| ^^^^ help: did you mean to write: `4_i64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:48:18
|
||||
|
|
||||
LL | let fail16 = 7_8;
|
||||
| ^^^ help: did you mean to write: `7_i8`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:49:18
|
||||
|
|
||||
LL | let fail17 = 23_16;
|
||||
| ^^^^^ help: did you mean to write: `23_i16`
|
||||
|
||||
error: digits grouped inconsistently by underscores
|
||||
--> $DIR/literals.rs:51:18
|
||||
--> $DIR/literals.rs:42:18
|
||||
|
|
||||
LL | let fail19 = 12_3456_21;
|
||||
| ^^^^^^^^^^ help: consider: `12_345_621`
|
||||
|
|
||||
= note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:52:18
|
||||
|
|
||||
LL | let fail20 = 2__8;
|
||||
| ^^^^ help: did you mean to write: `2_i8`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:53:18
|
||||
|
|
||||
LL | let fail21 = 4___16;
|
||||
| ^^^^^^ help: did you mean to write: `4_i16`
|
||||
|
||||
error: digits grouped inconsistently by underscores
|
||||
--> $DIR/literals.rs:54:18
|
||||
--> $DIR/literals.rs:43:18
|
||||
|
|
||||
LL | let fail22 = 3__4___23;
|
||||
| ^^^^^^^^^ help: consider: `3_423`
|
||||
|
||||
error: digits grouped inconsistently by underscores
|
||||
--> $DIR/literals.rs:55:18
|
||||
--> $DIR/literals.rs:44:18
|
||||
|
|
||||
LL | let fail23 = 3__16___23;
|
||||
| ^^^^^^^^^^ help: consider: `31_623`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:57:18
|
||||
|
|
||||
LL | let fail24 = 12.34_64;
|
||||
| ^^^^^^^^ help: did you mean to write: `12.34_f64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:58:18
|
||||
|
|
||||
LL | let fail25 = 1E2_32;
|
||||
| ^^^^^^ help: did you mean to write: `1E2_f32`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:59:18
|
||||
|
|
||||
LL | let fail26 = 43E7_64;
|
||||
| ^^^^^^^ help: did you mean to write: `43E7_f64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:60:18
|
||||
|
|
||||
LL | let fail27 = 243E17_32;
|
||||
| ^^^^^^^^^ help: did you mean to write: `243E17_f32`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:61:18
|
||||
|
|
||||
LL | let fail28 = 241251235E723_64;
|
||||
| ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/literals.rs:62:18
|
||||
|
|
||||
LL | let fail29 = 42279.911_32;
|
||||
| ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32`
|
||||
|
||||
error: aborting due to 31 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
|
3
tests/ui/missing-doc-crate-missing.rs
Normal file
3
tests/ui/missing-doc-crate-missing.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
#![warn(clippy::missing_docs_in_private_items)]
|
||||
|
||||
fn main() {}
|
12
tests/ui/missing-doc-crate-missing.stderr
Normal file
12
tests/ui/missing-doc-crate-missing.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error: missing documentation for crate
|
||||
--> $DIR/missing-doc-crate-missing.rs:1:1
|
||||
|
|
||||
LL | / #![warn(clippy::missing_docs_in_private_items)]
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
|
||||
= note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
5
tests/ui/missing-doc-crate.rs
Normal file
5
tests/ui/missing-doc-crate.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
#![warn(clippy::missing_docs_in_private_items)]
|
||||
#![feature(external_doc)]
|
||||
#![doc(include = "../../README.md")]
|
||||
|
||||
fn main() {}
|
0
tests/ui/missing-doc-crate.stderr
Normal file
0
tests/ui/missing-doc-crate.stderr
Normal file
22
tests/ui/mistyped_literal_suffix.fixed
Normal file
22
tests/ui/mistyped_literal_suffix.fixed
Normal file
|
@ -0,0 +1,22 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(dead_code, unused_variables, clippy::excessive_precision)]
|
||||
|
||||
fn main() {
|
||||
let fail14 = 2_i32;
|
||||
let fail15 = 4_i64;
|
||||
let fail16 = 7_i8; //
|
||||
let fail17 = 23_i16; //
|
||||
let ok18 = 23_128;
|
||||
|
||||
let fail20 = 2_i8; //
|
||||
let fail21 = 4_i16; //
|
||||
|
||||
let fail24 = 12.34_f64;
|
||||
let fail25 = 1E2_f32;
|
||||
let fail26 = 43E7_f64;
|
||||
let fail27 = 243E17_f32;
|
||||
#[allow(overflowing_literals)]
|
||||
let fail28 = 241_251_235E723_f64;
|
||||
let fail29 = 42_279.911_f32;
|
||||
}
|
22
tests/ui/mistyped_literal_suffix.rs
Normal file
22
tests/ui/mistyped_literal_suffix.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(dead_code, unused_variables, clippy::excessive_precision)]
|
||||
|
||||
fn main() {
|
||||
let fail14 = 2_32;
|
||||
let fail15 = 4_64;
|
||||
let fail16 = 7_8; //
|
||||
let fail17 = 23_16; //
|
||||
let ok18 = 23_128;
|
||||
|
||||
let fail20 = 2__8; //
|
||||
let fail21 = 4___16; //
|
||||
|
||||
let fail24 = 12.34_64;
|
||||
let fail25 = 1E2_32;
|
||||
let fail26 = 43E7_64;
|
||||
let fail27 = 243E17_32;
|
||||
#[allow(overflowing_literals)]
|
||||
let fail28 = 241251235E723_64;
|
||||
let fail29 = 42279.911_32;
|
||||
}
|
76
tests/ui/mistyped_literal_suffix.stderr
Normal file
76
tests/ui/mistyped_literal_suffix.stderr
Normal file
|
@ -0,0 +1,76 @@
|
|||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:6:18
|
||||
|
|
||||
LL | let fail14 = 2_32;
|
||||
| ^^^^ help: did you mean to write: `2_i32`
|
||||
|
|
||||
= note: #[deny(clippy::mistyped_literal_suffixes)] on by default
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:7:18
|
||||
|
|
||||
LL | let fail15 = 4_64;
|
||||
| ^^^^ help: did you mean to write: `4_i64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:8:18
|
||||
|
|
||||
LL | let fail16 = 7_8; //
|
||||
| ^^^ help: did you mean to write: `7_i8`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:9:18
|
||||
|
|
||||
LL | let fail17 = 23_16; //
|
||||
| ^^^^^ help: did you mean to write: `23_i16`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:12:18
|
||||
|
|
||||
LL | let fail20 = 2__8; //
|
||||
| ^^^^ help: did you mean to write: `2_i8`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:13:18
|
||||
|
|
||||
LL | let fail21 = 4___16; //
|
||||
| ^^^^^^ help: did you mean to write: `4_i16`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:15:18
|
||||
|
|
||||
LL | let fail24 = 12.34_64;
|
||||
| ^^^^^^^^ help: did you mean to write: `12.34_f64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:16:18
|
||||
|
|
||||
LL | let fail25 = 1E2_32;
|
||||
| ^^^^^^ help: did you mean to write: `1E2_f32`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:17:18
|
||||
|
|
||||
LL | let fail26 = 43E7_64;
|
||||
| ^^^^^^^ help: did you mean to write: `43E7_f64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:18:18
|
||||
|
|
||||
LL | let fail27 = 243E17_32;
|
||||
| ^^^^^^^^^ help: did you mean to write: `243E17_f32`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:20:18
|
||||
|
|
||||
LL | let fail28 = 241251235E723_64;
|
||||
| ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64`
|
||||
|
||||
error: mistyped literal suffix
|
||||
--> $DIR/mistyped_literal_suffix.rs:21:18
|
||||
|
|
||||
LL | let fail29 = 42279.911_32;
|
||||
| ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
|
@ -95,7 +95,7 @@ impl<T: Serialize, U> S<T, U> {
|
|||
s.len() + t.capacity()
|
||||
}
|
||||
|
||||
fn bar(_t: T // Ok, since `&T: Serialize` too
|
||||
fn bar(_t: T, // Ok, since `&T: Serialize` too
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
@ -17,4 +17,9 @@ fn main() {
|
|||
let bad = (0b11_0110_i64, 0x0123_4567_8901_usize, 123_456_f32, 1.234_567_f32);
|
||||
let good_sci = 1.1234e1;
|
||||
let bad_sci = 1.123_456e1;
|
||||
|
||||
let fail9 = 0x00ab_cdef;
|
||||
let fail10: u32 = 0xBAFE_BAFE;
|
||||
let fail11 = 0x0abc_deff;
|
||||
let fail12: i128 = 0x00ab_cabc_abca_bcab_cabc;
|
||||
}
|
||||
|
|
|
@ -17,4 +17,9 @@ fn main() {
|
|||
let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32);
|
||||
let good_sci = 1.1234e1;
|
||||
let bad_sci = 1.123456e1;
|
||||
|
||||
let fail9 = 0xabcdef;
|
||||
let fail10: u32 = 0xBAFEBAFE;
|
||||
let fail11 = 0xabcdeff;
|
||||
let fail12: i128 = 0xabcabcabcabcabcabc;
|
||||
}
|
||||
|
|
|
@ -30,5 +30,29 @@ error: long literal lacking separators
|
|||
LL | let bad_sci = 1.123456e1;
|
||||
| ^^^^^^^^^^ help: consider: `1.123_456e1`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:21:17
|
||||
|
|
||||
LL | let fail9 = 0xabcdef;
|
||||
| ^^^^^^^^ help: consider: `0x00ab_cdef`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:22:23
|
||||
|
|
||||
LL | let fail10: u32 = 0xBAFEBAFE;
|
||||
| ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:23:18
|
||||
|
|
||||
LL | let fail11 = 0xabcdeff;
|
||||
| ^^^^^^^^^ help: consider: `0x0abc_deff`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:24:24
|
||||
|
|
||||
LL | let fail12: i128 = 0xabcabcabcabcabcabc;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
@ -239,6 +239,7 @@ mod nesting {
|
|||
struct Foo {}
|
||||
impl Foo {
|
||||
fn foo() {
|
||||
#[allow(unused_imports)]
|
||||
use self::Foo; // Can't use Self here
|
||||
struct Bar {
|
||||
foo: Foo, // Foo != Self
|
||||
|
|
|
@ -239,6 +239,7 @@ mod nesting {
|
|||
struct Foo {}
|
||||
impl Foo {
|
||||
fn foo() {
|
||||
#[allow(unused_imports)]
|
||||
use self::Foo; // Can't use Self here
|
||||
struct Bar {
|
||||
foo: Foo, // Foo != Self
|
||||
|
|
|
@ -151,43 +151,43 @@ LL | use_self_expand!(); // Should lint in local macros
|
|||
| ------------------- in this macro invocation
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:260:21
|
||||
--> $DIR/use_self.rs:261:21
|
||||
|
|
||||
LL | fn baz() -> Foo {
|
||||
| ^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:261:13
|
||||
--> $DIR/use_self.rs:262:13
|
||||
|
|
||||
LL | Foo {}
|
||||
| ^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:248:29
|
||||
--> $DIR/use_self.rs:249:29
|
||||
|
|
||||
LL | fn bar() -> Bar {
|
||||
| ^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:249:21
|
||||
--> $DIR/use_self.rs:250:21
|
||||
|
|
||||
LL | Bar { foo: Foo {} }
|
||||
| ^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:303:13
|
||||
--> $DIR/use_self.rs:304:13
|
||||
|
|
||||
LL | nested::A::fun_1();
|
||||
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:304:13
|
||||
--> $DIR/use_self.rs:305:13
|
||||
|
|
||||
LL | nested::A::A;
|
||||
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:306:13
|
||||
--> $DIR/use_self.rs:307:13
|
||||
|
|
||||
LL | nested::A {};
|
||||
| ^^^^^^^^^ help: use the applicable keyword: `Self`
|
||||
|
|
136
tests/ui/useless_asref.fixed
Normal file
136
tests/ui/useless_asref.fixed
Normal file
|
@ -0,0 +1,136 @@
|
|||
// run-rustfix
|
||||
|
||||
#![deny(clippy::useless_asref)]
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
struct FakeAsRef;
|
||||
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
impl FakeAsRef {
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
struct MoreRef;
|
||||
|
||||
impl<'a, 'b, 'c> AsRef<&'a &'b &'c MoreRef> for MoreRef {
|
||||
fn as_ref(&self) -> &&'a &'b &'c MoreRef {
|
||||
&&&&MoreRef
|
||||
}
|
||||
}
|
||||
|
||||
fn foo_rstr(x: &str) {
|
||||
println!("{:?}", x);
|
||||
}
|
||||
fn foo_rslice(x: &[i32]) {
|
||||
println!("{:?}", x);
|
||||
}
|
||||
fn foo_mrslice(x: &mut [i32]) {
|
||||
println!("{:?}", x);
|
||||
}
|
||||
fn foo_rrrrmr(_: &&&&MoreRef) {
|
||||
println!("so many refs");
|
||||
}
|
||||
|
||||
fn not_ok() {
|
||||
let rstr: &str = "hello";
|
||||
let mut mrslice: &mut [i32] = &mut [1, 2, 3];
|
||||
|
||||
{
|
||||
let rslice: &[i32] = &*mrslice;
|
||||
foo_rstr(rstr);
|
||||
foo_rstr(rstr);
|
||||
foo_rslice(rslice);
|
||||
foo_rslice(rslice);
|
||||
}
|
||||
{
|
||||
foo_mrslice(mrslice);
|
||||
foo_mrslice(mrslice);
|
||||
foo_rslice(mrslice);
|
||||
foo_rslice(mrslice);
|
||||
}
|
||||
|
||||
{
|
||||
let rrrrrstr = &&&&rstr;
|
||||
let rrrrrslice = &&&&&*mrslice;
|
||||
foo_rslice(rrrrrslice);
|
||||
foo_rslice(rrrrrslice);
|
||||
foo_rstr(rrrrrstr);
|
||||
foo_rstr(rrrrrstr);
|
||||
}
|
||||
{
|
||||
let mrrrrrslice = &mut &mut &mut &mut mrslice;
|
||||
foo_mrslice(mrrrrrslice);
|
||||
foo_mrslice(mrrrrrslice);
|
||||
foo_rslice(mrrrrrslice);
|
||||
foo_rslice(mrrrrrslice);
|
||||
}
|
||||
#[allow(unused_parens, clippy::double_parens)]
|
||||
foo_rrrrmr((&&&&MoreRef));
|
||||
|
||||
generic_not_ok(mrslice);
|
||||
generic_ok(mrslice);
|
||||
}
|
||||
|
||||
fn ok() {
|
||||
let string = "hello".to_owned();
|
||||
let mut arr = [1, 2, 3];
|
||||
let mut vec = vec![1, 2, 3];
|
||||
|
||||
{
|
||||
foo_rstr(string.as_ref());
|
||||
foo_rslice(arr.as_ref());
|
||||
foo_rslice(vec.as_ref());
|
||||
}
|
||||
{
|
||||
foo_mrslice(arr.as_mut());
|
||||
foo_mrslice(vec.as_mut());
|
||||
}
|
||||
|
||||
{
|
||||
let rrrrstring = &&&&string;
|
||||
let rrrrarr = &&&&arr;
|
||||
let rrrrvec = &&&&vec;
|
||||
foo_rstr(rrrrstring.as_ref());
|
||||
foo_rslice(rrrrarr.as_ref());
|
||||
foo_rslice(rrrrvec.as_ref());
|
||||
}
|
||||
{
|
||||
let mrrrrarr = &mut &mut &mut &mut arr;
|
||||
let mrrrrvec = &mut &mut &mut &mut vec;
|
||||
foo_mrslice(mrrrrarr.as_mut());
|
||||
foo_mrslice(mrrrrvec.as_mut());
|
||||
}
|
||||
FakeAsRef.as_ref();
|
||||
foo_rrrrmr(MoreRef.as_ref());
|
||||
|
||||
generic_not_ok(arr.as_mut());
|
||||
generic_ok(&mut arr);
|
||||
}
|
||||
|
||||
fn foo_mrt<T: Debug + ?Sized>(t: &mut T) {
|
||||
println!("{:?}", t);
|
||||
}
|
||||
fn foo_rt<T: Debug + ?Sized>(t: &T) {
|
||||
println!("{:?}", t);
|
||||
}
|
||||
|
||||
fn generic_not_ok<T: AsMut<T> + AsRef<T> + Debug + ?Sized>(mrt: &mut T) {
|
||||
foo_mrt(mrt);
|
||||
foo_mrt(mrt);
|
||||
foo_rt(mrt);
|
||||
foo_rt(mrt);
|
||||
}
|
||||
|
||||
fn generic_ok<U: AsMut<T> + AsRef<T> + ?Sized, T: Debug + ?Sized>(mru: &mut U) {
|
||||
foo_mrt(mru.as_mut());
|
||||
foo_rt(mru.as_ref());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
not_ok();
|
||||
ok();
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
// run-rustfix
|
||||
|
||||
#![deny(clippy::useless_asref)]
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
struct FakeAsRef;
|
||||
|
@ -65,6 +68,7 @@ fn not_ok() {
|
|||
foo_rslice(mrrrrrslice.as_ref());
|
||||
foo_rslice(mrrrrrslice);
|
||||
}
|
||||
#[allow(unused_parens, clippy::double_parens)]
|
||||
foo_rrrrmr((&&&&MoreRef).as_ref());
|
||||
|
||||
generic_not_ok(mrslice);
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:41:18
|
||||
--> $DIR/useless_asref.rs:44:18
|
||||
|
|
||||
LL | foo_rstr(rstr.as_ref());
|
||||
| ^^^^^^^^^^^^^ help: try this: `rstr`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/useless_asref.rs:1:9
|
||||
--> $DIR/useless_asref.rs:3:9
|
||||
|
|
||||
LL | #![deny(clippy::useless_asref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:43:20
|
||||
--> $DIR/useless_asref.rs:46:20
|
||||
|
|
||||
LL | foo_rslice(rslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^ help: try this: `rslice`
|
||||
|
||||
error: this call to `as_mut` does nothing
|
||||
--> $DIR/useless_asref.rs:47:21
|
||||
--> $DIR/useless_asref.rs:50:21
|
||||
|
|
||||
LL | foo_mrslice(mrslice.as_mut());
|
||||
| ^^^^^^^^^^^^^^^^ help: try this: `mrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:49:20
|
||||
--> $DIR/useless_asref.rs:52:20
|
||||
|
|
||||
LL | foo_rslice(mrslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^ help: try this: `mrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:56:20
|
||||
--> $DIR/useless_asref.rs:59:20
|
||||
|
|
||||
LL | foo_rslice(rrrrrslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:58:18
|
||||
--> $DIR/useless_asref.rs:61:18
|
||||
|
|
||||
LL | foo_rstr(rrrrrstr.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr`
|
||||
|
||||
error: this call to `as_mut` does nothing
|
||||
--> $DIR/useless_asref.rs:63:21
|
||||
--> $DIR/useless_asref.rs:66:21
|
||||
|
|
||||
LL | foo_mrslice(mrrrrrslice.as_mut());
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:65:20
|
||||
--> $DIR/useless_asref.rs:68:20
|
||||
|
|
||||
LL | foo_rslice(mrrrrrslice.as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:68:16
|
||||
--> $DIR/useless_asref.rs:72:16
|
||||
|
|
||||
LL | foo_rrrrmr((&&&&MoreRef).as_ref());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)`
|
||||
|
||||
error: this call to `as_mut` does nothing
|
||||
--> $DIR/useless_asref.rs:118:13
|
||||
--> $DIR/useless_asref.rs:122:13
|
||||
|
|
||||
LL | foo_mrt(mrt.as_mut());
|
||||
| ^^^^^^^^^^^^ help: try this: `mrt`
|
||||
|
||||
error: this call to `as_ref` does nothing
|
||||
--> $DIR/useless_asref.rs:120:12
|
||||
--> $DIR/useless_asref.rs:124:12
|
||||
|
|
||||
LL | foo_rt(mrt.as_ref());
|
||||
| ^^^^^^^^^^^^ help: try this: `mrt`
|
||||
|
|
Loading…
Reference in a new issue