Auto merge of #8656 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: none
This commit is contained in:
commit
abc59bb914
@ -8,9 +8,9 @@ document.
|
||||
|
||||
[57b3c4b...master](https://github.com/rust-lang/rust-clippy/compare/57b3c4b...master)
|
||||
|
||||
## Rust 1.60 (beta)
|
||||
## Rust 1.60
|
||||
|
||||
Current beta, release 2022-04-07
|
||||
Current stable, released 2022-04-07
|
||||
|
||||
[0eff589...57b3c4b](https://github.com/rust-lang/rust-clippy/compare/0eff589...57b3c4b)
|
||||
|
||||
@ -142,7 +142,7 @@ Current beta, release 2022-04-07
|
||||
|
||||
## Rust 1.59
|
||||
|
||||
Current stable, release 2022-02-24
|
||||
Released 2022-02-24
|
||||
|
||||
[e181011...0eff589](https://github.com/rust-lang/rust-clippy/compare/e181011...0eff589)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clippy"
|
||||
version = "0.1.61"
|
||||
version = "0.1.62"
|
||||
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
repository = "https://github.com/rust-lang/rust-clippy"
|
||||
readme = "README.md"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.61"
|
||||
version = "0.1.62"
|
||||
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
|
||||
repository = "https://github.com/rust-lang/rust-clippy"
|
||||
readme = "README.md"
|
||||
|
@ -139,11 +139,11 @@ impl<'tcx> LateLintPass<'tcx> for Arithmetic {
|
||||
}
|
||||
|
||||
fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
|
||||
let body_owner = cx.tcx.hir().body_owner(body.id());
|
||||
let body_owner = cx.tcx.hir().body_owner_def_id(body.id());
|
||||
|
||||
match cx.tcx.hir().body_owner_kind(body_owner) {
|
||||
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
|
||||
let body_span = cx.tcx.hir().span(body_owner);
|
||||
let body_span = cx.tcx.def_span(body_owner);
|
||||
|
||||
if let Some(span) = self.const_span {
|
||||
if span.contains(body_span) {
|
||||
|
@ -3,11 +3,12 @@ use clippy_utils::higher::IfLetOrMatch;
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_hir::LangItem::OptionNone;
|
||||
use rustc_hir::{Arm, Expr, Guard, HirId, Pat, PatKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -129,8 +130,8 @@ fn check_arm<'tcx>(
|
||||
&msg,
|
||||
|diag| {
|
||||
let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]);
|
||||
help_span.push_span_label(binding_span, "replace this binding".into());
|
||||
help_span.push_span_label(inner_then_pat.span, "with this pattern".into());
|
||||
help_span.push_span_label(binding_span, "replace this binding");
|
||||
help_span.push_span_label(inner_then_pat.span, "with this pattern");
|
||||
diag.span_help(help_span, "the outer pattern can be modified to include the inner pattern");
|
||||
},
|
||||
);
|
||||
|
@ -11,7 +11,7 @@ use rustc_ast::token::CommentKind;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::{Applicability, Handler, SuggestionStyle};
|
||||
use rustc_errors::{Applicability, Handler, MultiSpan, SuggestionStyle};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{AnonConst, Expr};
|
||||
@ -25,7 +25,7 @@ use rustc_session::parse::ParseSess;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{BytePos, FilePathMapping, MultiSpan, SourceMap, Span};
|
||||
use rustc_span::source_map::{BytePos, FilePathMapping, SourceMap, Span};
|
||||
use rustc_span::{sym, FileName, Pos};
|
||||
use std::io;
|
||||
use std::ops::Range;
|
||||
@ -621,7 +621,19 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
||||
let filename = FileName::anon_source_code(&code);
|
||||
|
||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let emitter = EmitterWriter::new(Box::new(io::sink()), None, false, false, false, None, false);
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
|
||||
let emitter = EmitterWriter::new(
|
||||
Box::new(io::sink()),
|
||||
None,
|
||||
None,
|
||||
fallback_bundle,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
let handler = Handler::with_emitter(false, None, Box::new(emitter));
|
||||
let sess = ParseSess::with_span_handler(handler, sm);
|
||||
|
||||
|
@ -3,7 +3,7 @@ use clippy_utils::{higher, peel_blocks_with_stmt, SpanlessEq};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{lang_items::LangItem, BinOpKind, Expr, ExprKind, QPath};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
@ -82,14 +82,6 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||
|
||||
// Get the variable name
|
||||
let var_name = ares_path.segments[0].ident.name.as_str();
|
||||
const INT_TYPES: [LangItem; 5] = [
|
||||
LangItem::I8,
|
||||
LangItem::I16,
|
||||
LangItem::I32,
|
||||
LangItem::I64,
|
||||
LangItem::Isize
|
||||
];
|
||||
|
||||
match cond_num_val.kind {
|
||||
ExprKind::Lit(ref cond_lit) => {
|
||||
// Check if the constant is zero
|
||||
@ -105,8 +97,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||
if name.ident.as_str() == "MIN";
|
||||
if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id);
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(const_id);
|
||||
let mut int_ids = INT_TYPES.iter().filter_map(|&ty| cx.tcx.lang_items().require(ty).ok());
|
||||
if int_ids.any(|int_id| int_id == impl_id);
|
||||
if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
|
||||
if cx.tcx.type_of(impl_id).is_integral();
|
||||
then {
|
||||
print_lint_and_sugg(cx, var_name, expr)
|
||||
}
|
||||
@ -118,8 +110,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||
if name.ident.as_str() == "min_value";
|
||||
if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id);
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(func_id);
|
||||
let mut int_ids = INT_TYPES.iter().filter_map(|&ty| cx.tcx.lang_items().require(ty).ok());
|
||||
if int_ids.any(|int_id| int_id == impl_id);
|
||||
if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
|
||||
if cx.tcx.type_of(impl_id).is_integral();
|
||||
then {
|
||||
print_lint_and_sugg(cx, var_name, expr)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{can_move_expr_to_closure, is_trait_method, path_to_local, path_to_local_id, CaptureKind};
|
||||
use if_chain::if_chain;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{Applicability, MultiSpan};
|
||||
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
||||
use rustc_hir::{Block, Expr, ExprKind, HirId, HirIdSet, Local, Mutability, Node, PatKind, Stmt, StmtKind};
|
||||
use rustc_lint::LateContext;
|
||||
@ -14,7 +14,7 @@ use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
use rustc_span::Span;
|
||||
|
||||
const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
|
||||
|
||||
@ -102,7 +102,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
|
||||
|
||||
// Suggest replacing iter_call with iter_replacement, and removing stmt
|
||||
let mut span = MultiSpan::from_span(method_name.ident.span);
|
||||
span.push_span_label(iter_call.span, "the iterator could be used here instead".into());
|
||||
span.push_span_label(iter_call.span, "the iterator could be used here instead");
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
super::NEEDLESS_COLLECT,
|
||||
|
@ -273,7 +273,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
|
||||
}
|
||||
return false; // no need to walk further *on the variable*
|
||||
}
|
||||
Res::Def(DefKind::Static | DefKind::Const, ..) => {
|
||||
Res::Def(DefKind::Static (_)| DefKind::Const, ..) => {
|
||||
if index_used_directly {
|
||||
self.indexed_directly.insert(
|
||||
seqvar.segments[0].ident.name,
|
||||
|
@ -104,7 +104,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
|
||||
Res::Local(hir_id) => {
|
||||
self.ids.insert(hir_id);
|
||||
},
|
||||
Res::Def(DefKind::Static, def_id) => {
|
||||
Res::Def(DefKind::Static(_), def_id) => {
|
||||
let mutable = self.cx.tcx.is_mutable_static(def_id);
|
||||
self.def_ids.insert(def_id, mutable);
|
||||
},
|
||||
|
@ -93,7 +93,7 @@ pub(super) fn check<'tcx>(
|
||||
},
|
||||
hir::ExprKind::Path(ref p) => matches!(
|
||||
cx.qpath_res(p, arg.hir_id),
|
||||
hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _)
|
||||
hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static(_), _)
|
||||
),
|
||||
_ => false,
|
||||
}
|
||||
|
@ -48,12 +48,11 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir
|
||||
"to_os_string" => is_diag_item_method(cx, method_def_id, sym::OsStr),
|
||||
"to_owned" => is_diag_trait_item(cx, method_def_id, sym::ToOwned),
|
||||
"to_path_buf" => is_diag_item_method(cx, method_def_id, sym::Path),
|
||||
"to_vec" => {
|
||||
cx.tcx
|
||||
.impl_of_method(method_def_id)
|
||||
.map(|impl_did| Some(impl_did) == cx.tcx.lang_items().slice_alloc_impl())
|
||||
== Some(true)
|
||||
},
|
||||
"to_vec" => cx
|
||||
.tcx
|
||||
.impl_of_method(method_def_id)
|
||||
.filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none())
|
||||
.is_some(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -2488,7 +2488,6 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
||||
Some(("err", [recv], err_span)) => err_expect::check(cx, expr, recv, msrv, span, err_span),
|
||||
_ => expect_used::check(cx, expr, recv),
|
||||
},
|
||||
|
||||
("extend", [arg]) => {
|
||||
string_extend_chars::check(cx, expr, recv, arg);
|
||||
extend_with_drain::check(cx, expr, recv, arg);
|
||||
@ -2630,7 +2629,6 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
||||
unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
|
||||
},
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -12,13 +12,13 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
|
||||
if count <= 1;
|
||||
if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
|
||||
let lang_items = cx.tcx.lang_items();
|
||||
if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id);
|
||||
if cx.tcx.impl_trait_ref(impl_id).is_none();
|
||||
let self_ty = cx.tcx.type_of(impl_id);
|
||||
if self_ty.is_slice() || self_ty.is_str();
|
||||
then {
|
||||
// Ignore empty slice and string literals when used with a literal count.
|
||||
if matches!(self_arg.kind, ExprKind::Array([]))
|
||||
|| matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
|
||||
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
|
||||
"the resulting iterator will always return `None`")
|
||||
} else {
|
||||
(format!("`{}` called with `1` split", method_name),
|
||||
if lang_items.slice_impl() == Some(impl_id) {
|
||||
if self_ty.is_slice() {
|
||||
"the resulting iterator will always return the entire slice followed by `None`"
|
||||
} else {
|
||||
"the resulting iterator will always return the entire string followed by `None`"
|
||||
|
@ -148,7 +148,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
|
||||
|
||||
if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv.as_ref()) {
|
||||
if cx.tcx.is_const_fn_raw(def_id.to_def_id()) {
|
||||
cx.tcx.sess.span_err(span, &err);
|
||||
cx.tcx.sess.span_err(span, err.as_ref());
|
||||
}
|
||||
} else {
|
||||
span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`");
|
||||
|
@ -235,11 +235,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||
for (span, suggestion) in clone_spans {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
&snippet_opt(cx, span)
|
||||
snippet_opt(cx, span)
|
||||
.map_or(
|
||||
"change the call to".into(),
|
||||
|x| Cow::from(format!("change `{}` to", x)),
|
||||
),
|
||||
)
|
||||
.as_ref(),
|
||||
suggestion.into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
@ -264,11 +265,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||
for (span, suggestion) in clone_spans {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
&snippet_opt(cx, span)
|
||||
snippet_opt(cx, span)
|
||||
.map_or(
|
||||
"change the call to".into(),
|
||||
|x| Cow::from(format!("change `{}` to", x))
|
||||
),
|
||||
)
|
||||
.as_ref(),
|
||||
suggestion.into(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::expr_sig;
|
||||
use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{Applicability, MultiSpan};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::hir_id::HirIdMap;
|
||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||
@ -16,11 +16,11 @@ use rustc_hir::{
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::{self, AssocItems, AssocKind, Ty};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{sym, MultiSpan};
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
|
||||
@ -308,7 +308,6 @@ struct PtrArg<'tcx> {
|
||||
method_renames: &'static [(&'static str, &'static str)],
|
||||
ref_prefix: RefPrefix,
|
||||
deref_ty: DerefTy<'tcx>,
|
||||
deref_assoc_items: Option<(DefId, &'tcx AssocItems<'tcx>)>,
|
||||
}
|
||||
impl PtrArg<'_> {
|
||||
fn build_msg(&self) -> String {
|
||||
@ -411,7 +410,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||
if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id));
|
||||
|
||||
then {
|
||||
let (method_renames, deref_ty, deref_impl_id) = match cx.tcx.get_diagnostic_name(adt.did()) {
|
||||
let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) {
|
||||
Some(sym::Vec) => (
|
||||
[("clone", ".to_owned()")].as_slice(),
|
||||
DerefTy::Slice(
|
||||
@ -424,17 +423,14 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||
}),
|
||||
substs.type_at(0),
|
||||
),
|
||||
cx.tcx.lang_items().slice_impl()
|
||||
),
|
||||
Some(sym::String) => (
|
||||
[("clone", ".to_owned()"), ("as_str", "")].as_slice(),
|
||||
DerefTy::Str,
|
||||
cx.tcx.lang_items().str_impl()
|
||||
),
|
||||
Some(sym::PathBuf) => (
|
||||
[("clone", ".to_path_buf()"), ("as_path", "")].as_slice(),
|
||||
DerefTy::Path,
|
||||
None,
|
||||
),
|
||||
Some(sym::Cow) if mutability == Mutability::Not => {
|
||||
let ty_name = name.args
|
||||
@ -470,7 +466,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||
mutability,
|
||||
},
|
||||
deref_ty,
|
||||
deref_assoc_items: deref_impl_id.map(|id| (id, cx.tcx.associated_items(id))),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -606,16 +601,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
|
||||
},
|
||||
// If the types match check for methods which exist on both types. e.g. `Vec::len` and
|
||||
// `slice::len`
|
||||
ty::Adt(def, _)
|
||||
if def.did() == args.ty_did
|
||||
&& (i != 0
|
||||
|| self.cx.tcx.trait_of_item(id).is_some()
|
||||
|| !args.deref_assoc_items.map_or(false, |(id, items)| {
|
||||
items
|
||||
.find_by_name_and_kind(self.cx.tcx, name.ident, AssocKind::Fn, id)
|
||||
.is_some()
|
||||
})) =>
|
||||
{
|
||||
ty::Adt(def, _) if def.did() == args.ty_did => {
|
||||
set_skip_flag();
|
||||
},
|
||||
_ => (),
|
||||
|
@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)] // truncation very unlikely here
|
||||
#[must_use]
|
||||
fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span {
|
||||
fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u8) -> Span {
|
||||
let offset = u32::from(offset);
|
||||
let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
|
||||
let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
|
||||
|
@ -139,14 +139,20 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
|
||||
|
||||
fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
|
||||
let hir = cx.tcx.hir();
|
||||
if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) {
|
||||
if !matches!(
|
||||
hir.body_owner_kind(hir.body_owner_def_id(body.id())),
|
||||
BodyOwnerKind::Closure
|
||||
) {
|
||||
self.bindings.push(FxHashMap::default());
|
||||
}
|
||||
}
|
||||
|
||||
fn check_body_post(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
|
||||
let hir = cx.tcx.hir();
|
||||
if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) {
|
||||
if !matches!(
|
||||
hir.body_owner_kind(hir.body_owner_def_id(body.id())),
|
||||
BodyOwnerKind::Closure
|
||||
) {
|
||||
self.bindings.pop();
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use rustc_hir::{
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::ty::{self, subst::GenericArgKind};
|
||||
use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, subst::GenericArgKind, FloatTy};
|
||||
use rustc_semver::RustcVersion;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::Spanned;
|
||||
@ -889,7 +889,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
|
||||
}
|
||||
}
|
||||
},
|
||||
Res::Def(DefKind::Const | DefKind::Static, def_id) => {
|
||||
Res::Def(DefKind::Const | DefKind::Static(..), def_id) => {
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(def_id) {
|
||||
if let ItemKind::Const(.., body_id) | ItemKind::Static(.., body_id) = item.kind {
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
@ -934,7 +934,16 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
|
||||
// implementations of native types. Check lang items.
|
||||
let path_syms: Vec<_> = path.iter().map(|p| Symbol::intern(p)).collect();
|
||||
let lang_items = cx.tcx.lang_items();
|
||||
for item_def_id in lang_items.items().iter().flatten() {
|
||||
// This list isn't complete, but good enough for our current list of paths.
|
||||
let incoherent_impls = [
|
||||
SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32),
|
||||
SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64),
|
||||
SimplifiedTypeGen::SliceSimplifiedType,
|
||||
SimplifiedTypeGen::StrSimplifiedType,
|
||||
]
|
||||
.iter()
|
||||
.flat_map(|&ty| cx.tcx.incoherent_impls(ty));
|
||||
for item_def_id in lang_items.items().iter().flatten().chain(incoherent_impls) {
|
||||
let lang_item_path = cx.get_def_path(*item_def_id);
|
||||
if path_syms.starts_with(&lang_item_path) {
|
||||
if let [item] = &path_syms[lang_item_path.len()..] {
|
||||
|
@ -756,7 +756,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
|
||||
let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
|
||||
if match_type(self.cx, expr_ty, &paths::LINT);
|
||||
then {
|
||||
if let hir::def::Res::Def(DefKind::Static, _) = path.res {
|
||||
if let hir::def::Res::Def(DefKind::Static(..), _) = path.res {
|
||||
let lint_name = last_path_segment(qpath).ident.name;
|
||||
self.lints.push(sym_to_string(lint_name).to_ascii_lowercase());
|
||||
} else if let Some(local) = get_parent_local(self.cx, expr) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.61"
|
||||
version = "0.1.62"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
@ -8,10 +8,10 @@
|
||||
//! Thank you!
|
||||
//! ~The `INTERNAL_METADATA_COLLECTOR` lint
|
||||
|
||||
use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic};
|
||||
use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic, MultiSpan};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_lint::{LateContext, Lint, LintContext};
|
||||
use rustc_span::source_map::{MultiSpan, Span};
|
||||
use rustc_span::source_map::Span;
|
||||
use std::env;
|
||||
|
||||
fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
|
||||
|
@ -77,17 +77,22 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
|
||||
use rustc_hir::{
|
||||
def, lang_items, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr,
|
||||
ExprKind, FnDecl, ForeignItem, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local,
|
||||
MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Target,
|
||||
TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
|
||||
def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl,
|
||||
ForeignItem, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource,
|
||||
Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind,
|
||||
TraitRef, TyKind, UnOp,
|
||||
};
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::ty as rustc_ty;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||
use rustc_middle::ty::binding::BindingMode;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{
|
||||
ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
|
||||
PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
|
||||
};
|
||||
use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture};
|
||||
use rustc_middle::ty::{FloatTy, IntTy, UintTy};
|
||||
use rustc_semver::RustcVersion;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
@ -455,14 +460,6 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
|
||||
/// Resolves a def path like `std::vec::Vec`.
|
||||
/// This function is expensive and should be used sparingly.
|
||||
pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
||||
macro_rules! try_res {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Some(e) => e,
|
||||
None => return Res::Err,
|
||||
}
|
||||
};
|
||||
}
|
||||
fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Option<Res> {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
|
||||
@ -479,11 +476,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn find_primitive(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
|
||||
if let Some(&(index, Target::Impl)) = lang_items::ITEM_REFS.get(&Symbol::intern(name)) {
|
||||
tcx.lang_items().items()[index]
|
||||
} else {
|
||||
None
|
||||
fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
|
||||
let single = |ty| tcx.incoherent_impls(ty).iter().copied();
|
||||
let empty = || [].iter().copied();
|
||||
match name {
|
||||
"bool" => single(BoolSimplifiedType),
|
||||
"char" => single(CharSimplifiedType),
|
||||
"str" => single(StrSimplifiedType),
|
||||
"array" => single(ArraySimplifiedType),
|
||||
"slice" => single(SliceSimplifiedType),
|
||||
// FIXME: rustdoc documents these two using just `pointer`.
|
||||
//
|
||||
// Maybe this is something we should do here too.
|
||||
"const_ptr" => single(PtrSimplifiedType(Mutability::Not)),
|
||||
"mut_ptr" => single(PtrSimplifiedType(Mutability::Mut)),
|
||||
"isize" => single(IntSimplifiedType(IntTy::Isize)),
|
||||
"i8" => single(IntSimplifiedType(IntTy::I8)),
|
||||
"i16" => single(IntSimplifiedType(IntTy::I16)),
|
||||
"i32" => single(IntSimplifiedType(IntTy::I32)),
|
||||
"i64" => single(IntSimplifiedType(IntTy::I64)),
|
||||
"i128" => single(IntSimplifiedType(IntTy::I128)),
|
||||
"usize" => single(UintSimplifiedType(UintTy::Usize)),
|
||||
"u8" => single(UintSimplifiedType(UintTy::U8)),
|
||||
"u16" => single(UintSimplifiedType(UintTy::U16)),
|
||||
"u32" => single(UintSimplifiedType(UintTy::U32)),
|
||||
"u64" => single(UintSimplifiedType(UintTy::U64)),
|
||||
"u128" => single(UintSimplifiedType(UintTy::U128)),
|
||||
"f32" => single(FloatSimplifiedType(FloatTy::F32)),
|
||||
"f64" => single(FloatSimplifiedType(FloatTy::F64)),
|
||||
_ => empty(),
|
||||
}
|
||||
}
|
||||
fn find_crate(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
|
||||
@ -502,30 +523,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
||||
_ => return Res::Err,
|
||||
};
|
||||
let tcx = cx.tcx;
|
||||
let first = try_res!(
|
||||
find_primitive(tcx, base)
|
||||
.or_else(|| find_crate(tcx, base))
|
||||
.and_then(|id| item_child_by_name(tcx, id, first))
|
||||
);
|
||||
let starts = find_primitive(tcx, base)
|
||||
.chain(find_crate(tcx, base))
|
||||
.filter_map(|id| item_child_by_name(tcx, id, first));
|
||||
|
||||
let last = path
|
||||
.iter()
|
||||
.copied()
|
||||
// for each segment, find the child item
|
||||
.try_fold(first, |res, segment| {
|
||||
let def_id = res.def_id();
|
||||
if let Some(item) = item_child_by_name(tcx, def_id, segment) {
|
||||
Some(item)
|
||||
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
|
||||
// it is not a child item so check inherent impl items
|
||||
tcx.inherent_impls(def_id)
|
||||
.iter()
|
||||
.find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
try_res!(last).expect_non_local()
|
||||
for first in starts {
|
||||
let last = path
|
||||
.iter()
|
||||
.copied()
|
||||
// for each segment, find the child item
|
||||
.try_fold(first, |res, segment| {
|
||||
let def_id = res.def_id();
|
||||
if let Some(item) = item_child_by_name(tcx, def_id, segment) {
|
||||
Some(item)
|
||||
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
|
||||
// it is not a child item so check inherent impl items
|
||||
tcx.inherent_impls(def_id)
|
||||
.iter()
|
||||
.find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(last) = last {
|
||||
return last;
|
||||
}
|
||||
}
|
||||
|
||||
Res::Err
|
||||
}
|
||||
|
||||
/// Convenience function to get the `DefId` of a trait by path.
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2022-03-24"
|
||||
channel = "nightly-2022-04-07"
|
||||
components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
@ -165,9 +165,12 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
// Separate the output with an empty line
|
||||
eprintln!();
|
||||
|
||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
|
||||
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
|
||||
rustc_errors::ColorConfig::Auto,
|
||||
None,
|
||||
None,
|
||||
fallback_bundle,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
@ -178,8 +181,8 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
// a .span_bug or .bug call has already printed what
|
||||
// it wants to print.
|
||||
if !info.payload().is::<rustc_errors::ExplicitBug>() {
|
||||
let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
|
||||
handler.emit_diagnostic(&d);
|
||||
let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
|
||||
handler.emit_diagnostic(&mut d);
|
||||
}
|
||||
|
||||
let version_info = rustc_tools_util::get_version_info!();
|
||||
@ -191,7 +194,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
];
|
||||
|
||||
for note in &xs {
|
||||
handler.note_without_error(note);
|
||||
handler.note_without_error(note.as_ref());
|
||||
}
|
||||
|
||||
// If backtraces are enabled, also print the query stack
|
||||
|
@ -46,11 +46,6 @@ LL | | report_in_external_macro: true
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/check_clippy_version_attribute.rs:1:9
|
||||
|
|
||||
LL | #![deny(clippy::internal)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::missing_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
|
||||
= help: please use a `clippy::version` attribute, see `doc/adding_lints.md`
|
||||
= note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
fn main() {
|
||||
let s = String::from("String");
|
||||
s.as_bytes().get(3);
|
||||
let _ = s.as_bytes().get(3);
|
||||
let _ = &s.as_bytes().get(3);
|
||||
s[..].as_bytes().get(3);
|
||||
let _ = s[..].as_bytes().get(3);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
fn main() {
|
||||
let s = String::from("String");
|
||||
s.bytes().nth(3);
|
||||
let _ = s.bytes().nth(3);
|
||||
let _ = &s.bytes().nth(3);
|
||||
s[..].bytes().nth(3);
|
||||
let _ = s[..].bytes().nth(3);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: called `.bytes().nth()` on a `String`
|
||||
--> $DIR/bytes_nth.rs:8:5
|
||||
--> $DIR/bytes_nth.rs:8:13
|
||||
|
|
||||
LL | s.bytes().nth(3);
|
||||
| ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
|
||||
LL | let _ = s.bytes().nth(3);
|
||||
| ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
|
||||
|
|
||||
= note: `-D clippy::bytes-nth` implied by `-D warnings`
|
||||
|
||||
@ -13,10 +13,10 @@ LL | let _ = &s.bytes().nth(3);
|
||||
| ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
|
||||
|
||||
error: called `.bytes().nth()` on a `str`
|
||||
--> $DIR/bytes_nth.rs:10:5
|
||||
--> $DIR/bytes_nth.rs:10:13
|
||||
|
|
||||
LL | s[..].bytes().nth(3);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`
|
||||
LL | let _ = s[..].bytes().nth(3);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
10
tests/ui/crashes/ice-5497.stderr
Normal file
10
tests/ui/crashes/ice-5497.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: this operation will panic at runtime
|
||||
--> $DIR/ice-5497.rs:9:22
|
||||
|
|
||||
LL | const OOB: i32 = [1][1] + T::OOB;
|
||||
| ^^^^^^ index out of bounds: the length is 1 but the index is 1
|
||||
|
|
||||
= note: `#[deny(unconditional_panic)]` on by default
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -6,16 +6,16 @@ fn main() {
|
||||
let s = [1, 2, 3];
|
||||
let v = vec![1, 2, 3];
|
||||
|
||||
s.get(0);
|
||||
let _ = s.get(0);
|
||||
// Should be replaced by s.get(0)
|
||||
|
||||
s.get(2);
|
||||
let _ = s.get(2);
|
||||
// Should be replaced by s.get(2)
|
||||
|
||||
v.get(5);
|
||||
let _ = v.get(5);
|
||||
// Should be replaced by v.get(5)
|
||||
|
||||
v.get(0);
|
||||
let _ = v.get(0);
|
||||
// Should be replaced by v.get(0)
|
||||
|
||||
let o = Some(5);
|
||||
|
@ -6,16 +6,16 @@ fn main() {
|
||||
let s = [1, 2, 3];
|
||||
let v = vec![1, 2, 3];
|
||||
|
||||
s.iter().next();
|
||||
let _ = s.iter().next();
|
||||
// Should be replaced by s.get(0)
|
||||
|
||||
s[2..].iter().next();
|
||||
let _ = s[2..].iter().next();
|
||||
// Should be replaced by s.get(2)
|
||||
|
||||
v[5..].iter().next();
|
||||
let _ = v[5..].iter().next();
|
||||
// Should be replaced by v.get(5)
|
||||
|
||||
v.iter().next();
|
||||
let _ = v.iter().next();
|
||||
// Should be replaced by v.get(0)
|
||||
|
||||
let o = Some(5);
|
||||
|
@ -1,28 +1,28 @@
|
||||
error: using `.iter().next()` on an array
|
||||
--> $DIR/iter_next_slice.rs:9:5
|
||||
--> $DIR/iter_next_slice.rs:9:13
|
||||
|
|
||||
LL | s.iter().next();
|
||||
| ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)`
|
||||
LL | let _ = s.iter().next();
|
||||
| ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)`
|
||||
|
|
||||
= note: `-D clippy::iter-next-slice` implied by `-D warnings`
|
||||
|
||||
error: using `.iter().next()` on a Slice without end index
|
||||
--> $DIR/iter_next_slice.rs:12:5
|
||||
--> $DIR/iter_next_slice.rs:12:13
|
||||
|
|
||||
LL | s[2..].iter().next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)`
|
||||
LL | let _ = s[2..].iter().next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)`
|
||||
|
||||
error: using `.iter().next()` on a Slice without end index
|
||||
--> $DIR/iter_next_slice.rs:15:5
|
||||
--> $DIR/iter_next_slice.rs:15:13
|
||||
|
|
||||
LL | v[5..].iter().next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)`
|
||||
LL | let _ = v[5..].iter().next();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)`
|
||||
|
||||
error: using `.iter().next()` on an array
|
||||
--> $DIR/iter_next_slice.rs:18:5
|
||||
--> $DIR/iter_next_slice.rs:18:13
|
||||
|
|
||||
LL | v.iter().next();
|
||||
| ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)`
|
||||
LL | let _ = v.iter().next();
|
||||
| ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user