Auto merge of #3893 - mati865:rustup, r=oli-obk
Rustup Supersedes https://github.com/rust-lang/rust-clippy/pull/3889 Addresses some review comments from previous PR and rustups to https://github.com/rust-lang/rust/pull/58899
This commit is contained in:
commit
92612c9de1
@ -14,7 +14,7 @@
|
||||
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 @@ fn name(&self) -> &'static str {
|
||||
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_str() {
|
||||
match ident {
|
||||
"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 @@ fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||
}
|
||||
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_str() {
|
||||
match ident {
|
||||
"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 @@ fn hash<H>(&self, state: &mut H)
|
||||
}
|
||||
|
||||
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 @@ pub fn expr(&mut self, e: &Expr) -> Option<Constant> {
|
||||
}
|
||||
|
||||
#[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 @@ fn constant_not(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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 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 nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -51,7 +51,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem
|
||||
|
||||
fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if attr.name() != "inline" {
|
||||
if !attr.check_name("inline") {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -3,7 +3,7 @@
|
||||
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 @@ fn name(&self) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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.did), suffix)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -2196,7 +2196,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 +2217,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;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ fn has_include(meta: Option<MetaItem>) -> bool {
|
||||
if let Some(meta) = meta;
|
||||
if let MetaItemKind::List(list) = meta.node;
|
||||
if let Some(meta) = list.get(0);
|
||||
if let Some(name) = meta.name();
|
||||
if let Some(name) = meta.ident_str();
|
||||
then {
|
||||
name == "include"
|
||||
} else {
|
||||
@ -91,7 +91,7 @@ fn check_missing_docs_attrs(
|
||||
|
||||
let has_doc = attrs
|
||||
.iter()
|
||||
.any(|a| a.name() == "doc" && (a.is_value_str() || Self::has_include(a.meta())));
|
||||
.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 @@
|
||||
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,
|
||||
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
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 @@ fn lint(&self) -> (&'static Lint, &'static str, Span) {
|
||||
}
|
||||
}
|
||||
|
||||
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`
|
||||
|
@ -12,7 +12,7 @@
|
||||
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;
|
||||
|
@ -263,7 +263,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
}
|
||||
|
||||
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 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||
|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 @@ fn check_fn(
|
||||
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::*;
|
||||
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::{
|
||||
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 @@ fn name(&self) -> &'static str {
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
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;
|
||||
@ -233,7 +234,7 @@ fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
|
||||
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) {
|
||||
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 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 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::DisambiguatedDefPathData;
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::{LateContext, Level, Lint, LintContext};
|
||||
@ -41,8 +43,7 @@
|
||||
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,96 @@ 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)?;
|
||||
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 +199,10 @@ fn push(&mut self, text: &str) {
|
||||
/// ```
|
||||
///
|
||||
/// 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 +214,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()
|
||||
}
|
||||
|
||||
@ -1010,7 +1086,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.
|
||||
|
Loading…
Reference in New Issue
Block a user