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:
bors 2019-03-18 16:21:56 +00:00
commit 92612c9de1
22 changed files with 233 additions and 152 deletions

View File

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

View File

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

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

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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