Merge branch 'master' into clippy_dev_toolchain

This commit is contained in:
Michael Wright 2019-04-05 05:59:46 +02:00
commit a9d002c8a5
57 changed files with 701 additions and 374 deletions

View file

@ -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" }

View file

@ -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;

View file

@ -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) => {

View file

@ -152,7 +152,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>,
spans.extend_from_slice(&current_spans);
doc.push_str(&current);
}
} else if attr.name() == "doc" {
} else if attr.check_name("doc") {
// ignore mix of sugared and non-sugared doc
return;
}

View file

@ -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)));
}
}
}

View file

@ -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(),
}
}

View file

@ -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,

View file

@ -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))

View file

@ -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;
}

View file

@ -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);

View file

@ -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)]

View file

@ -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);

View file

@ -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,

View file

@ -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();

View file

@ -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;
}

View file

@ -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,

View file

@ -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;
}
}

View file

@ -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))
})
}

View file

@ -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! {

View file

@ -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,

View file

@ -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`

View file

@ -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);
}

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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
};

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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))

View file

@ -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.

View file

@ -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()

View file

@ -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

View file

@ -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 {

View file

@ -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) => {},

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -0,0 +1,3 @@
#![warn(clippy::missing_docs_in_private_items)]
fn main() {}

View 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

View file

@ -0,0 +1,5 @@
#![warn(clippy::missing_docs_in_private_items)]
#![feature(external_doc)]
#![doc(include = "../../README.md")]
fn main() {}

View file

View 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;
}

View 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;
}

View 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

View file

@ -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
) {
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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`

View 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();
}

View file

@ -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);

View file

@ -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`