Auto merge of #8656 - flip1995:rustup, r=flip1995

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2022-04-07 15:30:27 +00:00
commit abc59bb914
34 changed files with 196 additions and 157 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()..] {

View File

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

View File

@ -1,6 +1,6 @@
[package]
name = "clippy_utils"
version = "0.1.61"
version = "0.1.62"
edition = "2021"
publish = false

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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