Merge remote-tracking branch 'upstream/master' into rustup

This commit is contained in:
flip1995 2020-12-20 16:25:54 +01:00
commit 883a3d10c8
No known key found for this signature in database
GPG key ID: 2CEFCDB27ED0BE79
120 changed files with 3205 additions and 1066 deletions

View file

@ -408,7 +408,10 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
}
pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool {
matches!((l, r), (Defaultness::Final, Defaultness::Final) | (Defaultness::Default(_), Defaultness::Default(_)))
matches!(
(l, r),
(Defaultness::Final, Defaultness::Final) | (Defaultness::Default(_), Defaultness::Default(_))
)
}
pub fn eq_vis(l: &Visibility, r: &Visibility) -> bool {

View file

@ -106,7 +106,7 @@ macro_rules! define_Conf {
pub use self::helpers::Conf;
define_Conf! {
/// Lint: MANUAL_NON_EXHAUSTIVE, MANUAL_STRIP, OPTION_AS_REF_DEREF, MATCH_LIKE_MATCHES_MACRO. The minimum rust version that the project supports
/// Lint: REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN. The minimum rust version that the project supports
(msrv, "msrv": Option<String>, None),
/// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
(blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),

View file

@ -15,6 +15,7 @@ use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Node, Path, StmtKind, Ty, TyKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::{Span, Spanned};
@ -247,6 +248,30 @@ declare_clippy_lint! {
"invalid path"
}
declare_clippy_lint! {
/// **What it does:**
/// Checks for interning symbols that have already been pre-interned and defined as constants.
///
/// **Why is this bad?**
/// It's faster and easier to use the symbol constant.
///
/// **Known problems:** None.
///
/// **Example:**
/// Bad:
/// ```rust,ignore
/// let _ = sym!(f32);
/// ```
///
/// Good:
/// ```rust,ignore
/// let _ = sym::f32;
/// ```
pub INTERNING_DEFINED_SYMBOL,
internal,
"interning a symbol that is pre-interned and defined as a constant"
}
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
impl EarlyLintPass for ClippyLintsInternal {
@ -840,3 +865,56 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
}
}
}
#[derive(Default)]
pub struct InterningDefinedSymbol {
// Maps the symbol value to the constant name.
symbol_map: FxHashMap<u32, String>,
}
impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL]);
impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
if !self.symbol_map.is_empty() {
return;
}
if let Some(Res::Def(_, def_id)) = path_to_res(cx, &paths::SYM_MODULE) {
for item in cx.tcx.item_children(def_id).iter() {
if_chain! {
if let Res::Def(DefKind::Const, item_def_id) = item.res;
let ty = cx.tcx.type_of(item_def_id);
if match_type(cx, ty, &paths::SYMBOL);
if let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id);
if let Ok(value) = value.to_u32();
then {
self.symbol_map.insert(value, item.ident.to_string());
}
}
}
}
}
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::Call(func, [arg]) = &expr.kind;
if let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind();
if match_def_path(cx, *def_id, &paths::SYMBOL_INTERN);
if let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg);
let value = Symbol::intern(&arg).as_u32();
if let Some(symbol_const) = self.symbol_map.get(&value);
then {
span_lint_and_sugg(
cx,
INTERNING_DEFINED_SYMBOL,
is_expn_of(expr.span, "sym").unwrap_or(expr.span),
"interning a defined symbol",
"try",
format!("rustc_span::symbol::sym::{}", symbol_const),
Applicability::MachineApplicable,
);
}
}
}
}

View file

@ -41,7 +41,7 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::Node;
use rustc_hir::{
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind,
@ -603,6 +603,37 @@ pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
visitor.found
}
struct FindMacroCalls<'a, 'b> {
names: &'a [&'b str],
result: Vec<Span>,
}
impl<'a, 'b, 'tcx> Visitor<'tcx> for FindMacroCalls<'a, 'b> {
type Map = Map<'tcx>;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if self.names.iter().any(|fun| is_expn_of(expr.span, fun).is_some()) {
self.result.push(expr.span);
}
// and check sub-expressions
intravisit::walk_expr(self, expr);
}
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
NestedVisitorMap::None
}
}
/// Finds calls of the specified macros in a function body.
pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> {
let mut fmc = FindMacroCalls {
names,
result: Vec::new(),
};
fmc.visit_expr(&body.value);
fmc.result
}
/// Converts a span to a code snippet if available, otherwise use default.
///
/// This is useful if you want to provide suggestions for your lint or more generally, if you want
@ -1500,7 +1531,7 @@ pub fn is_no_std_crate(krate: &Crate<'_>) -> bool {
/// ```
pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
matches!(item.kind, ItemKind::Impl{ of_trait: Some(_), .. })
matches!(item.kind, ItemKind::Impl { of_trait: Some(_), .. })
} else {
false
}

View file

@ -146,6 +146,12 @@ pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
#[cfg(feature = "internal-lints")]
pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
#[cfg(feature = "internal-lints")]
pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
#[cfg(feature = "internal-lints")]
pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
#[cfg(feature = "internal-lints")]
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"];
pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];

View file

@ -116,20 +116,27 @@ pub struct ParamBindingIdCollector {
}
impl<'tcx> ParamBindingIdCollector {
fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec<hir::HirId> {
let mut finder = ParamBindingIdCollector {
binding_hir_ids: Vec::new(),
};
finder.visit_body(body);
finder.binding_hir_ids
let mut hir_ids: Vec<hir::HirId> = Vec::new();
for param in body.params.iter() {
let mut finder = ParamBindingIdCollector {
binding_hir_ids: Vec::new(),
};
finder.visit_param(param);
for hir_id in &finder.binding_hir_ids {
hir_ids.push(*hir_id);
}
}
hir_ids
}
}
impl<'tcx> intravisit::Visitor<'tcx> for ParamBindingIdCollector {
type Map = Map<'tcx>;
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
if let hir::PatKind::Binding(_, hir_id, ..) = param.pat.kind {
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
if let hir::PatKind::Binding(_, hir_id, ..) = pat.kind {
self.binding_hir_ids.push(hir_id);
}
intravisit::walk_pat(self, pat);
}
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {