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:
commit
7c21f91b15
@ -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]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
@ -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| {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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()),
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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, "..");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
|
||||
}
|
||||
|
||||
match kind {
|
||||
FnKind::ItemFn(.., header, _) => {
|
||||
FnKind::ItemFn(.., header) => {
|
||||
if header.abi != Abi::Rust {
|
||||
return;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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, ¯o_line.sf)
|
||||
&& Lrc::ptr_eq(&unsafe_line.sf, ¯o_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.
|
||||
|
@ -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
|
||||
);
|
||||
},
|
||||
|
@ -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);
|
||||
|
@ -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! {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)?;
|
||||
|
@ -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(..)
|
||||
|
@ -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"]
|
||||
|
@ -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,
|
||||
|
10
tests/ui/crashes/ice-96721.rs
Normal file
10
tests/ui/crashes/ice-96721.rs
Normal file
@ -0,0 +1,10 @@
|
||||
macro_rules! foo {
|
||||
() => {
|
||||
"bar.rs"
|
||||
};
|
||||
}
|
||||
|
||||
#[path = foo!()] //~ ERROR malformed `path` attribute
|
||||
mod abc {}
|
||||
|
||||
fn main() {}
|
8
tests/ui/crashes/ice-96721.stderr
Normal file
8
tests/ui/crashes/ice-96721.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -95,4 +95,7 @@ trait FooIter: Iterator<Item = Foo> {
|
||||
}
|
||||
}
|
||||
|
||||
// This should not lint
|
||||
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
|
||||
|
||||
fn main() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -79,4 +79,7 @@ where
|
||||
u: U,
|
||||
}
|
||||
|
||||
// This should not lint
|
||||
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
|
||||
|
||||
fn main() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
Loading…
x
Reference in New Issue
Block a user