Auto merge of #8788 - flip1995:rustup, r=xFrednet,flip1995

Rustup

r? `@ghost`

changelog: move trait_duplication_in_bounds and type_repetition_in_bounds to nursery temporarily. This could already be reverted before the release. Check the Clippy in the Rust repo beta branch when writing this changelog.
This commit is contained in:
bors 2022-05-05 13:12:09 +00:00
commit 7c21f91b15
62 changed files with 319 additions and 279 deletions

View File

@ -10,7 +10,7 @@ indoc = "1.0"
itertools = "0.10.1"
opener = "0.5"
shell-escape = "0.1"
tempfile = "3.3"
tempfile = "3.2"
walkdir = "2.3"
[features]

View File

@ -6,7 +6,7 @@ use clippy_utils::msrvs;
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use clippy_utils::{extract_msrv_attr, meets_msrv};
use if_chain::if_chain;
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MacArgs, MacArgsEq, MetaItemKind, NestedMetaItem};
use rustc_errors::Applicability;
use rustc_hir::{
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
@ -593,6 +593,10 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
};
if attr.style == AttrStyle::Outer {
if let MacArgs::Eq(_, MacArgsEq::Ast(expr)) = &attr_item.args
&& !matches!(expr.kind, rustc_ast::ExprKind::Lit(..)) {
return;
}
if attr_item.args.inner_tokens().is_empty() || !is_present_in_source(cx, attr.span) {
return;
}

View File

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_data_structures::intern::Interned;
use rustc_hir::{Expr, ExprKind, PathSegment};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
@ -56,8 +55,8 @@ fn check_case_sensitive_file_extension_comparison(ctx: &LateContext<'_>, expr: &
ty::Str => {
return Some(span);
},
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) => {
if ctx.tcx.is_diagnostic_item(sym::String, did) {
ty::Adt(def, _) => {
if ctx.tcx.is_diagnostic_item(sym::String, def.did()) {
return Some(span);
}
},

View File

@ -82,7 +82,7 @@ impl CognitiveComplexity {
if rust_cc > self.limit.limit() {
let fn_span = match kind {
FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
FnKind::Closure => {
let header_span = body_span.with_hi(decl.output.span().lo());
let pos = snippet_opt(cx, header_span).and_then(|snip| {

View File

@ -240,7 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
}
},
hir::ItemKind::Impl(ref impl_) => {
hir::ItemKind::Impl(impl_) => {
self.in_trait_impl = impl_.of_trait.is_some();
},
hir::ItemKind::Trait(_, unsafety, ..) => {
@ -622,7 +622,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fallback_bundle =
rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
let emitter = EmitterWriter::new(
Box::new(io::sink()),
None,

View File

@ -260,7 +260,7 @@ impl LateLintPass<'_> for EnumVariantNames {
}
// The `module_name_repetitions` lint should only trigger if the item has the module in its
// name. Having the same name is accepted.
if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() {
if cx.tcx.visibility(item.def_id).is_public() && item_camel.len() > mod_camel.len() {
let matching = count_match_start(mod_camel, &item_camel);
let rmatching = count_match_end(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();

View File

@ -78,7 +78,10 @@ impl LateLintPass<'_> for ExhaustiveItems {
if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
then {
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
if v.fields().iter().any(|f| !f.vis.node.is_pub()) {
if v.fields().iter().any(|f| {
let def_id = cx.tcx.hir().local_def_id(f.hir_id);
!cx.tcx.visibility(def_id).is_public()
}) {
// skip structs with private fields
return;
}

View File

@ -20,7 +20,7 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = must_use_attr(attrs);
if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind {
if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
let is_public = cx.access_levels.is_exported(item.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
if let Some(attr) = attr {
@ -105,12 +105,7 @@ fn check_needless_must_use(
fn_header_span,
"this unit-returning function has a `#[must_use]` attribute",
|diag| {
diag.span_suggestion(
attr.span,
"remove the attribute",
"".into(),
Applicability::MachineApplicable,
);
diag.span_suggestion(attr.span, "remove the attribute", "", Applicability::MachineApplicable);
},
);
} else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {

View File

@ -17,8 +17,8 @@ pub(super) fn check_fn<'tcx>(
hir_id: hir::HirId,
) {
let unsafety = match kind {
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety,
intravisit::FnKind::Method(_, sig) => sig.header.unsafety,
intravisit::FnKind::Closure => return,
};

View File

@ -14,7 +14,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
use super::RESULT_UNIT_ERR;
pub(super) fn check_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
if let hir::ItemKind::Fn(ref sig, ref _generics, _) = item.kind {
if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind {
let is_public = cx.access_levels.is_exported(item.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
if is_public {

View File

@ -26,9 +26,8 @@ pub(super) fn check_fn(
header: hir::FnHeader { abi: Abi::Rust, .. },
..
},
_,
)
| intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => check_arg_number(
| intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }) => check_arg_number(
cx,
decl,
span.with_hi(decl.output.span().hi()),

View File

@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
}
match item.kind {
ItemKind::Impl(ref impl_) => {
ItemKind::Impl(impl_) => {
let mut vis = ImplicitHasherTypeVisitor::new(cx);
vis.visit_ty(impl_.self_ty);
@ -155,7 +155,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
);
}
},
ItemKind::Fn(ref sig, ref generics, body_id) => {
ItemKind::Fn(ref sig, generics, body_id) => {
let body = cx.tcx.hir().body(body_id);
for ty in sig.decl.inputs {

View File

@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
fn get_impl_span(cx: &LateContext<'_>, id: LocalDefId) -> Option<Span> {
let id = cx.tcx.hir().local_def_id_to_hir_id(id);
if let Node::Item(&Item {
kind: ItemKind::Impl(ref impl_item),
kind: ItemKind::Impl(impl_item),
span,
..
}) = cx.tcx.hir().get(id)

View File

@ -28,6 +28,8 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(strings::STRING_LIT_AS_BYTES),
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(transmute::USELESS_TRANSMUTE),
LintId::of(use_self::USE_SELF),

View File

@ -84,8 +84,6 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
LintId::of(strings::STRING_ADD_ASSIGN),
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
LintId::of(types::LINKEDLIST),
LintId::of(types::OPTION_OPTION),

View File

@ -10,7 +10,7 @@ use rustc_hir::FnRetTy::Return;
use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier,
TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
@ -85,9 +85,9 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
impl<'tcx> LateLintPass<'tcx> for Lifetimes {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Fn(ref sig, ref generics, id) = item.kind {
if let ItemKind::Fn(ref sig, generics, id) = item.kind {
check_fn_inner(cx, sig.decl, Some(id), None, generics, item.span, true);
} else if let ItemKind::Impl(ref impl_) = item.kind {
} else if let ItemKind::Impl(impl_) = item.kind {
report_extra_impl_lifetimes(cx, impl_);
}
}
@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
sig.decl,
Some(id),
None,
&item.generics,
item.generics,
item.span,
report_extra_lifetimes,
);
@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
TraitFn::Required(sig) => (None, Some(sig)),
TraitFn::Provided(id) => (Some(id), None),
};
check_fn_inner(cx, sig.decl, body, trait_sig, &item.generics, item.span, true);
check_fn_inner(cx, sig.decl, body, trait_sig, item.generics, item.span, true);
}
}
}
@ -135,7 +135,7 @@ fn check_fn_inner<'tcx>(
span: Span,
report_extra_lifetimes: bool,
) {
if span.from_expansion() || has_where_lifetimes(cx, &generics.where_clause) {
if span.from_expansion() || has_where_lifetimes(cx, generics) {
return;
}
@ -144,28 +144,35 @@ fn check_fn_inner<'tcx>(
.iter()
.filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
for typ in types {
for bound in typ.bounds {
let mut visitor = RefVisitor::new(cx);
walk_param_bound(&mut visitor, bound);
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
return;
for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
if pred.in_where_clause {
// has_where_lifetimes checked that this predicate contains no lifetime.
continue;
}
if let GenericBound::Trait(ref trait_ref, _) = *bound {
let params = &trait_ref
.trait_ref
.path
.segments
.last()
.expect("a path must have at least one segment")
.args;
if let Some(params) = *params {
let lifetimes = params.args.iter().filter_map(|arg| match arg {
GenericArg::Lifetime(lt) => Some(lt),
_ => None,
});
for bound in lifetimes {
if bound.name != LifetimeName::Static && !bound.is_elided() {
return;
for bound in pred.bounds {
let mut visitor = RefVisitor::new(cx);
walk_param_bound(&mut visitor, bound);
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
return;
}
if let GenericBound::Trait(ref trait_ref, _) = *bound {
let params = &trait_ref
.trait_ref
.path
.segments
.last()
.expect("a path must have at least one segment")
.args;
if let Some(params) = *params {
let lifetimes = params.args.iter().filter_map(|arg| match arg {
GenericArg::Lifetime(lt) => Some(lt),
_ => None,
});
for bound in lifetimes {
if bound.name != LifetimeName::Static && !bound.is_elided() {
return;
}
}
}
}
@ -326,9 +333,7 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
let mut allowed_lts = FxHashSet::default();
for par in named_generics.iter() {
if let GenericParamKind::Lifetime { .. } = par.kind {
if par.bounds.is_empty() {
allowed_lts.insert(RefLt::Named(par.name.ident().name));
}
allowed_lts.insert(RefLt::Named(par.name.ident().name));
}
}
allowed_lts.insert(RefLt::Unnamed);
@ -449,8 +454,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
/// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
/// reason about elision.
fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereClause<'_>) -> bool {
for predicate in where_clause.predicates {
fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) -> bool {
for predicate in generics.predicates {
match *predicate {
WherePredicate::RegionPredicate(..) => return true,
WherePredicate::BoundPredicate(ref pred) => {
@ -565,7 +570,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
.collect();
let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, hs);
walk_generics(&mut checker, &impl_.generics);
walk_generics(&mut checker, impl_.generics);
if let Some(ref trait_ref) = impl_.of_trait {
walk_trait_ref(&mut checker, trait_ref);
}

View File

@ -59,7 +59,7 @@ pub(super) fn check<'tcx>(
if let Some(indexed_extent) = indexed_extent {
let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id);
let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
return;
}
@ -262,7 +262,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
match res {
Res::Local(hir_id) => {
let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id).unwrap();
if index_used_directly {
self.indexed_directly.insert(
seqvar.segments[0].ident.name,

View File

@ -168,14 +168,16 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
.operands
.iter()
.map(|(o, _)| match o {
InlineAsmOperand::In { expr, .. }
| InlineAsmOperand::InOut { expr, .. }
| InlineAsmOperand::Sym { expr } => never_loop_expr(expr, main_loop_id),
InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
never_loop_expr(expr, main_loop_id)
},
InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id),
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id)
},
InlineAsmOperand::Const { .. } => NeverLoopResult::Otherwise,
InlineAsmOperand::Const { .. }
| InlineAsmOperand::SymFn { .. }
| InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
})
.fold(NeverLoopResult::Otherwise, combine_both),
ExprKind::Struct(_, _, None)

View File

@ -177,9 +177,10 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
&& let [.., name] = p.segments
&& let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res
&& name.ident.as_str().starts_with('_')
&& let Some(variant_id) = cx.tcx.parent(id)
&& let Some(enum_id) = cx.tcx.parent(variant_id)
{
let variant_id = cx.tcx.parent(id);
let enum_id = cx.tcx.parent(variant_id);
self.constructed_enum_variants.insert((enum_id, variant_id));
}
}

View File

@ -40,10 +40,8 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
};
let lhs_val = lhs_const.int_value(cx, ty)?;
let rhs_val = rhs_const.int_value(cx, ty)?;
let rhs_bound = match range_end {
RangeEnd::Included => EndBound::Included(rhs_val),
RangeEnd::Excluded => EndBound::Excluded(rhs_val),

View File

@ -139,7 +139,7 @@ fn find_sugg_for_if_let<'tcx>(
PatKind::TupleStruct(ref qpath, [sub_pat], _) => {
if let PatKind::Wild = sub_pat.kind {
let res = cx.typeck_results().qpath_res(qpath, check_pat.hir_id);
let Some(id) = res.opt_def_id().and_then(|ctor_id| cx.tcx.parent(ctor_id)) else { return };
let Some(id) = res.opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id)) else { return };
let lang_items = cx.tcx.lang_items();
if Some(id) == lang_items.result_ok_variant() {
("is_ok()", try_get_generic_ty(op_ty, 0).unwrap_or(op_ty))

View File

@ -42,7 +42,7 @@ pub(crate) trait BindInsteadOfMap {
fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
let item_id = cx.tcx.parent(variant_id)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}({})`, which is a no-op",
cx.tcx.item_name(item_id),
@ -53,7 +53,7 @@ pub(crate) trait BindInsteadOfMap {
fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
let item_id = cx.tcx.parent(variant_id)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
cx.tcx.item_name(item_id),
@ -145,7 +145,7 @@ pub(crate) trait BindInsteadOfMap {
if_chain! {
if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM);
if Some(adt.did()) == cx.tcx.parent(vid);
if adt.did() == cx.tcx.parent(vid);
then {} else { return false; }
}
@ -182,7 +182,7 @@ pub(crate) trait BindInsteadOfMap {
fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
if let Ok(variant_id) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM) {
return cx.tcx.parent(id) == Some(variant_id);
return cx.tcx.parent(id) == variant_id;
}
}
false

View File

@ -19,7 +19,7 @@ pub(super) fn check(
if_chain! {
if let Some(args) = method_chain_args(info.chain, chain_methods);
if let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind;
if let Some(id) = path_def_id(cx, fun).and_then(|ctor_id| cx.tcx.parent(ctor_id));
if let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id));
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let mut applicability = Applicability::MachineApplicable;

View File

@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(
let arg_snippet = snippet(cx, span, "..");
let body = cx.tcx.hir().body(id);
if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);
if let Some(id) = path_def_id(cx, func).and_then(|ctor_id| cx.tcx.parent(ctor_id));
if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let func_snippet = snippet(cx, arg_char.span, "..");

View File

@ -11,7 +11,7 @@ use if_chain::if_chain;
use rustc_ast::ast::{self, MetaItem, MetaItemKind};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
use rustc_middle::ty::{self, DefIdTree};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::Span;
@ -131,8 +131,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
hir::ItemKind::Fn(..) => {
// ignore main()
if it.ident.name == sym::main {
let def_key = cx.tcx.hir().def_key(it.def_id);
if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
let at_root = cx.tcx.local_parent(it.def_id) == CRATE_DEF_ID;
if at_root {
return;
}
}

View File

@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
let attrs = cx.tcx.hir().attrs(it.hir_id());
check_missing_inline_attrs(cx, attrs, it.span, desc);
},
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, _bounds, trait_items) => {
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => {
// note: we need to check if the trait is exported so we can't use
// `LateLintPass::check_trait_item` here.
for tit in trait_items {

View File

@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
}
match kind {
FnKind::ItemFn(.., header, _) => {
FnKind::ItemFn(.., header) => {
let attrs = cx.tcx.hir().attrs(hir_id);
if header.abi != Abi::Rust || requires_exact_signature(attrs) {
return;
@ -241,7 +241,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|x| Cow::from(format!("change `{}` to", x)),
)
.as_ref(),
suggestion.into(),
suggestion,
Applicability::Unspecified,
);
}
@ -271,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|x| Cow::from(format!("change `{}` to", x))
)
.as_ref(),
suggestion.into(),
suggestion,
Applicability::Unspecified,
);
}

View File

@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
if_chain! {
if let ExprKind::Lit(ref l) = lit.kind;
if consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
if cx.typeck_results().expr_ty(exp).is_integral();
then {

View File

@ -62,13 +62,13 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
if let hir::ItemKind::Impl(hir::Impl {
of_trait: None,
ref generics,
generics,
self_ty: impl_self_ty,
items,
..
}) = item.kind
{
for assoc_item in items {
for assoc_item in *items {
if assoc_item.kind == (hir::AssocItemKind::Fn { has_self: false }) {
let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
if in_external_macro(cx.sess(), impl_item.span) {

View File

@ -42,7 +42,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
if trait_ref.path.res.def_id() == eq_trait;
then {
for impl_item in impl_items {
for impl_item in *impl_items {
if impl_item.ident.name == sym::ne {
span_lint_hir(
cx,

View File

@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
}
match kind {
FnKind::ItemFn(.., header, _) => {
FnKind::ItemFn(.., header) => {
if header.abi != Abi::Rust {
return;
}

View File

@ -1,9 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Item, ItemKind, VisibilityKind};
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::hygiene::MacroKind;
declare_clippy_lint! {
@ -44,7 +46,7 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);
impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if_chain! {
if let VisibilityKind::Crate { .. } = item.vis.node;
if cx.tcx.visibility(item.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id());
if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false);
if is_not_macro_export(item);
then {
@ -57,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
&format!("pub(crate) {} inside private module", descr),
|diag| {
diag.span_suggestion(
item.vis.span,
item.vis_span,
"consider using",
"pub".to_string(),
Applicability::MachineApplicable,
@ -84,6 +86,8 @@ fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = path.res {
return false;
}
} else if let ItemKind::Macro(..) = item.kind {
return false;
}
true

View File

@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse {
) {
if_chain! {
// We are only interested in methods, not in functions or associated functions.
if matches!(kind, FnKind::Method(_, _, _));
if matches!(kind, FnKind::Method(_, _));
if let Some(fn_def) = cx.tcx.hir().opt_local_def_id(hir_id);
if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id());
// We don't want this method to be te implementation of a trait because the

View File

@ -50,110 +50,111 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
let mut map = FxHashMap::<Res, ExistingName>::default();
for item in cx.tcx.hir().items() {
if let ItemKind::Impl(Impl {
items,
of_trait,
self_ty,
..
}) = &item.kind
for id in cx.tcx.hir().items() {
if matches!(cx.tcx.hir().def_kind(id.def_id), DefKind::Impl)
&& let item = cx.tcx.hir().item(id)
&& let ItemKind::Impl(Impl {
items,
of_trait,
self_ty,
..
}) = &item.kind
&& let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
{
if let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind {
if !map.contains_key(res) {
map.insert(
*res,
ExistingName {
impl_methods: BTreeMap::new(),
trait_methods: BTreeMap::new(),
},
);
}
let existing_name = map.get_mut(res).unwrap();
match of_trait {
Some(trait_ref) => {
let mut methods_in_trait: BTreeSet<Symbol> = if_chain! {
if let Some(Node::TraitRef(TraitRef { path, .. })) =
cx.tcx.hir().find(trait_ref.hir_ref_id);
if let Res::Def(DefKind::Trait, did) = path.res;
then{
// FIXME: if
// `rustc_middle::ty::assoc::AssocItems::items` is public,
// we can iterate its keys instead of `in_definition_order`,
// which's more efficient
cx.tcx
.associated_items(did)
.in_definition_order()
.filter(|assoc_item| {
matches!(assoc_item.kind, AssocKind::Fn)
})
.map(|assoc_item| assoc_item.name)
.collect()
}else{
BTreeSet::new()
}
};
let mut check_trait_method = |method_name: Symbol, trait_method_span: Span| {
if let Some(impl_span) = existing_name.impl_methods.get(&method_name) {
span_lint_and_then(
cx,
SAME_NAME_METHOD,
*impl_span,
"method's name is the same as an existing method in a trait",
|diag| {
diag.span_note(
trait_method_span,
&format!("existing `{}` defined here", method_name),
);
},
);
}
if let Some(v) = existing_name.trait_methods.get_mut(&method_name) {
v.push(trait_method_span);
} else {
existing_name.trait_methods.insert(method_name, vec![trait_method_span]);
}
};
for impl_item_ref in (*items).iter().filter(|impl_item_ref| {
matches!(impl_item_ref.kind, rustc_hir::AssocItemKind::Fn { .. })
}) {
let method_name = impl_item_ref.ident.name;
methods_in_trait.remove(&method_name);
check_trait_method(method_name, impl_item_ref.span);
}
for method_name in methods_in_trait {
check_trait_method(method_name, item.span);
}
if !map.contains_key(res) {
map.insert(
*res,
ExistingName {
impl_methods: BTreeMap::new(),
trait_methods: BTreeMap::new(),
},
None => {
for impl_item_ref in (*items).iter().filter(|impl_item_ref| {
matches!(impl_item_ref.kind, rustc_hir::AssocItemKind::Fn { .. })
}) {
let method_name = impl_item_ref.ident.name;
let impl_span = impl_item_ref.span;
if let Some(trait_spans) = existing_name.trait_methods.get(&method_name) {
span_lint_and_then(
cx,
SAME_NAME_METHOD,
impl_span,
"method's name is the same as an existing method in a trait",
|diag| {
// TODO should we `span_note` on every trait?
// iterate on trait_spans?
diag.span_note(
trait_spans[0],
&format!("existing `{}` defined here", method_name),
);
},
);
}
existing_name.impl_methods.insert(method_name, impl_span);
);
}
let existing_name = map.get_mut(res).unwrap();
match of_trait {
Some(trait_ref) => {
let mut methods_in_trait: BTreeSet<Symbol> = if_chain! {
if let Some(Node::TraitRef(TraitRef { path, .. })) =
cx.tcx.hir().find(trait_ref.hir_ref_id);
if let Res::Def(DefKind::Trait, did) = path.res;
then{
// FIXME: if
// `rustc_middle::ty::assoc::AssocItems::items` is public,
// we can iterate its keys instead of `in_definition_order`,
// which's more efficient
cx.tcx
.associated_items(did)
.in_definition_order()
.filter(|assoc_item| {
matches!(assoc_item.kind, AssocKind::Fn)
})
.map(|assoc_item| assoc_item.name)
.collect()
}else{
BTreeSet::new()
}
},
}
};
let mut check_trait_method = |method_name: Symbol, trait_method_span: Span| {
if let Some(impl_span) = existing_name.impl_methods.get(&method_name) {
span_lint_and_then(
cx,
SAME_NAME_METHOD,
*impl_span,
"method's name is the same as an existing method in a trait",
|diag| {
diag.span_note(
trait_method_span,
&format!("existing `{}` defined here", method_name),
);
},
);
}
if let Some(v) = existing_name.trait_methods.get_mut(&method_name) {
v.push(trait_method_span);
} else {
existing_name.trait_methods.insert(method_name, vec![trait_method_span]);
}
};
for impl_item_ref in (*items).iter().filter(|impl_item_ref| {
matches!(impl_item_ref.kind, rustc_hir::AssocItemKind::Fn { .. })
}) {
let method_name = impl_item_ref.ident.name;
methods_in_trait.remove(&method_name);
check_trait_method(method_name, impl_item_ref.span);
}
for method_name in methods_in_trait {
check_trait_method(method_name, item.span);
}
},
None => {
for impl_item_ref in (*items).iter().filter(|impl_item_ref| {
matches!(impl_item_ref.kind, rustc_hir::AssocItemKind::Fn { .. })
}) {
let method_name = impl_item_ref.ident.name;
let impl_span = impl_item_ref.span;
if let Some(trait_spans) = existing_name.trait_methods.get(&method_name) {
span_lint_and_then(
cx,
SAME_NAME_METHOD,
impl_span,
"method's name is the same as an existing method in a trait",
|diag| {
// TODO should we `span_note` on every trait?
// iterate on trait_spans?
diag.span_note(
trait_spans[0],
&format!("existing `{}` defined here", method_name),
);
},
);
}
existing_name.impl_methods.insert(method_name, impl_span);
}
},
}
}
}

View File

@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for SerdeApi {
if did == visit_did {
let mut seen_str = None;
let mut seen_string = None;
for item in items {
for item in *items {
match item.ident.as_str() {
"visit_str" => seen_str = Some(item.span),
"visit_string" => seen_string = Some(item.span),

View File

@ -160,8 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool {
let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id());
let first_scope = scope_tree.var_scope(first);
let second_scope = scope_tree.var_scope(second);
let first_scope = scope_tree.var_scope(first).unwrap();
let second_scope = scope_tree.var_scope(second).unwrap();
scope_tree.is_subscope_of(second_scope, first_scope)
}

View File

@ -8,8 +8,7 @@ use rustc_data_structures::unhash::UnhashMap;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{
GenericBound, Generics, Item, ItemKind, Node, ParamName, Path, PathSegment, QPath, TraitItem, Ty, TyKind,
WherePredicate,
GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, QPath, TraitItem, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
@ -36,7 +35,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.38.0"]
pub TYPE_REPETITION_IN_BOUNDS,
pedantic,
nursery,
"Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
}
@ -66,7 +65,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.47.0"]
pub TRAIT_DUPLICATION_IN_BOUNDS,
pedantic,
nursery,
"Check if the same trait bounds are specified twice during a function declaration"
}
@ -91,10 +90,9 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) {
let Generics { where_clause, .. } = &item.generics;
let mut self_bounds_map = FxHashMap::default();
for predicate in where_clause.predicates {
for predicate in item.generics.predicates {
if_chain! {
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
if !bound_predicate.span.from_expansion();
@ -167,7 +165,7 @@ impl TraitBounds {
}
let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default();
let mut applicability = Applicability::MaybeIncorrect;
for bound in gen.where_clause.predicates {
for bound in gen.predicates {
if_chain! {
if let WherePredicate::BoundPredicate(ref p) = bound;
if p.bounds.len() as u64 <= self.max_trait_bounds;
@ -217,34 +215,23 @@ impl TraitBounds {
}
fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
if gen.span.from_expansion() || gen.params.is_empty() || gen.where_clause.predicates.is_empty() {
if gen.span.from_expansion() || gen.params.is_empty() || gen.predicates.is_empty() {
return;
}
let mut map = FxHashMap::default();
for param in gen.params {
if let ParamName::Plain(ref ident) = param.name {
let res = param
.bounds
.iter()
.filter_map(get_trait_info_from_bound)
.collect::<Vec<_>>();
map.insert(*ident, res);
}
}
for predicate in gen.where_clause.predicates {
let mut map = FxHashMap::<_, Vec<_>>::default();
for predicate in gen.predicates {
if_chain! {
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(segment) = segments.first();
if let Some(trait_resolutions_direct) = map.get(&segment.ident);
then {
for (res_where, _, _) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
if let Some((_, _, span_direct)) = trait_resolutions_direct
for (res_where, _, span_where) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
let trait_resolutions_direct = map.entry(segment.ident).or_default();
if let Some((_, span_direct)) = trait_resolutions_direct
.iter()
.find(|(res_direct, _, _)| *res_direct == res_where) {
.find(|(res_direct, _)| *res_direct == res_where) {
span_lint_and_help(
cx,
TRAIT_DUPLICATION_IN_BOUNDS,
@ -254,6 +241,9 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
"consider removing this trait bound",
);
}
else {
trait_resolutions_direct.push((res_where, span_where));
}
}
}
}

View File

@ -104,8 +104,10 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id:
if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
if synthetic;
if let Some(generics) = cx.tcx.hir().get_generics(id.owner);
if let Some(pred) = generics.bounds_for_param(did.expect_local()).next();
then {
Some(generic_param.bounds)
Some(pred.bounds)
} else {
None
}

View File

@ -1,13 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_lint_allowed;
use clippy_utils::source::walk_span_to_context;
use rustc_data_structures::sync::Lrc;
use rustc_hir::{Block, BlockCheckMode, UnsafeSource};
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{BytePos, Pos, SyntaxContext};
use std::rc::Rc;
declare_clippy_lint! {
/// ### What it does
@ -117,7 +117,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, block: &Block<'_>) -> bool {
// ^--------------------------------------------^
if let Ok(unsafe_line) = source_map.lookup_line(block.span.lo())
&& let Ok(macro_line) = source_map.lookup_line(ctxt.outer_expn_data().def_site.lo())
&& Rc::ptr_eq(&unsafe_line.sf, &macro_line.sf)
&& Lrc::ptr_eq(&unsafe_line.sf, &macro_line.sf)
&& let Some(src) = unsafe_line.sf.src.as_deref()
{
macro_line.line < unsafe_line.line && text_has_safety_comment(
@ -133,7 +133,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, block: &Block<'_>) -> bool {
&& let Some(body) = cx.enclosing_body
&& let Some(body_span) = walk_span_to_context(cx.tcx.hir().body(body).value.span, SyntaxContext::root())
&& let Ok(body_line) = source_map.lookup_line(body_span.lo())
&& Rc::ptr_eq(&unsafe_line.sf, &body_line.sf)
&& Lrc::ptr_eq(&unsafe_line.sf, &body_line.sf)
&& let Some(src) = unsafe_line.sf.src.as_deref()
{
// Get the text from the start of function body to the unsafe block.

View File

@ -34,7 +34,7 @@ pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
diag.span_suggestion(
local.pat.span,
"use a wild (`_`) binding",
"_".into(),
"_",
Applicability::MaybeIncorrect, // snippet
);
},

View File

@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
span: Span,
hir_id: HirId,
) {
if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }, _) = &fn_kind {
if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }) = &fn_kind {
if matches!(asyncness, IsAsync::Async) {
let mut visitor = AsyncFnVisitor { cx, found_await: false };
walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), span, hir_id);

View File

@ -8,6 +8,7 @@ use rustc_hir::{
Item, ItemKind, PathSegment, UseKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::kw;
use rustc_span::{sym, BytePos};
@ -115,7 +116,8 @@ impl LateLintPass<'_> for WildcardImports {
if is_test_module_or_function(cx.tcx, item) {
self.test_modules_deep = self.test_modules_deep.saturating_add(1);
}
if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
let module = cx.tcx.parent_module_from_def_id(item.def_id);
if cx.tcx.visibility(item.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
return;
}
if_chain! {

View File

@ -13,7 +13,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_parse::parser;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, BytePos, Span, DUMMY_SP};
use rustc_span::{sym, BytePos, InnerSpan, Span, DUMMY_SP};
declare_clippy_lint! {
/// ### What it does
@ -454,6 +454,7 @@ impl SimpleFormatArgs {
}
},
ArgumentNamed(n, _) => {
let n = Symbol::intern(n);
if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) {
match x.1.as_slice() {
// A non-empty format string has been seen already.
@ -495,7 +496,7 @@ impl Write {
let span = parser
.arg_places
.last()
.map_or(DUMMY_SP, |&x| str_lit.span.from_inner(x));
.map_or(DUMMY_SP, |&x| str_lit.span.from_inner(InnerSpan::new(x.start, x.end)));
if !self.in_debug_impl && arg.format.ty == "?" {
// FIXME: modify rustc's fmt string parser to give us the current span

View File

@ -688,7 +688,8 @@ pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool {
match (l, r) {
(Empty, Empty) => true,
(Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts),
(Eq(_, lt), Eq(_, rt)) => lt.kind == rt.kind,
(Eq(_, MacArgsEq::Ast(le)), Eq(_, MacArgsEq::Ast(re))) => eq_expr(le, re),
(Eq(_, MacArgsEq::Hir(ll)), Eq(_, MacArgsEq::Hir(rl))) => ll.kind == rl.kind,
_ => false,
}
}

View File

@ -179,7 +179,7 @@ impl Constant {
}
/// Parses a `LitKind` to a `Constant`.
pub fn lit_to_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
match *lit {
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
LitKind::Byte(b) => Constant::Int(u128::from(b)),
@ -301,7 +301,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
if is_direct_expn_of(e.span, "cfg").is_some() {
None
} else {
Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e)))
Some(lit_to_mir_constant(&lit.node, self.typeck_results.expr_ty_opt(e)))
}
},
ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),

View File

@ -681,8 +681,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(out_expr);
}
},
InlineAsmOperand::Const { anon_const } => self.hash_body(anon_const.body),
InlineAsmOperand::Sym { expr } => self.hash_expr(expr),
InlineAsmOperand::Const { anon_const } | InlineAsmOperand::SymFn { anon_const } => {
self.hash_body(anon_const.body);
},
InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
}
}
},

View File

@ -235,7 +235,7 @@ pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem
if let QPath::Resolved(_, path) = qpath {
if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) {
return cx.tcx.parent(ctor_id) == Some(item_id);
return cx.tcx.parent(ctor_id) == item_id;
}
}
}
@ -1690,7 +1690,7 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
/// Checks if the given function kind is an async function.
pub fn is_async_fn(kind: FnKind<'_>) -> bool {
matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness == IsAsync::Async)
}
/// Peels away all the compiler generated code surrounding the body of an async function,

View File

@ -23,7 +23,7 @@ pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
pub const CSTRING_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"];
pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
/// Preferably use the diagnostic item `sym::deref_method` where possible

View File

@ -211,7 +211,9 @@ fn check_statement<'tcx>(
StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body),
// just an assignment
StatementKind::SetDiscriminant { place, .. } => check_place(tcx, **place, span, body),
StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
check_place(tcx, **place, span, body)
},
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => {
check_operand(tcx, dst, span, body)?;

View File

@ -214,6 +214,7 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::Path(..)
| ast::ExprKind::Repeat(..)
| ast::ExprKind::Ret(..)
| ast::ExprKind::Yeet(..)
| ast::ExprKind::Struct(..)
| ast::ExprKind::Try(..)
| ast::ExprKind::TryBlock(..)

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2022-04-07"
channel = "nightly-2022-05-05"
components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]

View File

@ -165,7 +165,7 @@ 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 fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
rustc_errors::ColorConfig::Auto,
None,

View File

@ -0,0 +1,10 @@
macro_rules! foo {
() => {
"bar.rs"
};
}
#[path = foo!()] //~ ERROR malformed `path` attribute
mod abc {}
fn main() {}

View File

@ -0,0 +1,8 @@
error: malformed `path` attribute input
--> $DIR/ice-96721.rs:7:1
|
LL | #[path = foo!()] //~ ERROR malformed `path` attribute
| ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]`
error: aborting due to previous error

View File

@ -6,12 +6,6 @@ LL | fn unused_lt<'a>(x: u8) {}
|
= note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings`
error: this lifetime isn't used in the function definition
--> $DIR/extra_unused_lifetimes.rs:16:25
|
LL | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) {
| ^^
error: this lifetime isn't used in the function definition
--> $DIR/extra_unused_lifetimes.rs:41:10
|
@ -42,5 +36,5 @@ error: this lifetime isn't used in the function definition
LL | pub fn something<'c>() -> Self {
| ^^
error: aborting due to 7 previous errors
error: aborting due to 6 previous errors

View File

@ -108,12 +108,6 @@ error: explicit lifetimes given in parameter types where they could be elided (o
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> $DIR/needless_lifetimes.rs:307:5
|
LL | fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> $DIR/needless_lifetimes.rs:310:5
|
@ -192,5 +186,5 @@ error: explicit lifetimes given in parameter types where they could be elided (o
LL | fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 32 previous errors
error: aborting due to 31 previous errors

View File

@ -11,6 +11,19 @@ note: existing `foo` defined here
LL | fn foo() {}
| ^^^^^^^^^^^
error: method's name is the same as an existing method in a trait
--> $DIR/same_name_method.rs:34:13
|
LL | fn clone() {}
| ^^^^^^^^^^^^^
|
note: existing `clone` defined here
--> $DIR/same_name_method.rs:30:18
|
LL | #[derive(Clone)]
| ^^^^^
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
error: method's name is the same as an existing method in a trait
--> $DIR/same_name_method.rs:44:13
|
@ -47,18 +60,5 @@ note: existing `foo` defined here
LL | impl T1 for S {}
| ^^^^^^^^^^^^^^^^
error: method's name is the same as an existing method in a trait
--> $DIR/same_name_method.rs:34:13
|
LL | fn clone() {}
| ^^^^^^^^^^^^^
|
note: existing `clone` defined here
--> $DIR/same_name_method.rs:30:18
|
LL | #[derive(Clone)]
| ^^^^^
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 5 previous errors

View File

@ -95,4 +95,7 @@ trait FooIter: Iterator<Item = Foo> {
}
}
// This should not lint
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
fn main() {}

View File

@ -67,5 +67,13 @@ LL | Self: Iterator<Item = Foo>,
|
= help: consider removing this trait bound
error: aborting due to 8 previous errors
error: this trait bound is already specified in the where clause
--> $DIR/trait_duplication_in_bounds.rs:99:23
|
LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
| ^^^^^^^^^^
|
= help: consider removing this trait bound
error: aborting due to 9 previous errors

View File

@ -79,4 +79,7 @@ where
u: U,
}
// This should not lint
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
fn main() {}

View File

@ -19,5 +19,13 @@ LL | Self: Copy + Default + Ord,
|
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
error: aborting due to 2 previous errors
error: this type has already been used as a bound predicate
--> $DIR/type_repetition_in_bounds.rs:83:43
|
LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
| ^^^^^^^^^^
|
= help: consider combining the bounds: `impl AsRef<str>: AsRef<str> + AsRef<str>`
error: aborting due to 3 previous errors

View File

@ -1,8 +1,8 @@
error: unneeded unit return type
--> $DIR/unused_unit.rs:19:28
--> $DIR/unused_unit.rs:19:58
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()`
| ^^^^^^ help: remove the `-> ()`
|
note: the lint level is defined here
--> $DIR/unused_unit.rs:12:9
@ -10,18 +10,18 @@ note: the lint level is defined here
LL | #![deny(clippy::unused_unit)]
| ^^^^^^^^^^^^^^^^^^^
error: unneeded unit return type
--> $DIR/unused_unit.rs:19:28
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
--> $DIR/unused_unit.rs:20:18
|
LL | where G: Fn() -> () {
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
--> $DIR/unused_unit.rs:19:58
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
| ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
--> $DIR/unused_unit.rs:21:26
|