}
fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
- if let ExprKind::Lit(start_lit) = &start.peel_parens().kind
- && let ExprKind::Lit(end_lit) = &end.peel_parens().kind
+ if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
+ && let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
&& matches!(
- (&start_lit.kind, &end_lit.kind),
- (LitKind::Byte(b'a') | LitKind::Char('a'), LitKind::Byte(b'z') | LitKind::Char('z'))
- | (LitKind::Byte(b'A') | LitKind::Char('A'), LitKind::Byte(b'Z') | LitKind::Char('Z'))
+ (
+ LitKind::from_token_lit(start_token_lit),
+ LitKind::from_token_lit(end_token_lit),
+ ),
+ (
+ Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
+ Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
+ )
+ | (
+ Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
+ Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
+ )
)
&& !in_external_macro(cx.sess(), span)
{
(Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut));
// The `U` in `pointer::cast` have to be `Sized`
// as explained here: https://github.com/rust-lang/rust/issues/60602.
- if to_pointee_ty.is_sized(cx.tcx.at(expr.span), cx.param_env);
+ if to_pointee_ty.is_sized(cx.tcx, cx.param_env);
then {
let mut applicability = Applicability::MachineApplicable;
let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability);
of_trait: Some(ref trait_ref),
..
}) = item.kind;
- let ty = cx.tcx.type_of(item.def_id);
+ let ty = cx.tcx.type_of(item.owner_id);
if is_copy(cx, ty);
if let Some(trait_id) = trait_ref.trait_def_id();
if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
None,
&format!(
"consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
- cx.tcx.def_path_str(item.def_id.to_def_id())
+ cx.tcx.def_path_str(item.owner_id.to_def_id())
),
);
}
};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{symbol::sym, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
use std::collections::VecDeque;
},
Node::Item(&Item {
kind: ItemKind::Static(..) | ItemKind::Const(..),
- def_id,
+ owner_id,
span,
..
})
| Node::TraitItem(&TraitItem {
kind: TraitItemKind::Const(..),
- def_id,
+ owner_id,
span,
..
})
| Node::ImplItem(&ImplItem {
kind: ImplItemKind::Const(..),
- def_id,
+ owner_id,
span,
..
}) if span.ctxt() == ctxt => {
- let ty = cx.tcx.type_of(def_id.def_id);
+ let ty = cx.tcx.type_of(owner_id.def_id);
Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
},
Node::Item(&Item {
kind: ItemKind::Fn(..),
- def_id,
+ owner_id,
span,
..
})
| Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(..),
- def_id,
+ owner_id,
span,
..
})
| Node::ImplItem(&ImplItem {
kind: ImplItemKind::Fn(..),
- def_id,
+ owner_id,
span,
..
}) if span.ctxt() == ctxt => {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(def_id.to_def_id()).output());
+ .erase_late_bound_regions(cx.tcx.fn_sig(owner_id.to_def_id()).output());
Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx))
},
cx.typeck_results().node_type(ty.ty.hir_id),
binder_args,
))
- .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()),
+ .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
)
}
},
cx.typeck_results().node_type(ty.ty.hir_id),
binder_args,
))
- .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()),
+ .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
),
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
Position::ReborrowStable(precedence)
.iter()
.filter_map(|predicate| {
if let PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder()
- && trait_predicate.self_ty() == param_ty.to_ty(cx.tcx)
+ && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx)
{
Some(trait_predicate.trait_ref.def_id)
} else {
}
let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty);
- let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate);
+ let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
let infcx = cx.tcx.infer_ctxt().build();
infcx.predicate_must_hold_modulo_regions(&obligation)
})
fn position_for_result(self, cx: &LateContext<'tcx>) -> Position {
match (self.position, self.ty) {
(Position::ReborrowStable(precedence), Some(ty)) => {
- Position::DerefStable(precedence, ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env))
+ Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env))
},
(position, _) => position,
}
| ty::Closure(..)
| ty::Never
| ty::Tuple(_)
- | ty::Projection(_) => Position::DerefStable(
- precedence,
- ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()),
- )
- .into(),
+ | ty::Projection(_) => {
+ Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
+ },
};
}
}
self_ty,
..
}) = item.kind;
- if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived);
+ if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
if !item.span.from_expansion();
if let Some(def_id) = trait_ref.trait_def_id();
if cx.tcx.is_diagnostic_item(sym::Default, def_id);
if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
if let ImplItemKind::Fn(_, b) = &impl_item.kind;
if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
- if let Some(adt_def) = cx.tcx.type_of(item.def_id).ty_adt_def();
+ if let Some(adt_def) = cx.tcx.type_of(item.owner_id).ty_adt_def();
if let attrs = cx.tcx.hir().attrs(item.hir_id());
if !attrs.iter().any(|attr| attr.doc_str().is_some());
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
..
}) = item.kind
{
- let ty = cx.tcx.type_of(item.def_id);
- let is_automatically_derived = cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived);
+ let ty = cx.tcx.type_of(item.owner_id);
+ let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
match item.kind {
hir::ItemKind::Fn(ref sig, _, body_id) => {
- if !(is_entrypoint_fn(cx, item.def_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
+ if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
let body = cx.tcx.hir().body(body_id);
let mut fpu = FindPanicUnwrap {
cx,
- typeck_results: cx.tcx.typeck(item.def_id.def_id),
+ typeck_results: cx.tcx.typeck(item.owner_id.def_id),
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.def_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
}
},
hir::ItemKind::Impl(impl_) => {
(false, hir::Unsafety::Unsafe) => span_lint(
cx,
MISSING_SAFETY_DOC,
- cx.tcx.def_span(item.def_id),
+ cx.tcx.def_span(item.owner_id),
"docs for unsafe trait missing `# Safety` section",
),
(true, hir::Unsafety::Normal) => span_lint(
cx,
UNNECESSARY_SAFETY_DOC,
- cx.tcx.def_span(item.def_id),
+ cx.tcx.def_span(item.owner_id),
"docs for safe trait have unnecessary `# Safety` section",
),
_ => (),
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
if !in_external_macro(cx.tcx.sess, item.span) {
- lint_for_missing_headers(cx, item.def_id.def_id, sig, headers, None, None);
+ lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, None, None);
}
}
}
let body = cx.tcx.hir().body(body_id);
let mut fpu = FindPanicUnwrap {
cx,
- typeck_results: cx.tcx.typeck(item.def_id.def_id),
+ typeck_results: cx.tcx.typeck(item.owner_id.def_id),
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.def_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
}
}
}
body_id: Option<hir::BodyId>,
panic_span: Option<Span>,
) {
- if !cx.access_levels.is_exported(def_id) {
+ if !cx.effective_visibilities.is_exported(def_id) {
return; // Private functions do not require doc comments
}
false,
None,
false,
+ false,
);
let handler = Handler::with_emitter(false, None, Box::new(emitter));
let sess = ParseSess::with_span_handler(handler, sm);
}
}
},
- ExprKind::MethodCall(_, _, ref params, _) => {
- if let [ref param] = params[..] {
- if let ExprKind::Paren(_) = param.kind {
- span_lint(cx, DOUBLE_PARENS, param.span, msg);
+ ExprKind::MethodCall(ref call) => {
+ if let [ref arg] = call.args[..] {
+ if let ExprKind::Paren(_) = arg.kind {
+ span_lint(cx, DOUBLE_PARENS, arg.span, msg);
}
}
},
}
if let ItemKind::Enum(..) = item.kind {
- let ty = cx.tcx.type_of(item.def_id);
+ let ty = cx.tcx.type_of(item.owner_id);
let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
if adt.variants().is_empty() {
span_lint_and_help(
}
// The `module_name_repetitions` lint should only trigger if the item has the module in its
// name. Having the same name is accepted.
- if cx.tcx.visibility(item.def_id).is_public() && item_camel.len() > mod_camel.len() {
+ if cx.tcx.visibility(item.owner_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();
}
}
if let ItemKind::Enum(ref def, _) = item.kind {
- if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id.def_id)) {
+ if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id)) {
check_variant(cx, self.threshold, def, item_name, item.span);
}
}
use clippy_utils::diagnostics::span_lint_hir;
use rustc_hir::intravisit;
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
// be sure we have `self` parameter in this function
if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
trait_self_ty = Some(
- TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id())
+ TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id())
.self_ty()
.skip_binder(),
);
}
}
- fn fake_read(
- &mut self,
- _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
- _: FakeReadCause,
- _: HirId,
- ) {
- }
+ fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if_chain! {
if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind;
- if cx.access_levels.is_exported(item.def_id.def_id);
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id);
let attrs = cx.tcx.hir().attrs(item.hir_id());
if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
then {
// check for `impl From<???> for ..`
if_chain! {
if let hir::ItemKind::Impl(impl_) = &item.kind;
- if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
+ if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.def_id);
then {
lint_impl_body(cx, item.span, impl_.items);
let body = cx.tcx.hir().body(body_id);
let mut fpu = FindPanicUnwrap {
lcx: cx,
- typeck_results: cx.tcx.typeck(impl_item.id.def_id.def_id),
+ typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id),
result: Vec::new(),
};
fpu.visit_expr(body.value);
if format_args.format_string.parts == [kw::Empty];
if arg.format.is_default();
if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
- ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did()),
+ ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
ty::Str => true,
_ => false,
};
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{match_def_path, paths, peel_hir_expr_refs};
-use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_lint_pass!(FormatPushString => [FORMAT_PUSH_STRING]);
fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
- is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), sym::String)
+ is_type_lang_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), LangItem::String)
}
fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
if let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id {
&& let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
// `impl Into<target_ty> for self_ty`
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
- && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.def_id)
+ && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
&& cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
{
span_lint_and_then(
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_integer_literal;
use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::{def, Expr, ExprKind, PrimTy, QPath, TyKind};
+use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
/// Checks if a Ty is `String` or `&str`
fn is_ty_stringish(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
- is_type_diagnostic_item(cx, ty, sym::String) || is_type_diagnostic_item(cx, ty, sym::str)
+ is_type_lang_item(cx, ty, LangItem::String) || is_type_diagnostic_item(cx, ty, sym::str)
}
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
- let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
+ let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
- let is_public = cx.access_levels.is_exported(item.def_id.def_id);
+ let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
if let Some(attr) = attr {
check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.def_id.def_id,
+ item.owner_id.def_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this function could have a `#[must_use]` attribute",
);
pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
- let is_public = cx.access_levels.is_exported(item.def_id.def_id);
+ let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
let attrs = cx.tcx.hir().attrs(item.hir_id());
- let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
+ let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let Some(attr) = attr {
check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
- } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id.def_id).is_none()
+ } else if is_public
+ && !is_proc_macro(cx.sess(), attrs)
+ && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
{
check_must_use_candidate(
cx,
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.def_id.def_id,
+ item.owner_id.def_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
- let is_public = cx.access_levels.is_exported(item.def_id.def_id);
+ let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
let attrs = cx.tcx.hir().attrs(item.hir_id());
- let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
+ let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let Some(attr) = attr {
check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
} else if let hir::TraitFn::Provided(eid) = *eid {
sig.decl,
body,
item.span,
- item.def_id.def_id,
+ item.owner_id.def_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
|| mutates_static(cx, body)
|| in_external_macro(cx.sess(), item_span)
|| returns_unit(decl)
- || !cx.access_levels.is_exported(item_id)
+ || !cx.effective_visibilities.is_exported(item_id)
|| is_must_use_ty(cx, return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(item_id)))
{
return;
return false; // ignore `_` patterns
}
if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
- is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), pat.span, tys)
+ is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), tys)
} else {
false
}
static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
-fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool {
+fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool {
match *ty.kind() {
// primitive types are never mutable
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
ty::Adt(adt, substs) => {
- tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
+ tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
|| KNOWN_WRAPPER_TYS
.iter()
.any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
- && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
+ && substs.types().any(|ty| is_mutable_ty(cx, ty, tys))
},
- ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)),
- ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys),
+ ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
+ ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, tys),
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => {
- mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys)
+ mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys)
},
// calling something constitutes a side effect, so return true on all callables
// also never calls need not be used, so return true for them, too
let mut tys = DefIdSet::default();
for arg in args {
if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
- && is_mutable_ty(
- cx,
- cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
- arg.span,
- &mut tys,
- )
+ && is_mutable_ty(cx, cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), &mut tys)
&& is_mutated_static(arg)
{
return ControlFlow::Break(());
let mut tys = DefIdSet::default();
for arg in std::iter::once(receiver).chain(args.iter()) {
if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
- && is_mutable_ty(
- cx,
- cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
- arg.span,
- &mut tys,
- )
+ && is_mutable_ty(cx, cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), &mut tys)
&& is_mutated_static(arg)
{
return ControlFlow::Break(());
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
let body = cx.tcx.hir().body(eid);
- check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id.def_id);
+ check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.owner_id.def_id);
}
}
body: &'tcx hir::Body<'tcx>,
def_id: LocalDefId,
) {
- if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(def_id) {
+ if unsafety == hir::Unsafety::Normal && cx.effective_visibilities.is_exported(def_id) {
let raw_ptrs = iter_input_pats(decl, body)
.filter_map(|arg| raw_ptr_arg(cx, arg))
.collect::<HirIdSet>();
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) {
if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind
- && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span)
+ && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
{
- if cx.access_levels.is_exported(item.def_id.def_id) {
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
check_result_unit_err(cx, err_ty, fn_header_span);
}
pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) {
// Don't lint if method is a trait's implementation, we can't do anything about those
if let hir::ImplItemKind::Fn(ref sig, _) = item.kind
- && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span)
- && trait_ref_of_method(cx, item.def_id.def_id).is_none()
+ && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
+ && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
{
- if cx.access_levels.is_exported(item.def_id.def_id) {
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
check_result_unit_err(cx, err_ty, fn_header_span);
}
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) {
if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
- if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) {
- if cx.access_levels.is_exported(item.def_id.def_id) {
+ if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) {
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
check_result_unit_err(cx, err_ty, fn_header_span);
}
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
}
}
- if !cx.access_levels.is_exported(item.def_id.def_id) {
+ if !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
return;
}
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::ty::{implements_trait, is_type_lang_item};
use clippy_utils::{return_ty, trait_ref_of_method};
use if_chain::if_chain;
-use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
+use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));
// Check if return type is String
- if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);
+ if is_type_lang_item(cx, return_ty(cx, impl_item.hir_id()), LangItem::String);
// Filters instances of to_string which are required by a trait
- if trait_ref_of_method(cx, impl_item.def_id.def_id).is_none();
+ if trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none();
then {
show_lint(cx, impl_item);
.expect("Failed to get trait ID of `Display`!");
// Get the real type of 'self'
- let self_type = cx.tcx.fn_sig(item.def_id).input(0);
+ let self_type = cx.tcx.fn_sig(item.owner_id).input(0);
let self_type = self_type.skip_binder().peel_refs();
// Emit either a warning or an error
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind};
+use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind};
+use rustc_ast::token;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
impl IntPlusOne {
#[expect(clippy::cast_sign_loss)]
- fn check_lit(lit: &Lit, target_value: i128) -> bool {
- if let LitKind::Int(value, ..) = lit.kind {
+ fn check_lit(token_lit: token::Lit, target_value: i128) -> bool {
+ if let Ok(LitKind::Int(value, ..)) = LitKind::from_token_lit(token_lit) {
return value == (target_value as u128);
}
false
(BinOpKind::Ge, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) => {
match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
// `-1 + x`
- (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
+ (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => {
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
},
// `x - 1`
- (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+ (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
},
_ => None,
(BinOpKind::Ge, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) if rhskind.node == BinOpKind::Add => {
match (&rhslhs.kind, &rhsrhs.kind) {
// `y + 1` and `1 + y`
- (ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
+ (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => {
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
},
- (_, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+ (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
},
_ => None,
(BinOpKind::Le, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) if lhskind.node == BinOpKind::Add => {
match (&lhslhs.kind, &lhsrhs.kind) {
// `1 + x` and `x + 1`
- (ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
+ (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => {
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
},
- (_, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+ (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
},
_ => None,
(BinOpKind::Le, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) => {
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
// `-1 + y`
- (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
+ (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => {
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
},
// `y - 1`
- (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
+ (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => {
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
},
_ => None,
let name = item.ident.name.as_str();
if matches!(name, "iter" | "iter_mut") {
if let TraitItemKind::Fn(fn_sig, _) = &item.kind {
- check_sig(cx, name, fn_sig, item.def_id.def_id);
+ check_sig(cx, name, fn_sig, item.owner_id.def_id);
}
}
}
)
{
if let ImplItemKind::Fn(fn_sig, _) = &item.kind {
- check_sig(cx, name, fn_sig, item.def_id.def_id);
+ check_sig(cx, name, fn_sig, item.owner_id.def_id);
}
}
}
return;
}
if let ItemKind::Enum(ref def, _) = item.kind {
- let ty = cx.tcx.type_of(item.def_id);
+ let ty = cx.tcx.type_of(item.owner_id);
let Adt(adt, subst) = ty.kind() else {
panic!("already checked whether this is an enum")
};
if item.ident.name == sym::len;
if let ImplItemKind::Fn(sig, _) = &item.kind;
if sig.decl.implicit_self.has_implicit_self();
- if cx.access_levels.is_exported(item.def_id.def_id);
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id);
if matches!(sig.decl.output, FnRetTy::Return(_));
if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id());
if imp.of_trait.is_none();
if let Some(local_id) = ty_id.as_local();
let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
if !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id);
- if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.def_id).skip_binder());
+ if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).skip_binder());
then {
let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
item.ident.name == name
&& if let AssocItemKind::Fn { has_self } = item.kind {
- has_self && { cx.tcx.fn_sig(item.id.def_id).inputs().skip_binder().len() == 1 }
+ has_self && { cx.tcx.fn_sig(item.id.owner_id).inputs().skip_binder().len() == 1 }
} else {
false
}
}
}
- if cx.access_levels.is_exported(visited_trait.def_id.def_id)
+ if cx.effective_visibilities.is_exported(visited_trait.owner_id.def_id)
&& trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
{
let mut current_and_super_traits = DefIdSet::default();
- fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
+ fill_trait_set(visited_trait.owner_id.to_def_id(), &mut current_and_super_traits, cx);
let is_empty = sym!(is_empty);
let is_empty_method_found = current_and_super_traits
None,
None,
),
- Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => (
+ Some(is_empty) if !cx.effective_visibilities.is_exported(is_empty.def_id.expect_local()) => (
format!(
"{item_kind} `{}` has a public `len` method, but a private `is_empty` method",
item_name.as_str(),
let span = stmt.span.to(if_.span);
let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze(
- cx.tcx.at(span),
+ cx.tcx,
cx.param_env,
);
if has_interior_mutability { return; }
extern crate rustc_hir;
extern crate rustc_hir_analysis;
extern crate rustc_hir_pretty;
+extern crate rustc_hir_typeck;
extern crate rustc_index;
extern crate rustc_infer;
extern crate rustc_lexer;
walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
};
+use rustc_hir::lang_items;
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, PredicateOrigin, TraitFn,
- TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+ ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
+ TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
if let ImplItemKind::Fn(ref sig, id) = item.kind {
- let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id.def_id).is_none();
+ let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none();
check_fn_inner(
cx,
sig.decl,
occurrences
}
-const CLOSURE_TRAIT_BOUNDS: [LangItem; 3] = [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
-
/// A visitor usable for `rustc_front::visit::walk_ty()`.
struct RefVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
let trait_ref = &poly_tref.trait_ref;
- if CLOSURE_TRAIT_BOUNDS.iter().any(|&item| {
- self.cx
- .tcx
- .lang_items()
- .require(item)
- .map_or(false, |id| Some(id) == trait_ref.trait_def_id())
+ if let Some(id) = trait_ref.trait_def_id() && lang_items::FN_TRAITS.iter().any(|&item| {
+ self.cx.tcx.lang_items().get(item) == Some(id)
}) {
let mut sub_visitor = RefVisitor::new(self.cx);
sub_visitor.visit_trait_ref(trait_ref);
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
-use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
+use rustc_ast::ast::{Expr, ExprKind, LitKind};
+use rustc_ast::token;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
use std::iter;
declare_clippy_lint! {
return;
}
- if let ExprKind::Lit(ref lit) = expr.kind {
- self.check_lit(cx, lit);
+ if let ExprKind::Lit(lit) = expr.kind {
+ self.check_lit(cx, lit, expr.span);
}
}
}
}
}
- fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
+ fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
if_chain! {
- if let Some(src) = snippet_opt(cx, lit.span);
- if let Some(mut num_lit) = NumericLiteral::from_lit(&src, lit);
+ if let Some(src) = snippet_opt(cx, span);
+ if let Ok(lit_kind) = LitKind::from_token_lit(lit);
+ if let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind);
then {
- if !Self::check_for_mistyped_suffix(cx, lit.span, &mut num_lit) {
+ if !Self::check_for_mistyped_suffix(cx, span, &mut num_lit) {
return;
}
| WarningType::InconsistentDigitGrouping
| WarningType::UnusualByteGroupings
| WarningType::LargeDigitGroups => {
- !lit.span.from_expansion()
+ !span.from_expansion()
}
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => {
true
}
};
if should_warn {
- warning_type.display(num_lit.format(), cx, lit.span);
+ warning_type.display(num_lit.format(), cx, span);
}
}
}
return;
}
- if let ExprKind::Lit(ref lit) = expr.kind {
- self.check_lit(cx, lit);
+ if let ExprKind::Lit(lit) = expr.kind {
+ self.check_lit(cx, lit, expr.span);
}
}
}
pub fn new(threshold: u64) -> Self {
Self { threshold }
}
- fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
+ fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
// Lint integral literals.
if_chain! {
- if let LitKind::Int(val, _) = lit.kind;
- if let Some(src) = snippet_opt(cx, lit.span);
- if let Some(num_lit) = NumericLiteral::from_lit(&src, lit);
+ if let Ok(lit_kind) = LitKind::from_token_lit(lit);
+ if let LitKind::Int(val, _) = lit_kind;
+ if let Some(src) = snippet_opt(cx, span);
+ if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind);
if num_lit.radix == Radix::Decimal;
if val >= u128::from(self.threshold);
then {
let hex = format!("{val:#X}");
let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
- warning_type.display(num_lit.format(), cx, lit.span);
+ warning_type.display(num_lit.format(), cx, span);
});
}
}
use if_chain::if_chain;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind};
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::{mir::FakeReadCause, ty};
}
}
- fn fake_read(
- &mut self,
- _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
- _: FakeReadCause,
- _: HirId,
- ) {
- }
+ fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
impl MutatePairDelegate<'_, '_> {
"only a `panic!` in `if`-then statement",
|diag| {
// comments can be noisy, do not show them to the user
- diag.tool_only_span_suggestion(
- expr.span.shrink_to_lo(),
- "add comments back",
- comments,
- applicability);
+ if !comments.is_empty() {
+ diag.tool_only_span_suggestion(
+ expr.span.shrink_to_lo(),
+ "add comments back",
+ comments,
+ applicability);
+ }
diag.span_suggestion(
expr.span,
"try instead",
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
- HirId, IsAsync, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
+ HirId, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
) {
if_chain! {
if let Some(header) = kind.header();
- if header.asyncness == IsAsync::NotAsync;
+ if !header.asyncness.is_async();
// Check that this function returns `impl Future`
if let FnRetTy::Return(ret_ty) = decl.output;
if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
&& def.variants.len() > 1
{
let mut iter = def.variants.iter().filter_map(|v| {
- let id = cx.tcx.hir().local_def_id(v.id);
- (matches!(v.data, hir::VariantData::Unit(_))
+ let id = cx.tcx.hir().local_def_id(v.hir_id);
+ (matches!(v.data, hir::VariantData::Unit(..))
&& v.ident.as_str().starts_with('_')
- && is_doc_hidden(cx.tcx.hir().attrs(v.id)))
+ && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
.then_some((id, v.span))
});
if let Some((id, span)) = iter.next()
&& iter.next().is_none()
{
- self.potential_enums.push((item.def_id.def_id, id, item.span, span));
+ self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
}
}
}
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq};
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
&& let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
&& let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
- && cx.tcx.lang_items().require(hir::LangItem::IntoIterIntoIter).ok() == Some(into_iter_def_id)
+ && Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn()
&& match_acceptable_type(cx, left_expr, msrv)
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
suggest(cx, parent_expr, left_expr, target_expr);
&& let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id)
&& match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS)
&& let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
- && is_type_diagnostic_item(cx, ty, sym::String)
+ && is_type_lang_item(cx, ty, hir::LangItem::String)
&& SpanlessEq::new(cx).eq_expr(left_expr, str_expr) {
suggest(cx, parent_expr, left_expr, filter_expr);
}
let ty = cx.typeck_results().expr_ty(expr);
match ty.kind() {
ty::Adt(adt_def, _) if adt_def.is_struct() => {
- if !cx.tcx.is_diagnostic_item(sym::String, adt_def.did()) {
+ if cx.tcx.lang_items().string() != Some(adt_def.did()) {
return;
}
},
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{Arm, Expr, ExprKind, PatKind};
+use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::Span;
use super::MATCH_STR_CASE_MISMATCH;
if let Some(case_method) = get_case_method(segment_ident) {
let ty = self.cx.typeck_results().expr_ty(receiver).peel_refs();
- if is_type_diagnostic_item(self.cx, ty, sym::String) || ty.kind() == &ty::Str {
+ if is_type_lang_item(self.cx, ty, LangItem::String) || ty.kind() == &ty::Str {
self.case_method = Some(case_method);
return true;
}
const GOOD_METHOD_NAME: &'static str;
fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
- let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
+ let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}({})`, which is a no-op",
}
fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
- let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
+ let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
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 let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM);
if adt.did() == cx.tcx.parent(vid);
then {} else { return false; }
}
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) {
+ if let Some(variant_id) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM) {
return cx.tcx.parent(id) == variant_id;
}
}
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::sym;
use super::BYTES_COUNT_TO_LEN;
if let Some(impl_id) = cx.tcx.impl_of_method(bytes_id);
if cx.tcx.type_of(impl_id).is_str();
let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs();
- if ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String);
+ if ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String);
then {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
-use rustc_hir::Expr;
+use rustc_hir::{Expr, LangItem};
use rustc_lint::LateContext;
-use rustc_span::sym;
use super::BYTES_NTH;
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
let caller_type = if ty.is_str() {
"str"
- } else if is_type_diagnostic_item(cx, ty, sym::String) {
+ } else if is_type_lang_item(cx, ty, LangItem::String) {
"String"
} else {
return;
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::LateContext;
-use rustc_span::{source_map::Spanned, symbol::sym, Span};
+use rustc_span::{source_map::Spanned, Span};
use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
if ext_str.chars().skip(1).all(|c| c.is_uppercase() || c.is_ascii_digit())
|| ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit());
let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
- if recv_ty.is_str() || is_type_diagnostic_item(cx, recv_ty, sym::String);
+ if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
then {
span_lint_and_help(
cx,
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn};
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
if (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) && {
let arg_type = cx.typeck_results().expr_ty(receiver);
let base_type = arg_type.peel_refs();
- *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String)
+ *base_type.kind() == ty::Str || is_type_lang_item(cx, base_type, hir::LangItem::String)
} {
receiver
} else {
// converted to string.
fn requires_to_string(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
let arg_ty = cx.typeck_results().expr_ty(arg);
- if is_type_diagnostic_item(cx, arg_ty, sym::String) {
+ if is_type_lang_item(cx, arg_ty, hir::LangItem::String) {
return false;
}
if let ty::Ref(_, ty, ..) = arg_ty.kind() {
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::{is_type_diagnostic_item, walk_ptrs_ty_depth};
+use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth};
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
return true;
}
- if is_type_diagnostic_item(cx, ty, sym::String) {
+ if is_type_lang_item(cx, ty, hir::LangItem::String) {
return true;
}
}
} else {
let ty = cx.typeck_results().expr_ty(e);
- if is_type_diagnostic_item(cx, ty, sym::String)
+ if is_type_lang_item(cx, ty, LangItem::String)
|| (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, Ty::is_str))
|| (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, Ty::is_str))
{
Some(RepeatKind::String)
} else {
let ty = ty.peel_refs();
- (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)).then_some(RepeatKind::String)
+ (ty.is_str() || is_type_lang_item(cx, ty, LangItem::String)).then_some(RepeatKind::String)
}
}
}
if_chain! {
if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat);
- if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::String);
+ if is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String);
if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id);
let name = impl_item.ident.name.as_str();
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
- let self_ty = cx.tcx.type_of(item.def_id);
+ let self_ty = cx.tcx.type_of(item.owner_id);
let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind {
- let method_sig = cx.tcx.fn_sig(impl_item.def_id);
+ let method_sig = cx.tcx.fn_sig(impl_item.owner_id);
let method_sig = cx.tcx.erase_late_bound_regions(method_sig);
let first_arg_ty_opt = method_sig.inputs().iter().next().copied();
// if this impl block implements a trait, lint in trait definition instead
- if !implements_trait && cx.access_levels.is_exported(impl_item.def_id.def_id) {
+ if !implements_trait && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
// check missing trait implementations
for method_config in &TRAIT_METHODS {
if name == method_config.method_name
if sig.decl.implicit_self.has_implicit_self()
&& !(self.avoid_breaking_exported_api
- && cx.access_levels.is_exported(impl_item.def_id.def_id))
+ && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id))
&& let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next()
&& let Some(first_arg_ty) = first_arg_ty_opt
{
then {
let first_arg_span = first_arg_ty.span;
let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
- let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id())
+ let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
.self_ty()
.skip_binder();
wrong_self_convention::check(
if item.ident.name == sym::new;
if let TraitItemKind::Fn(_, _) = item.kind;
let ret_ty = return_ty(cx, item.hir_id());
- let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id())
+ let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
.self_ty()
.skip_binder();
if !ret_ty.contains(self_ty);
use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use clippy_utils::SpanlessEq;
use if_chain::if_chain;
use rustc_ast::LitKind;
-use rustc_hir::ExprKind;
+use rustc_hir::{ExprKind, LangItem};
use rustc_lint::LateContext;
-use rustc_span::sym;
use super::NO_EFFECT_REPLACE;
arg2: &'tcx rustc_hir::Expr<'_>,
) {
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
- if !(ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)) {
+ if !(ty.is_str() || is_type_lang_item(cx, ty, LangItem::String)) {
return;
}
use clippy_utils::consts::{constant_context, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
-use rustc_hir::Expr;
+use rustc_hir::{Expr, LangItem};
use rustc_lint::LateContext;
-use rustc_span::sym;
use super::REPEAT_ONCE;
format!("{}.to_vec()", snippet(cx, recv.span, r#""...""#)),
Applicability::MachineApplicable,
);
- } else if is_type_diagnostic_item(cx, ty, sym::String) {
+ } else if is_type_lang_item(cx, ty, LangItem::String) {
span_lint_and_sugg(
cx,
REPEAT_ONCE,
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::deref_closure_args;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{is_trait_method, strip_pat_refs};
use if_chain::if_chain;
use rustc_errors::Applicability;
else if search_method == "find" {
let is_string_or_str_slice = |e| {
let self_ty = cx.typeck_results().expr_ty(e).peel_refs();
- if is_type_diagnostic_item(cx, self_ty, sym::String) {
+ if is_type_lang_item(cx, self_ty, hir::LangItem::String) {
true
} else {
*self_ty.kind() == ty::Str
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::method_chain_args;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::symbol::sym;
use super::STRING_EXTEND_CHARS;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
- if !is_type_diagnostic_item(cx, obj_ty, sym::String) {
+ if !is_type_lang_item(cx, obj_ty, hir::LangItem::String) {
return;
}
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
} else {
""
}
- } else if is_type_diagnostic_item(cx, self_ty, sym::String) {
+ } else if is_type_lang_item(cx, self_ty, hir::LangItem::String) {
"&"
} else {
return;
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
use clippy_utils::{fn_def_id, get_parent_expr};
use rustc_errors::Applicability;
-use rustc_hir::{def_id::DefId, Expr, ExprKind, LangItem};
+use rustc_hir::{def_id::DefId, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_span::{sym, Symbol};
/// Returns true if the named method is `IntoIterator::into_iter`.
pub fn is_into_iter(cx: &LateContext<'_>, callee_def_id: DefId) -> bool {
- cx.tcx.lang_items().require(LangItem::IntoIterIntoIter) == Ok(callee_def_id)
+ Some(callee_def_id) == cx.tcx.lang_items().into_iter_fn()
}
-use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_diagnostic_item};
+use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_lang_item};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::LateContext;
use rustc_middle::ty::{Ref, Slice};
-use rustc_span::{sym, Span};
+use rustc_span::Span;
use super::UNNECESSARY_JOIN;
// the turbofish for collect is ::<Vec<String>>
if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind();
if let Slice(slice) = ref_type.kind();
- if is_type_diagnostic_item(cx, *slice, sym::String);
+ if is_type_lang_item(cx, *slice, LangItem::String);
// the argument for join is ""
if let ExprKind::Lit(spanned) = &join_arg.kind;
if let LitKind::Str(symbol, _) = spanned.node;
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
-use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
-use rustc_hir_analysis::check::{FnCtxt, Inherited};
+use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
+use rustc_hir_typeck::{FnCtxt, Inherited};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::mir::Mutability;
Node::Expr(parent_expr) => {
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
{
- if cx.tcx.lang_items().require(LangItem::IntoFutureIntoFuture) == Ok(callee_def_id) {
+ if Some(callee_def_id) == cx.tcx.lang_items().into_future_fn() {
return false;
}
if trait_predicates.any(|predicate| {
let predicate = EarlyBinder(predicate).subst(cx.tcx, new_subst);
- let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate);
+ let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
!cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
}) {
return false;
use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::ast::Lit;
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
+use rustc_span::Span;
use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
-pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
+pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffix: &str, sugg_type: &str) {
let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
return; // It's useless so shouldn't lint.
};
span_lint_and_sugg(
cx,
SEPARATED_LITERAL_SUFFIX,
- lit.span,
+ lit_span,
&format!("{sugg_type} type suffix should not be separated by an underscore"),
"remove the underscore",
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
span_lint_and_sugg(
cx,
UNSEPARATED_LITERAL_SUFFIX,
- lit.span,
+ lit_span,
&format!("{sugg_type} type suffix should be separated by an underscore"),
"add an underscore",
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
use clippy_utils::diagnostics::span_lint;
-use rustc_ast::ast::Lit;
use rustc_lint::EarlyContext;
+use rustc_span::Span;
use super::MIXED_CASE_HEX_LITERALS;
-pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: &str) {
+pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_snip: &str) {
let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
return; // It's useless so shouldn't lint.
};
span_lint(
cx,
MIXED_CASE_HEX_LITERALS,
- lit.span,
+ lit_span,
"inconsistent casing in hexadecimal literal",
);
break;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
+use rustc_ast::ast::{Expr, ExprKind, Generics, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
+use rustc_ast::token;
use rustc_ast::visit::FnKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
return;
}
- if let ExprKind::Lit(ref lit) = expr.kind {
- MiscEarlyLints::check_lit(cx, lit);
+ if let ExprKind::Lit(lit) = expr.kind {
+ MiscEarlyLints::check_lit(cx, lit, expr.span);
}
double_neg::check(cx, expr);
}
}
impl MiscEarlyLints {
- fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
+ fn check_lit(cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
// We test if first character in snippet is a number, because the snippet could be an expansion
// from a built-in macro like `line!()` or a proc-macro like `#[wasm_bindgen]`.
// Note that this check also covers special case that `line!()` is eagerly expanded by compiler.
// See <https://github.com/rust-lang/rust-clippy/issues/4507> for a regression.
// FIXME: Find a better way to detect those cases.
- let lit_snip = match snippet_opt(cx, lit.span) {
+ let lit_snip = match snippet_opt(cx, span) {
Some(snip) if snip.chars().next().map_or(false, |c| c.is_ascii_digit()) => snip,
_ => return,
};
- if let LitKind::Int(value, lit_int_type) = lit.kind {
+ let lit_kind = LitKind::from_token_lit(lit);
+ if let Ok(LitKind::Int(value, lit_int_type)) = lit_kind {
let suffix = match lit_int_type {
LitIntType::Signed(ty) => ty.name_str(),
LitIntType::Unsigned(ty) => ty.name_str(),
LitIntType::Unsuffixed => "",
};
- literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
+ literal_suffix::check(cx, span, &lit_snip, suffix, "integer");
if lit_snip.starts_with("0x") {
- mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
+ mixed_case_hex_literals::check(cx, span, suffix, &lit_snip);
} else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
// nothing to do
} else if value != 0 && lit_snip.starts_with('0') {
- zero_prefixed_literal::check(cx, lit, &lit_snip);
+ zero_prefixed_literal::check(cx, span, &lit_snip);
}
- } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
+ } else if let Ok(LitKind::Float(_, LitFloatType::Suffixed(float_ty))) = lit_kind {
let suffix = float_ty.name_str();
- literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
+ literal_suffix::check(cx, span, &lit_snip, suffix, "float");
}
}
}
use clippy_utils::diagnostics::span_lint_and_then;
-use rustc_ast::ast::Lit;
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
+use rustc_span::Span;
use super::ZERO_PREFIXED_LITERAL;
-pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str) {
+pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str) {
let trimmed_lit_snip = lit_snip.trim_start_matches(|c| c == '_' || c == '0');
span_lint_and_then(
cx,
ZERO_PREFIXED_LITERAL,
- lit.span,
+ lit_span,
"this is a decimal constant",
|diag| {
diag.span_suggestion(
- lit.span,
+ lit_span,
"if you mean to use a decimal constant, remove the `0` to avoid confusion",
trimmed_lit_snip.to_string(),
Applicability::MaybeIncorrect,
// do not advise to use octal form if the literal cannot be expressed in base 8.
if !lit_snip.contains(|c| c == '8' || c == '9') {
diag.span_suggestion(
- lit.span,
+ lit_span,
"if you mean to use an octal constant, use `0o`",
format!("0o{trimmed_lit_snip}"),
Applicability::MaybeIncorrect,
hir::ItemKind::Fn(..) => {
// ignore main()
if it.ident.name == sym::main {
- let at_root = cx.tcx.local_parent(it.def_id.def_id) == CRATE_DEF_ID;
+ let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;
if at_root {
return;
}
| hir::ItemKind::Use(..) => return,
};
- let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(it.hir_id());
if !is_from_proc_macro(cx, it) {
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
- let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
if !is_from_proc_macro(cx, trait_item) {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
// If the method is an impl for a trait, don't doc.
- if let Some(cid) = cx.tcx.associated_item(impl_item.def_id).impl_container(cx.tcx) {
+ if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) {
if cx.tcx.impl_trait_ref(cid).is_some() {
return;
}
return;
}
- let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
if !is_from_proc_macro(cx, impl_item) {
self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc);
}
fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
- let attrs = cx.tcx.hir().attrs(v.id);
+ let attrs = cx.tcx.hir().attrs(v.hir_id);
if !is_from_proc_macro(cx, v) {
self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant");
}
return;
}
- if !cx.access_levels.is_exported(it.def_id.def_id) {
+ if !cx.effective_visibilities.is_exported(it.owner_id.def_id) {
return;
}
match it.kind {
match tit_.kind {
hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
hir::TraitItemKind::Fn(..) => {
- if cx.tcx.impl_defaultness(tit.id.def_id).has_value() {
+ if cx.tcx.impl_defaultness(tit.id.owner_id).has_value() {
// trait method with default body needs inline in case
// an impl is not provided
let desc = "a default trait method";
}
// If the item being implemented is not exported, then we don't need #[inline]
- if !cx.access_levels.is_exported(impl_item.def_id.def_id) {
+ if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
return;
}
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => return,
};
- let assoc_item = cx.tcx.associated_item(impl_item.def_id);
+ let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
let container_id = assoc_item.container_id(cx.tcx);
let trait_def_id = match assoc_item.container {
TraitContainer => Some(container_id),
};
if let Some(trait_def_id) = trait_def_id {
- if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id.def_id) {
+ if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
// If a trait is being implemented for an item, and the
// trait is not exported, we don't need #[inline]
return;
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
- if trait_ref_of_method(cx, item.def_id.def_id).is_none() {
+ if trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
self.check_sig(cx, item.hir_id(), sig.decl);
}
}
let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
.iter()
.any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
- if is_keyed_type && self.is_interior_mutable_type(cx, substs.type_at(0), span) {
+ if is_keyed_type && self.is_interior_mutable_type(cx, substs.type_at(0)) {
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
}
}
/// Determines if a type contains interior mutability which would affect its implementation of
/// [`Hash`] or [`Ord`].
- fn is_interior_mutable_type<'tcx>(&self, cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
+ fn is_interior_mutable_type<'tcx>(&self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
match *ty.kind() {
- Ref(_, inner_ty, mutbl) => {
- mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty, span)
- },
- Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty, span),
+ Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty),
+ Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty),
Array(inner_ty, size) => {
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
- && self.is_interior_mutable_type(cx, inner_ty, span)
+ && self.is_interior_mutable_type(cx, inner_ty)
},
- Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty, span)),
+ Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty)),
Adt(def, substs) => {
// Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to
// that of their type parameters. Note: we don't include `HashSet` and `HashMap`
let is_box = Some(def_id) == cx.tcx.lang_items().owned_box();
if is_std_collection || is_box || self.ignore_mut_def_ids.contains(&def_id) {
// The type is mutable if any of its type parameters are
- substs.types().any(|ty| self.is_interior_mutable_type(cx, ty, span))
+ substs.types().any(|ty| self.is_interior_mutable_type(cx, ty))
} else {
!ty.has_escaping_bound_vars()
&& cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
- && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
+ && !ty.is_freeze(cx.tcx, cx.param_env)
}
},
_ => false,
"generally you want to avoid `&mut &mut _` if possible",
);
} else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() {
- if ty.peel_refs().is_sized(self.cx.tcx.at(expr.span), self.cx.param_env) {
+ if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) {
span_lint(
self.cx,
MUT_MUT,
let suggestions = assignments
.iter()
.flat_map(|assignment| {
- [
- assignment.span.until(assignment.rhs_span),
- assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()),
- ]
+ let mut spans = vec![assignment.span.until(assignment.rhs_span)];
+
+ if assignment.rhs_span.hi() != assignment.span.hi() {
+ spans.push(assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()));
+ }
+
+ spans
})
.map(|span| (span, String::new()))
.collect::<Vec<(Span, String)>>();
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::ptr::get_spans;
use clippy_utils::source::{snippet, snippet_opt};
-use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
+use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::{get_trait_def_id, is_self, paths};
use if_chain::if_chain;
use rustc_ast::ast::Attribute;
use rustc_hir::{
BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind,
};
-use rustc_hir::{HirIdMap, HirIdSet};
-use rustc_hir_analysis::expr_use_visitor as euv;
+use rustc_hir::{HirIdMap, HirIdSet, LangItem};
+use rustc_hir_typeck::expr_use_visitor as euv;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, TypeVisitable};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::kw;
-use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::misc::can_type_implement_copy;
if !is_self(arg);
if !ty.is_mutable_ptr();
if !is_copy(cx, ty);
- if ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env);
+ if ty.is_sized(cx.tcx, cx.param_env);
if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
if !implements_borrow_trait;
if !all_borrowable_trait;
}
}
- if is_type_diagnostic_item(cx, ty, sym::String) {
+ if is_type_lang_item(cx, ty, LangItem::String) {
if let Some(clone_spans) =
get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) {
diag.span_suggestion(
fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
- fn fake_read(
- &mut self,
- _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
- _: FakeReadCause,
- _: HirId,
- ) {
- }
+ fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
// can't be implemented for unsafe new
return;
}
- if cx.tcx.is_doc_hidden(impl_item.def_id.def_id) {
+ if cx.tcx.is_doc_hidden(impl_item.owner_id.def_id) {
// shouldn't be implemented when it is hidden in docs
return;
}
if_chain! {
if sig.decl.inputs.is_empty();
if name == sym::new;
- if cx.access_levels.is_reachable(impl_item.def_id.def_id);
+ if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id);
let self_def_id = cx.tcx.hir().get_parent_item(id);
let self_ty = cx.tcx.type_of(self_def_id);
if self_ty == return_ty(cx, id);
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{sym, InnerSpan, Span, DUMMY_SP};
+use rustc_span::{sym, InnerSpan, Span};
// FIXME: this is a correctness problem but there's no suitable
// warn-by-default category.
// since it works when a pointer indirection involves (`Cell<*const T>`).
// Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
// but I'm not sure whether it's a decent way, if possible.
- cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env)
+ cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env)
}
fn is_value_unfrozen_raw<'tcx>(
if let Some(of_trait_def_id) = of_trait_ref.trait_def_id();
if let Some(of_assoc_item) = cx
.tcx
- .associated_item(impl_item.def_id)
+ .associated_item(impl_item.owner_id)
.trait_item_def_id;
if cx
.tcx
if let Some(trait_id) = trait_ref.trait_def_id();
if send_trait == trait_id;
if hir_impl.polarity == ImplPolarity::Positive;
- if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
+ if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
if let self_ty = ty_trait_ref.self_ty();
if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
then {
return;
}
- if let ExprKind::Lit(lit) = &expr.kind {
- if matches!(lit.token_lit.kind, LitKind::Str) {
- check_lit(cx, &lit.token_lit, lit.span, true);
- } else if matches!(lit.token_lit.kind, LitKind::ByteStr) {
- check_lit(cx, &lit.token_lit, lit.span, false);
+ if let ExprKind::Lit(token_lit) = &expr.kind {
+ if matches!(token_lit.kind, LitKind::Str) {
+ check_lit(cx, token_lit, expr.span, true);
+ } else if matches!(token_lit.kind, LitKind::ByteStr) {
+ check_lit(cx, token_lit, expr.span, false);
}
}
}
// `skip_params` is either `0` or `1` to skip the `self` parameter in trait functions.
// It can't be renamed, and it can't be removed without removing it from multiple functions.
let (fn_id, fn_kind, skip_params) = match get_parent_node(cx.tcx, body.value.hir_id) {
- Some(Node::Item(i)) => (i.def_id.to_def_id(), FnKind::Fn, 0),
+ Some(Node::Item(i)) => (i.owner_id.to_def_id(), FnKind::Fn, 0),
Some(Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(ref sig, _),
- def_id,
+ owner_id,
..
})) => (
- def_id.to_def_id(),
+ owner_id.to_def_id(),
FnKind::TraitFn,
usize::from(sig.decl.implicit_self.has_implicit_self()),
),
Some(Node::ImplItem(&ImplItem {
kind: ImplItemKind::Fn(ref sig, _),
- def_id,
+ owner_id,
..
})) => {
#[allow(trivial_casts)]
- if let Some(Node::Item(item)) = get_parent_node(cx.tcx, def_id.into())
- && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.def_id)
- && let Some(trait_item_id) = cx.tcx.associated_item(def_id).trait_item_def_id
+ if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into())
+ && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
+ && let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id
{
(
trait_item_id,
usize::from(sig.decl.implicit_self.has_implicit_self()),
)
} else {
- (def_id.to_def_id(), FnKind::Fn, 0)
+ (owner_id.to_def_id(), FnKind::Fn, 0)
}
},
_ => return,
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_lint::LateContext;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::BorrowKind;
let rty = cx.typeck_results().expr_ty(rhs);
if_chain! {
if let Some((_, lang_item)) = binop_traits(op.node);
- if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
+ if let Some(trait_id) = cx.tcx.lang_items().get(lang_item);
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
if trait_ref_of_method(cx, parent_fn)
.map_or(true, |t| t.path.res.def_id() != trait_id);
if let ty::Adt(adt_def, _) = middle_ty.kind();
if let Some(local_did) = adt_def.did().as_local();
let item = cx.tcx.hir().expect_item(local_did);
- let middle_ty_id = item.def_id.to_def_id();
+ let middle_ty_id = item.owner_id.to_def_id();
if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
if let Res::Def(_, hir_ty_id) = path.res;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_direct_expn_of;
use if_chain::if_chain;
-use rustc_ast::ast::{Expr, ExprKind};
+use rustc_ast::ast::{Expr, ExprKind, MethodCall};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
impl EarlyLintPass for OptionEnvUnwrap {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if_chain! {
- if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind;
- if matches!(path_segment.ident.name, sym::expect | sym::unwrap);
+ if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind;
+ if matches!(seg.ident.name, sym::expect | sym::unwrap);
if let ExprKind::Call(caller, _) = &receiver.kind;
if is_direct_expn_of(caller.span, "option_env").is_some();
then {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if_chain! {
if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
- if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived);
+ if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
if trait_ref.path.res.def_id() == eq_trait;
then {
}
fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, def_id: LocalDefId, decl: &FnDecl<'_>, span: Option<Span>) {
- if self.avoid_breaking_exported_api && cx.access_levels.is_exported(def_id) {
+ if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}
}
if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind {
- self.check_poly_fn(cx, item.def_id.def_id, method_sig.decl, None);
+ self.check_poly_fn(cx, item.owner_id.def_id, method_sig.decl, None);
}
}
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use if_chain::if_chain;
-use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp};
+use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp};
+use rustc_ast::token;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
let mut arg = operand;
let mut all_odd = true;
- while let ExprKind::MethodCall(path_segment, receiver, _, _) = &arg.kind {
- let path_segment_str = path_segment.ident.name.as_str();
+ while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind {
+ let seg_str = seg.ident.name.as_str();
all_odd &= ALLOWED_ODD_FUNCTIONS
.iter()
- .any(|odd_function| **odd_function == *path_segment_str);
+ .any(|odd_function| **odd_function == *seg_str);
arg = receiver;
}
if_chain! {
if !all_odd;
if let ExprKind::Lit(lit) = &arg.kind;
- if let LitKind::Int(..) | LitKind::Float(..) = &lit.kind;
+ if let token::LitKind::Integer | token::LitKind::Float = &lit.kind;
then {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
check_mut_from_ref(cx, sig, None);
for arg in check_fn_args(
cx,
- cx.tcx.fn_sig(item.def_id).skip_binder().inputs(),
+ cx.tcx.fn_sig(item.owner_id).skip_binder().inputs(),
sig.decl.inputs,
&[],
)
let (item_id, sig, is_trait_item) = match parents.next() {
Some((_, Node::Item(i))) => {
if let ItemKind::Fn(sig, ..) = &i.kind {
- (i.def_id, sig, false)
+ (i.owner_id, sig, false)
} else {
return;
}
return;
}
if let ImplItemKind::Fn(sig, _) = &i.kind {
- (i.def_id, sig, false)
+ (i.owner_id, sig, false)
} else {
return;
}
},
Some((_, Node::TraitItem(i))) => {
if let TraitItemKind::Fn(sig, _) = &i.kind {
- (i.def_id, sig, true)
+ (i.owner_id, sig, true)
} else {
return;
}
substs.type_at(0),
),
),
- Some(sym::String) => (
+ _ if Some(adt.did()) == cx.tcx.lang_items().string() => (
[("clone", ".to_owned()"), ("as_str", "")].as_slice(),
DerefTy::Str,
),
.type_implements_trait(p.def_id, ty, p.substs, cx.param_env)
.must_apply_modulo_regions(),
ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new(
+ cx.tcx,
ObligationCause::dummy(),
cx.param_env,
cx.tcx.mk_predicate(Binder::bind_with_vars(
then {
let mut applicability = Applicability::MachineApplicable;
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
- let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx.at(caller.span), cx.param_env) &&
+ let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) &&
!matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
let sugg = if let Some(else_inner) = r#else {
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, walk_ptrs_ty_depth};
+use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{def_id, Body, FnDecl, HirId};
+use rustc_hir::{def_id, Body, FnDecl, HirId, LangItem};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty};
let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD)
|| match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD)
|| (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD)
- && is_type_diagnostic_item(cx, arg_ty, sym::String));
+ && is_type_lang_item(cx, arg_ty, LangItem::String));
let from_deref = !from_borrow
&& (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF)
if_chain! {
if let ast::ExprKind::Call(ref paren, _) = expr.kind;
if let ast::ExprKind::Paren(ref closure) = paren.kind;
- if let ast::ExprKind::Closure(_, _, ref r#async, _, ref decl, ref block, _) = closure.kind;
+ if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind;
then {
let mut visitor = ReturnVisitor::new();
- visitor.visit_expr(block);
+ visitor.visit_expr(body);
if !visitor.found_return {
span_lint_and_then(
cx,
expr.span,
"try not to call a closure in the expression where it is declared",
|diag| {
- if decl.inputs.is_empty() {
+ if fn_decl.inputs.is_empty() {
let app = Applicability::MachineApplicable;
- let mut hint = Sugg::ast(cx, block, "..");
+ let mut hint = Sugg::ast(cx, body, "..");
- if r#async.is_async() {
+ if asyncness.is_async() {
// `async x` is a syntax error, so it becomes `async { x }`
- if !matches!(block.kind, ast::ExprKind::Block(_, _)) {
+ if !matches!(body.kind, ast::ExprKind::Block(_, _)) {
hint = hint.blockify();
}
impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if_chain! {
- if cx.tcx.visibility(item.def_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id());
- if !cx.access_levels.is_exported(item.def_id.def_id) && self.is_exported.last() == Some(&false);
+ if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id());
+ if !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false);
if is_not_macro_export(item);
then {
let span = item.span.with_hi(item.ident.span.hi());
- let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
+ let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
span_lint_and_then(
cx,
REDUNDANT_PUB_CRATE,
}
if let ItemKind::Mod { .. } = item.kind {
- self.is_exported.push(cx.access_levels.is_exported(item.def_id.def_id));
+ self.is_exported
+ .push(cx.effective_visibilities.is_exported(item.owner_id.def_id));
}
}
if !in_external_macro(cx.sess(), span);
if decl.implicit_self.has_implicit_self();
// We only show this warning for public exported methods.
- if cx.access_levels.is_exported(fn_def);
+ if cx.effective_visibilities.is_exported(fn_def);
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
if !cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::must_use));
if cx.tcx.visibility(fn_def.to_def_id()).is_public();
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) {
if let TraitItemKind::Fn(ref sig, _) = item.kind {
- check_method(cx, sig.decl, item.def_id.def_id, item.span, item.hir_id());
+ check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.hir_id());
}
}
}
let mut map = FxHashMap::<Res, ExistingName>::default();
for id in cx.tcx.hir().items() {
- if matches!(cx.tcx.def_kind(id.def_id), DefKind::Impl)
+ if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl)
&& let item = cx.tcx.hir().item(id)
&& let ItemKind::Impl(Impl {
items,
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
- let self_ty = cx.tcx.type_of(item.def_id);
+ let self_ty = cx.tcx.type_of(item.owner_id);
let ret_ty = return_ty(cx, impl_item.hir_id());
// Do not check trait impls
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::{snippet, snippet_with_applicability};
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths};
use clippy_utils::{peel_blocks, SpanlessEq};
use if_chain::if_chain;
},
ExprKind::Index(target, _idx) => {
let e_ty = cx.typeck_results().expr_ty(target).peel_refs();
- if matches!(e_ty.kind(), ty::Str) || is_type_diagnostic_item(cx, e_ty, sym::String) {
+ if matches!(e_ty.kind(), ty::Str) || is_type_lang_item(cx, e_ty, LangItem::String) {
span_lint(
cx,
STRING_SLICE,
}
fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
- is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), sym::String)
+ is_type_lang_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), LangItem::String)
}
fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool {
if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
if path.ident.name == sym::to_string;
let ty = cx.typeck_results().expr_ty(self_arg);
- if is_type_diagnostic_item(cx, ty, sym::String);
+ if is_type_lang_item(cx, ty, LangItem::String);
then {
span_lint_and_help(
cx,
| (Await(_), Await(_))
| (Async(_, _, _), Async(_, _, _))
| (Block(_, _), Block(_, _))
- | (Closure(_, _, _, _, _, _, _), Closure(_, _, _, _, _, _, _))
+ | (Closure(_), Closure(_))
| (Match(_, _), Match(_, _))
| (Loop(_, _), Loop(_, _))
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
| (Unary(_, _), Unary(_, _))
| (Binary(_, _, _), Binary(_, _, _))
| (Tup(_), Tup(_))
- | (MethodCall(_, _, _, _), MethodCall(_, _, _, _))
+ | (MethodCall(_), MethodCall(_))
| (Call(_, _), Call(_, _))
| (ConstBlock(_), ConstBlock(_))
| (Array(_), Array(_))
if_chain! {
if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
- if let Ok(binop_trait_id) = cx.tcx.lang_items().require(binop_trait_lang);
- if let Ok(op_assign_trait_id) = cx.tcx.lang_items().require(op_assign_trait_lang);
+ if let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang);
+ if let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang);
// Check for more than one binary operation in the implemented function
// Linting when multiple operations are involved can result in false positives
(&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
]
.iter()
- .find(|&(ts, _)| ts.iter().any(|&t| Ok(trait_id) == cx.tcx.lang_items().require(t)));
+ .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t)));
if count_binops(body.value) == 1;
then {
span_lint(
None,
&format!(
"consider annotating `{}` with `#[repr(C)]` or another `repr` attribute",
- cx.tcx.def_path_str(item.def_id.to_def_id())
+ cx.tcx.def_path_str(item.owner_id.to_def_id())
),
);
}
use rustc_lint::LateContext;
use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
-use rustc_span::DUMMY_SP;
#[expect(clippy::too_many_lines)]
pub(super) fn check<'tcx>(
continue;
},
(&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _)
- if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
+ if !unsized_ty.is_sized(cx.tcx, cx.param_env) =>
{
(true, false)
},
(_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })))
- if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
+ if !unsized_ty.is_sized(cx.tcx, cx.param_env) =>
{
(false, true)
},
+use rustc_hir as hir;
use rustc_hir::Expr;
-use rustc_hir_analysis::check::{cast, FnCtxt, Inherited};
+use rustc_hir_typeck::{cast, FnCtxt, Inherited};
use rustc_lint::LateContext;
use rustc_middle::ty::{cast::CastKind, Ty};
use rustc_span::DUMMY_SP;
);
if let Ok(check) = cast::CastCheck::new(
- &fn_ctxt, e, from_ty, to_ty,
+ &fn_ctxt,
+ e,
+ from_ty,
+ to_ty,
// We won't show any error to the user, so we don't care what the span is here.
- DUMMY_SP, DUMMY_SP,
+ DUMMY_SP,
+ DUMMY_SP,
+ hir::Constness::NotConst,
) {
let res = check.do_check(&fn_ctxt);
fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Symbol> {
let param = qpath_generic_tys(qpath).next()?;
let id = path_def_id(cx, param)?;
- cx.tcx.get_diagnostic_name(id).filter(|&name| {
- matches!(
- name,
- sym::HashMap
- | sym::String
- | sym::Vec
- | sym::HashSet
- | sym::VecDeque
- | sym::LinkedList
- | sym::BTreeMap
- | sym::BTreeSet
- | sym::BinaryHeap
- )
- })
+ cx.tcx
+ .get_diagnostic_name(id)
+ .filter(|&name| {
+ matches!(
+ name,
+ sym::HashMap
+ | sym::Vec
+ | sym::HashSet
+ | sym::VecDeque
+ | sym::LinkedList
+ | sym::BTreeMap
+ | sym::BTreeSet
+ | sym::BinaryHeap
+ )
+ })
+ .or_else(|| {
+ cx.tcx
+ .lang_items()
+ .string()
+ .filter(|did| id == *did)
+ .map(|_| sym::String)
+ })
}
false
};
- let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(id));
+ let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(id));
self.check_fn_decl(
cx,
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
- let is_exported = cx.access_levels.is_exported(item.def_id.def_id);
+ let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
match item.kind {
ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
- let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(field.hir_id));
+ let is_exported = cx
+ .effective_visibilities
+ .is_exported(cx.tcx.hir().local_def_id(field.hir_id));
self.check_ty(
cx,
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) {
- let is_exported = cx.access_levels.is_exported(item.def_id.def_id);
+ let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let context = CheckTyContext {
is_exported,
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
let ty = qpath_generic_tys(qpath).next()?;
let id = path_def_id(cx, ty)?;
- let path = match cx.tcx.get_diagnostic_name(id)? {
- sym::String => "str",
- sym::OsString => "std::ffi::OsStr",
- sym::PathBuf => "std::path::Path",
+ let path = match cx.tcx.get_diagnostic_name(id) {
+ Some(sym::OsString) => "std::ffi::OsStr",
+ Some(sym::PathBuf) => "std::path::Path",
+ _ if Some(id) == cx.tcx.lang_items().string() => "str",
_ => return None,
};
Some(path)
// here because `mod.rs` guarantees this lint is only run on types outside of bodies and
// is not run on locals.
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
- if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx.at(hir_ty.span), cx.param_env) {
+ if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) {
return false;
}
hir_ty.span
});
let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
if !ty_ty.has_escaping_bound_vars();
- if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env);
+ if ty_ty.is_sized(cx.tcx, cx.param_env);
if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
if ty_ty_size < box_size_threshold;
then {
-use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_diagnostic_item};
+use clippy_utils::{diagnostics::span_lint_and_sugg, ty::is_type_lang_item};
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
);
} else {
if_chain! {
- if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(fun_def_id);
+ if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
if let [.., last_arg] = args;
if let ExprKind::Lit(spanned) = &last_arg.kind;
if let LitKind::Str(symbol, _) = spanned.node;
if symbol.is_empty();
let inner_expr_type = cx.typeck_results().expr_ty(inner_expr);
- if is_type_diagnostic_item(cx, inner_expr_type, sym::String);
+ if is_type_lang_item(cx, inner_expr_type, LangItem::String);
then {
span_lint_and_sugg(
cx,
match fn_kind {
FnKind::ItemFn(..) | FnKind::Method(..) => {
let def_id = cx.tcx.hir().local_def_id(hir_id);
- if self.avoid_breaking_exported_api && cx.access_levels.is_exported(def_id) {
+ if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}
},
/// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern
/// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal.
fn extend_with_struct_pat(
- qself1: &Option<ast::QSelf>,
+ qself1: &Option<P<ast::QSelf>>,
path1: &ast::Path,
fps1: &mut [ast::PatField],
rest1: bool,
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, IsAsync, YieldSource};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, YieldSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_session::{declare_lint_pass, declare_tool_lint};
span: Span,
hir_id: HirId,
) {
- if !span.from_expansion() && fn_kind.asyncness() == IsAsync::Async {
+ if !span.from_expansion() && fn_kind.asyncness().is_async() {
let mut visitor = AsyncFnVisitor { cx, found_await: false };
walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), hir_id);
if !visitor.found_await {
use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators};
use rustc_ast::Mutability;
use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::lang_items::LangItem;
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter::OnlyBodies;
// If the Peekable is passed to a function, stop
ExprKind::Call(_, args) => {
if let Some(func_did) = fn_def_id(self.cx, expr)
- && let Ok(into_iter_did) = self
+ && let Some(into_iter_did) = self
.cx
.tcx
.lang_items()
- .require(LangItem::IntoIterIntoIter)
+ .into_iter_fn()
&& func_did == into_iter_did
{
// Probably a for loop desugar, stop searching
-use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet};
-use rustc_ast::ast::{Expr, ExprKind, LitKind};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::ast::{Expr, ExprKind, MethodCall};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
}
declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
-fn is_useless_rounding<'a>(cx: &EarlyContext<'a>, expr: &'a Expr) -> Option<(&'a str, String)> {
- if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind
+fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
+ if let ExprKind::MethodCall(box MethodCall { seg:name_ident, receiver, .. }) = &expr.kind
&& let method_name = name_ident.ident.name.as_str()
&& (method_name == "ceil" || method_name == "round" || method_name == "floor")
- && let ExprKind::Lit(spanned) = &receiver.kind
- && let LitKind::Float(symbol, _) = spanned.kind {
- let f = symbol.as_str().parse::<f64>().unwrap();
+ && let ExprKind::Lit(token_lit) = &receiver.kind
+ && token_lit.is_semantic_float() {
+ let mut f_str = token_lit.symbol.to_string();
+ let f = f_str.trim_end_matches('_').parse::<f64>().unwrap();
+ if let Some(suffix) = token_lit.suffix {
+ f_str.push_str(suffix.as_str());
+ }
if f.fract() == 0.0 {
- let f_str = snippet(cx, receiver.span, "..").to_string();
Some((method_name, f_str))
} else {
None
impl EarlyLintPass for UnusedRounding {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
- if let Some((method_name, float)) = is_useless_rounding(cx, expr) {
+ if let Some((method_name, float)) = is_useless_rounding(expr) {
span_lint_and_sugg(
cx,
UNUSED_ROUNDING,
}
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let parent_item = cx.tcx.hir().expect_item(parent);
- let assoc_item = cx.tcx.associated_item(impl_item.def_id);
+ let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
if_chain! {
if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
if assoc_item.fn_has_self_parameter;
if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
- if !cx.access_levels.is_exported(impl_item.def_id.def_id) || !self.avoid_breaking_exported_api;
+ if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api;
let body = cx.tcx.hir().body(*body_id);
if let [self_param, ..] = body.params;
if !is_local_used(cx, body, self_param.pat.hir_id);
fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
let body = cx.tcx.hir().body(body_id);
- let typeck = cx.tcx.typeck(impl_item.def_id.def_id);
+ let typeck = cx.tcx.typeck(impl_item.owner_id.def_id);
let mut result = Vec::new();
let _: Option<!> = for_each_expr(body.value, |e| {
// check for `expect`
fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) {
// do not lint public items or in macros
if in_external_macro(cx.sess(), it.span)
- || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id.def_id))
+ || (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(it.owner_id.def_id))
{
return;
}
if !is_from_proc_macro(cx, item); // expensive, should be last check
then {
StackItem::Check {
- impl_id: item.def_id.def_id,
+ impl_id: item.owner_id.def_id,
in_body: 0,
types_to_skip: std::iter::once(self_ty.hir_id).collect(),
}
// trait, not in the impl of the trait.
let trait_method = cx
.tcx
- .associated_item(impl_item.def_id)
+ .associated_item(impl_item.owner_id)
.trait_item_def_id
.expect("impl method matches a trait method");
let trait_method_sig = cx.tcx.fn_sig(trait_method);
use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, LangItem, MatchSource};
+use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
}
if_chain! {
- if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(def_id);
+ if Some(def_id) == cx.tcx.lang_items().from_fn();
if same_type_and_consts(a, b);
then {
SimplifiedTypeGen::StrSimplifiedType,
]
.iter()
- .flat_map(|&ty| cx.tcx.incoherent_impls(ty));
- for item_def_id in lang_items.items().iter().flatten().chain(incoherent_impls) {
- let lang_item_path = cx.get_def_path(*item_def_id);
+ .flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
+ for item_def_id in lang_items.iter().map(|(_, def_id)| def_id).chain(incoherent_impls) {
+ let lang_item_path = cx.get_def_path(item_def_id);
if path_syms.starts_with(&lang_item_path) {
if let [item] = &path_syms[lang_item_path.len()..] {
if matches!(
- cx.tcx.def_kind(*item_def_id),
+ cx.tcx.def_kind(item_def_id),
DefKind::Mod | DefKind::Enum | DefKind::Trait
) {
- for child in cx.tcx.module_children(*item_def_id) {
+ for child in cx.tcx.module_children(item_def_id) {
if child.ident.name == *item {
return true;
}
}
} else {
- for child in cx.tcx.associated_item_def_ids(*item_def_id) {
+ for child in cx.tcx.associated_item_def_ids(item_def_id) {
if cx.tcx.item_name(*child) == *item {
return true;
}
#[allow(clippy::too_many_lines)]
fn check_call(&mut self, cx: &LateContext<'_>, func: &Expr<'_>, args: &[Expr<'_>], span: Span) {
enum Item {
- LangItem(Symbol),
+ LangItem(&'static str),
DiagnosticItem(Symbol),
}
static PATHS: &[&[&str]] = &[
has_ctor,
),
(0, Item::LangItem(item)) => (
- format!("{cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some({def_snip})"),
+ format!("{cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some({def_snip})"),
has_ctor,
),
// match_trait_method
(3, Item::LangItem(item)) => (
format!(
"path_res({cx_snip}, {def_snip}).opt_def_id()\
- .map_or(false, |id| {cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some(id))",
+ .map_or(false, |id| {cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some(id))",
),
false,
),
fn read_mir_alloc_def_path<'tcx>(cx: &LateContext<'tcx>, alloc: &'tcx Allocation, ty: Ty<'_>) -> Option<Vec<String>> {
let (alloc, ty) = if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() {
- let &alloc = alloc.provenance().values().next()?;
+ let &alloc = alloc.provenance().ptrs().values().next()?;
if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
(alloc.inner(), ty)
} else {
{
alloc
.provenance()
+ .ptrs()
.values()
.map(|&alloc| {
if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
.collect()
}
-fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<Symbol> {
- if let Some(lang_item) = cx.tcx.lang_items().items().iter().position(|id| *id == Some(def_id)) {
- let lang_items = def_path_def_ids(cx, &["rustc_hir", "lang_items", "LangItem"])
- .next()
- .unwrap();
- let item_name = cx
- .tcx
- .adt_def(lang_items)
- .variants()
- .iter()
- .nth(lang_item)
- .unwrap()
- .name;
- Some(item_name)
+fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static str> {
+ if let Some((lang_item, _)) = cx.tcx.lang_items().iter().find(|(_, id)| *id == def_id) {
+ Some(lang_item.variant_name())
} else {
None
}
if is_test_module_or_function(cx.tcx, item) {
self.test_modules_deep = self.test_modules_deep.saturating_add(1);
}
- let module = cx.tcx.parent_module_from_def_id(item.def_id.def_id);
- if cx.tcx.visibility(item.def_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
+ let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id);
+ if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
return;
}
if_chain! {
if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind;
if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
- let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id.def_id);
+ let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id);
if !used_imports.is_empty(); // Already handled by `unused_imports`
then {
let mut applicability = Applicability::MachineApplicable;
&& over(&l.attrs, &r.attrs, eq_attr)
}
-pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool {
+pub fn eq_qself(l: &P<QSelf>, r: &P<QSelf>) -> bool {
l.position == r.position && eq_ty(&l.ty, &r.ty)
}
-pub fn eq_maybe_qself(l: &Option<QSelf>, r: &Option<QSelf>) -> bool {
+pub fn eq_maybe_qself(l: &Option<P<QSelf>>, r: &Option<P<QSelf>>) -> bool {
match (l, r) {
(Some(l), Some(r)) => eq_qself(l, r),
(None, None) => true,
(Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
(Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
- (MethodCall(lc, ls, la, _), MethodCall(rc, rs, ra, _)) => {
- eq_path_seg(lc, rc) && eq_expr(ls, rs) && over(la, ra, |l, r| eq_expr(l, r))
- },
+ (
+ MethodCall(box ast::MethodCall {
+ seg: ls,
+ receiver: lr,
+ args: la,
+ ..
+ }),
+ MethodCall(box ast::MethodCall {
+ seg: rs,
+ receiver: rr,
+ args: ra,
+ ..
+ }),
+ ) => eq_path_seg(ls, rs) && eq_expr(lr, rr) && over(la, ra, |l, r| eq_expr(l, r)),
(Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
- (Lit(l), Lit(r)) => l.kind == r.kind,
+ (Lit(l), Lit(r)) => l == r,
(Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt),
(Let(lp, le, _), Let(rp, re, _)) => eq_pat(lp, rp) && eq_expr(le, re),
(If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re),
(AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv),
(Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp),
(Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm),
- (Closure(lb, lc, la, lm, lf, le, _), Closure(rb, rc, ra, rm, rf, re, _)) => {
+ (
+ Closure(box ast::Closure {
+ binder: lb,
+ capture_clause: lc,
+ asyncness: la,
+ movability: lm,
+ fn_decl: lf,
+ body: le,
+ ..
+ }),
+ Closure(box ast::Closure {
+ binder: rb,
+ capture_clause: rc,
+ asyncness: ra,
+ movability: rm,
+ fn_decl: rf,
+ body: re,
+ ..
+ }),
+ ) => {
eq_closure_binder(lb, rb)
&& lc == rc
&& la.is_async() == ra.is_async()
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_hir;
-extern crate rustc_hir_analysis;
+extern crate rustc_hir_typeck;
extern crate rustc_index;
extern crate rustc_infer;
extern crate rustc_lexer;
/// For example, use this to check whether a function call or a pattern is `Some(..)`.
pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
if let Res::Def(DefKind::Ctor(..), id) = res
- && let Ok(lang_id) = cx.tcx.lang_items().require(lang_item)
+ && let Some(lang_id) = cx.tcx.lang_items().get(lang_item)
&& let Some(id) = cx.tcx.opt_parent(id)
{
id == lang_id
_ => did,
};
- cx.tcx.lang_items().require(item).map_or(false, |id| id == did)
+ cx.tcx.lang_items().get(item) == Some(did)
}
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, segments))
}
+/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
+/// it matches the given lang item.
+pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool {
+ path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.lang_items().get(lang_item) == Some(id))
+}
+
/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
/// it matches the given diagnostic item.
pub fn is_path_diagnostic_item<'tcx>(
ItemKind::Mod(r#mod) => r#mod
.item_ids
.iter()
- .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.def_id))
+ .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
.collect(),
ItemKind::Impl(r#impl) => r#impl
.items
.iter()
- .filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.def_id))
+ .filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.owner_id))
.collect(),
ItemKind::Trait(.., trait_item_refs) => trait_item_refs
.iter()
- .filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.def_id))
+ .filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.owner_id))
.collect(),
_ => Vec::new(),
}
/// constructor from the std library
fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
let std_types_symbols = &[
- sym::String,
sym::Vec,
sym::VecDeque,
sym::LinkedList,
if method.ident.name == sym::new {
if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
- return std_types_symbols
- .iter()
- .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did()));
+ return std_types_symbols.iter().any(|&symbol| {
+ cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
+ });
}
}
}
ExprKind::Lit(hir::Lit {
node: LitKind::Str(ref sym, _),
..
- }) => return sym.is_empty() && is_path_diagnostic_item(cx, ty, sym::String),
+ }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
ExprKind::Repeat(_, ArrayLen::Body(len)) => {
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind &&
Entry::Vacant(entry) => {
let mut names = Vec::new();
for id in tcx.hir().module_items(module) {
- if matches!(tcx.def_kind(id.def_id), DefKind::Const)
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
&& let item = tcx.hir().item(id)
&& let ItemKind::Const(ty, _body) = item.kind {
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
pub fn is_panic(cx: &LateContext<'_>, def_id: DefId) -> bool {
let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return false };
matches!(
- name.as_str(),
- "core_panic_macro"
- | "std_panic_macro"
- | "core_panic_2015_macro"
- | "std_panic_2015_macro"
- | "core_panic_2021_macro"
+ name,
+ sym::core_panic_macro
+ | sym::std_panic_macro
+ | sym::core_panic_2015_macro
+ | sym::std_panic_2015_macro
+ | sym::core_panic_2021_macro
)
}
-use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind};
+use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use std::iter;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
}
impl<'a> NumericLiteral<'a> {
- pub fn from_lit(src: &'a str, lit: &Lit) -> Option<NumericLiteral<'a>> {
- NumericLiteral::from_lit_kind(src, &lit.kind)
- }
-
pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<'a>> {
let unsigned_src = src.strip_prefix('-').map_or(src, |s| s);
if lit_kind.is_numeric()
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{EarlyContext, LateContext, LintContext};
use rustc_middle::hir::place::ProjectionKind;
| ast::ExprKind::InlineAsm(..)
| ast::ExprKind::ConstBlock(..)
| ast::ExprKind::Lit(..)
+ | ast::ExprKind::IncludedBytes(..)
| ast::ExprKind::Loop(..)
| ast::ExprKind::MacCall(..)
| ast::ExprKind::MethodCall(..)
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability) {
let mut remove_span = item;
- let hi = cx.sess().source_map().next_point(remove_span).hi();
- let fmpos = cx.sess().source_map().lookup_byte_offset(hi);
+ let fmpos = cx.sess().source_map().lookup_byte_offset(remove_span.hi());
if let Some(ref src) = fmpos.sf.src {
let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
- fn fake_read(
- &mut self,
- _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
- _: FakeReadCause,
- _: HirId,
- ) {
- }
+ fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
#[cfg(test)]
};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::{Size, VariantIdx};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::normalize::AtExt;
// Checks if the given type implements copy.
pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
- ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
+ ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
}
/// This checks whether a given type is known to implement Debug.
/// Returns `false` if the `LangItem` is not defined.
pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
match ty.kind() {
- ty::Adt(adt, _) => cx
- .tcx
- .lang_items()
- .require(lang_item)
- .map_or(false, |li| li == adt.did()),
+ ty::Adt(adt, _) => cx.tcx.lang_items().get(lang_item) == Some(adt.did()),
_ => false,
}
}
let mut output = None;
let lang_items = cx.tcx.lang_items();
- for pred in cx
+ for (pred, _) in cx
.tcx
.bound_explicit_item_bounds(ty.item_def_id)
- .transpose_iter()
- .map(|x| x.map_bound(|(p, _)| p))
+ .subst_iter_copied(cx.tcx, ty.substs)
{
- match pred.0.kind().skip_binder() {
+ match pred.kind().skip_binder() {
PredicateKind::Trait(p)
if (lang_items.fn_trait() == Some(p.def_id())
|| lang_items.fn_mut_trait() == Some(p.def_id())
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
{
- let i = pred
- .map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1)))
- .subst(cx.tcx, ty.substs);
+ let i = pred.kind().rebind(p.trait_ref.substs.type_at(1));
if inputs.map_or(false, |inputs| inputs != i) {
// Multiple different fn trait impls. Is this even allowed?
// Multiple different fn trait impls. Is this even allowed?
return None;
}
- output = Some(
- pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap()))
- .subst(cx.tcx, ty.substs),
- );
+ output = pred.kind().rebind(p.term.ty()).transpose();
},
_ => (),
}
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirIdSet;
use rustc_hir::{Expr, ExprKind, HirId, Node};
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
self.update(cmt);
}
- fn fake_read(
- &mut self,
- _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
- _: FakeReadCause,
- _: HirId,
- ) {
- }
+ fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
pub struct ParamBindingIdCollector {
use std::env;
use std::ops::Deref;
use std::panic;
-use std::path::{Path, PathBuf};
-use std::process::{exit, Command};
+use std::path::Path;
+use std::process::exit;
use std::sync::LazyLock;
/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
false,
None,
false,
+ false,
));
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
interface::try_print_query_stack(&handler, num_frames);
}
-fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<PathBuf> {
- home.and_then(|home| {
- toolchain.map(|toolchain| {
- let mut path = PathBuf::from(home);
- path.push("toolchains");
- path.push(toolchain);
- path
- })
- })
-}
-
#[allow(clippy::too_many_lines)]
pub fn main() {
rustc_driver::init_rustc_env_logger();
exit(rustc_driver::catch_with_exit_code(move || {
let mut orig_args: Vec<String> = env::args().collect();
- // Get the sysroot, looking from most specific to this invocation to the least:
- // - command line
- // - runtime environment
- // - SYSROOT
- // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
- // - sysroot from rustc in the path
- // - compile-time environment
- // - SYSROOT
- // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
- let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
- let have_sys_root_arg = sys_root_arg.is_some();
- let sys_root = sys_root_arg
- .map(PathBuf::from)
- .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
- .or_else(|| {
- let home = std::env::var("RUSTUP_HOME")
- .or_else(|_| std::env::var("MULTIRUST_HOME"))
- .ok();
- let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
- .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN"))
- .ok();
- toolchain_path(home, toolchain)
- })
- .or_else(|| {
- Command::new("rustc")
- .arg("--print")
- .arg("sysroot")
- .output()
- .ok()
- .and_then(|out| String::from_utf8(out.stdout).ok())
- .map(|s| PathBuf::from(s.trim()))
- })
- .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
- .or_else(|| {
- let home = option_env!("RUSTUP_HOME")
- .or(option_env!("MULTIRUST_HOME"))
- .map(ToString::to_string);
- let toolchain = option_env!("RUSTUP_TOOLCHAIN")
- .or(option_env!("MULTIRUST_TOOLCHAIN"))
- .map(ToString::to_string);
- toolchain_path(home, toolchain)
- })
- .map(|pb| pb.to_string_lossy().to_string())
- .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");
-
// make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc"
// for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver
// uses
orig_args.remove(pos);
orig_args[0] = "rustc".to_string();
- // if we call "rustc", we need to pass --sysroot here as well
- let mut args: Vec<String> = orig_args.clone();
- if !have_sys_root_arg {
- args.extend(vec!["--sysroot".into(), sys_root]);
- };
-
- return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
+ return rustc_driver::RunCompiler::new(&orig_args, &mut DefaultCallbacks).run();
}
if orig_args.iter().any(|a| a == "--version" || a == "-V") {
exit(0);
}
- // this conditional check for the --sysroot flag is there so users can call
- // `clippy_driver` directly
- // without having to pass --sysroot or anything
- let mut args: Vec<String> = orig_args.clone();
- if !have_sys_root_arg {
- args.extend(vec!["--sysroot".into(), sys_root]);
- };
-
let mut no_deps = false;
let clippy_args_var = env::var("CLIPPY_ARGS").ok();
let clippy_args = clippy_args_var
let clippy_enabled = !cap_lints_allow && (!no_deps || in_primary_package);
if clippy_enabled {
+ let mut args: Vec<String> = orig_args.clone();
args.extend(clippy_args);
rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }).run()
} else {
- rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }).run()
+ rustc_driver::RunCompiler::new(&orig_args, &mut RustcCallbacks { clippy_args_var }).run()
}
}))
}
-thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
+thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: internal compiler error: unexpected panic
let _ = is_type_lang_item(cx, ty, LangItem::OwnedBox);
let _ = is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit);
- let _ = cx.tcx.lang_items().require(LangItem::OwnedBox).ok() == Some(did);
+ let _ = cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did);
let _ = cx.tcx.is_diagnostic_item(sym::Option, did);
- let _ = cx.tcx.lang_items().require(LangItem::OptionSome).ok() == Some(did);
+ let _ = cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did);
let _ = is_trait_method(cx, expr, sym::AsRef);
let _ = is_path_diagnostic_item(cx, expr, sym::Option);
- let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().require(LangItem::IteratorNext).ok() == Some(id));
+ let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id));
let _ = is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome);
}
--> $DIR/unnecessary_def_path.rs:51:13
|
LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().require(LangItem::OwnedBox).ok() == Some(did)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)`
error: use of a def path to a diagnostic item
--> $DIR/unnecessary_def_path.rs:52:13
--> $DIR/unnecessary_def_path.rs:53:13
|
LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().require(LangItem::OptionSome).ok() == Some(did)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)`
|
= help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead
--> $DIR/unnecessary_def_path.rs:58:13
|
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().require(LangItem::IteratorNext).ok() == Some(id))`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))`
error: use of a def path to a `LangItem`
--> $DIR/unnecessary_def_path.rs:59:13
= help: convert all references to use `LangItem::DerefMut`
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
-error: hardcoded path to a diagnostic item
- --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
- |
-LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: convert all references to use `sym::deref_method`
-
error: hardcoded path to a diagnostic item
--> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
|
|
= help: convert all references to use `sym::Deref`
+error: hardcoded path to a diagnostic item
+ --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+ |
+LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: convert all references to use `sym::deref_method`
+
error: aborting due to 3 previous errors
|
LL | Some(reference) = cache.data.get(key) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: consider adding `let`
+ |
+LL | let Some(reference) = cache.data.get(key) {
+ | +++
error: aborting due to 3 previous errors
+// needs-asm-support
// run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
+// needs-asm-support
// run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:24:5
+ --> $DIR/entry.rs:25:5
|
LL | / if !m.contains_key(&k) {
LL | | m.insert(k, v);
= note: `-D clippy::map-entry` implied by `-D warnings`
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:29:5
+ --> $DIR/entry.rs:30:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:38:5
+ --> $DIR/entry.rs:39:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:47:5
+ --> $DIR/entry.rs:48:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:57:5
+ --> $DIR/entry.rs:58:5
|
LL | / if !m.contains_key(&k) {
LL | | foo();
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:63:5
+ --> $DIR/entry.rs:64:5
|
LL | / if !m.contains_key(&k) {
LL | | match 0 {
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:75:5
+ --> $DIR/entry.rs:76:5
|
LL | / if !m.contains_key(&k) {
LL | | match 0 {
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:85:5
+ --> $DIR/entry.rs:86:5
|
LL | / if !m.contains_key(&k) {
LL | | foo();
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:119:5
+ --> $DIR/entry.rs:120:5
|
LL | / if !m.contains_key(&m!(k)) {
LL | | m.insert(m!(k), m!(v));
| |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));`
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:151:5
+ --> $DIR/entry.rs:152:5
|
LL | / if !m.contains_key(&k) {
LL | | let x = (String::new(), String::new());
LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
-error[E0080]: erroneous constant used
+note: erroneous constant used
--> $DIR/indexing_slicing_index.rs:31:5
|
LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
- | ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+ | ^^^^^^^^^^^^^^^^^^^^^^
error: indexing may panic
--> $DIR/indexing_slicing_index.rs:22:5
LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0080`.
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
- | |_____^
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
-help: try instead
- |
-LL | assert!(a.is_empty(), "qaqaq{:?}", a);
- |
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!a.is_empty(), "with expansion {}", one!());
- |
+ | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: aborting due to 2 previous errors
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
- | |_____^
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
-help: try instead
- |
-LL | assert!(a.is_empty(), "qaqaq{:?}", a);
- |
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:34:5
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(a.is_empty(), "qwqwq");
- |
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:51:5
LL | / if b.is_empty() {
LL | | panic!("panic1");
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!b.is_empty(), "panic1");
- |
+ | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:54:5
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!(b.is_empty() && a.is_empty()), "panic2");
- |
+ | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:57:5
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!(a.is_empty() && !b.is_empty()), "panic3");
- |
+ | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:60:5
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!(b.is_empty() || a.is_empty()), "panic4");
- |
+ | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:63:5
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!(a.is_empty() || !b.is_empty()), "panic5");
- |
+ | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
- | |_____^
- |
-help: try instead
- |
-LL | assert!(!a.is_empty(), "with expansion {}", one!());
- |
+ | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:73:5
+// needs-asm-support
// aux-build: proc_macro_with_span.rs
#![warn(clippy::missing_docs_in_private_items)]
error: missing documentation for a type alias
- --> $DIR/missing_doc.rs:15:1
+ --> $DIR/missing_doc.rs:16:1
|
LL | type Typedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
error: missing documentation for a type alias
- --> $DIR/missing_doc.rs:16:1
+ --> $DIR/missing_doc.rs:17:1
|
LL | pub type PubTypedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing_doc.rs:18:1
+ --> $DIR/missing_doc.rs:19:1
|
LL | mod module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing_doc.rs:19:1
+ --> $DIR/missing_doc.rs:20:1
|
LL | pub mod pub_module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:23:1
+ --> $DIR/missing_doc.rs:24:1
|
LL | pub fn foo2() {}
| ^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:24:1
+ --> $DIR/missing_doc.rs:25:1
|
LL | fn foo3() {}
| ^^^^^^^^^^^^
error: missing documentation for an enum
- --> $DIR/missing_doc.rs:38:1
+ --> $DIR/missing_doc.rs:39:1
|
LL | / enum Baz {
LL | | BazA { a: isize, b: isize },
| |_^
error: missing documentation for a variant
- --> $DIR/missing_doc.rs:39:5
+ --> $DIR/missing_doc.rs:40:5
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing_doc.rs:39:12
+ --> $DIR/missing_doc.rs:40:12
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing_doc.rs:39:22
+ --> $DIR/missing_doc.rs:40:22
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a variant
- --> $DIR/missing_doc.rs:40:5
+ --> $DIR/missing_doc.rs:41:5
|
LL | BarB,
| ^^^^
error: missing documentation for an enum
- --> $DIR/missing_doc.rs:43:1
+ --> $DIR/missing_doc.rs:44:1
|
LL | / pub enum PubBaz {
LL | | PubBazA { a: isize },
| |_^
error: missing documentation for a variant
- --> $DIR/missing_doc.rs:44:5
+ --> $DIR/missing_doc.rs:45:5
|
LL | PubBazA { a: isize },
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing_doc.rs:44:15
+ --> $DIR/missing_doc.rs:45:15
|
LL | PubBazA { a: isize },
| ^^^^^^^^
error: missing documentation for a constant
- --> $DIR/missing_doc.rs:64:1
+ --> $DIR/missing_doc.rs:65:1
|
LL | const FOO: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^
error: missing documentation for a constant
- --> $DIR/missing_doc.rs:71:1
+ --> $DIR/missing_doc.rs:72:1
|
LL | pub const FOO4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/missing_doc.rs:73:1
+ --> $DIR/missing_doc.rs:74:1
|
LL | static BAR: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/missing_doc.rs:80:1
+ --> $DIR/missing_doc.rs:81:1
|
LL | pub static BAR4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing_doc.rs:82:1
+ --> $DIR/missing_doc.rs:83:1
|
LL | / mod internal_impl {
LL | | /// dox
| |_^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:85:5
+ --> $DIR/missing_doc.rs:86:5
|
LL | pub fn undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:86:5
+ --> $DIR/missing_doc.rs:87:5
|
LL | pub fn undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:87:5
+ --> $DIR/missing_doc.rs:88:5
|
LL | fn undocumented3() {}
| ^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:92:9
+ --> $DIR/missing_doc.rs:93:9
|
LL | pub fn also_undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:93:9
+ --> $DIR/missing_doc.rs:94:9
|
LL | fn also_undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
--- /dev/null
+// compile-flags: -Z track-diagnostics
+// error-pattern: created at
+
+// Normalize the emitted location so this doesn't need
+// updating everytime someone adds or removes a line.
+// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
+
+struct A;
+struct B;
+const S: A = B;
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/track-diagnostics.rs:LL:CC
+ |
+LL | const S: A = B;
+ | ^ expected struct `A`, found struct `B`
+-Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.