Auto merge of #148193 - camsteffen:remove-qpath-langitem, r=cjgillot
Remove `QPath::LangItem` Closes rust-lang/rust#115178. r? cjgillot
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::LoweringContext;
|
||||
@@ -128,7 +130,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let req_span = self.mark_span_with_reason(
|
||||
rustc_span::DesugaringKind::Contract,
|
||||
lowered_req.span,
|
||||
None,
|
||||
Some(Arc::clone(&self.allow_contracts)),
|
||||
);
|
||||
let precond = self.expr_call_lang_item_fn_mut(
|
||||
req_span,
|
||||
@@ -143,8 +145,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
ens: &Box<rustc_ast::Expr>,
|
||||
) -> &'hir rustc_hir::Expr<'hir> {
|
||||
let ens_span = self.lower_span(ens.span);
|
||||
let ens_span =
|
||||
self.mark_span_with_reason(rustc_span::DesugaringKind::Contract, ens_span, None);
|
||||
let ens_span = self.mark_span_with_reason(
|
||||
rustc_span::DesugaringKind::Contract,
|
||||
ens_span,
|
||||
Some(Arc::clone(&self.allow_contracts)),
|
||||
);
|
||||
let lowered_ens = self.lower_expr_mut(&ens);
|
||||
self.expr_call_lang_item_fn(
|
||||
ens_span,
|
||||
|
||||
@@ -865,6 +865,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
};
|
||||
|
||||
let features = match await_kind {
|
||||
FutureKind::Future if is_async_gen => Some(Arc::clone(&self.allow_async_gen)),
|
||||
FutureKind::Future => None,
|
||||
FutureKind::AsyncIterator => Some(Arc::clone(&self.allow_for_await)),
|
||||
};
|
||||
@@ -1479,7 +1480,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
|
||||
let e1 = self.lower_expr_mut(e1);
|
||||
let e2 = self.lower_expr_mut(e2);
|
||||
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
|
||||
let fn_path = self.make_lang_item_qpath(hir::LangItem::RangeInclusiveNew, span, None);
|
||||
let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
|
||||
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
|
||||
}
|
||||
@@ -1565,7 +1566,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
);
|
||||
|
||||
hir::ExprKind::Struct(
|
||||
self.arena.alloc(hir::QPath::LangItem(lang_item, span)),
|
||||
self.arena.alloc(self.make_lang_item_qpath(lang_item, span, None)),
|
||||
fields,
|
||||
hir::StructTailExpr::None,
|
||||
)
|
||||
@@ -1715,8 +1716,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
|
||||
// This ensures that we store our resumed `ResumeContext` correctly, and also that
|
||||
// the apparent value of the `yield` expression is `()`.
|
||||
let wrapped_yielded = self.expr_call_lang_item_fn(
|
||||
let desugar_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Async,
|
||||
span,
|
||||
Some(Arc::clone(&self.allow_async_gen)),
|
||||
);
|
||||
let wrapped_yielded = self.expr_call_lang_item_fn(
|
||||
desugar_span,
|
||||
hir::LangItem::AsyncGenReady,
|
||||
std::slice::from_ref(yielded),
|
||||
);
|
||||
@@ -1728,7 +1734,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
unreachable!("use of `await` outside of an async context.");
|
||||
};
|
||||
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
|
||||
let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
|
||||
let lhs = self.expr_ident(desugar_span, task_context_ident, task_context_hid);
|
||||
|
||||
hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))
|
||||
} else {
|
||||
@@ -2161,7 +2167,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
lang_item: hir::LangItem,
|
||||
fields: &'hir [hir::Expr<'hir>],
|
||||
) -> hir::Expr<'hir> {
|
||||
let path = self.arena.alloc(self.lang_item_path(span, lang_item));
|
||||
let path = self.arena.alloc(self.make_lang_item_qpath(lang_item, span, None));
|
||||
self.expr_enum_variant(span, path, fields)
|
||||
}
|
||||
|
||||
@@ -2198,16 +2204,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
span: Span,
|
||||
lang_item: hir::LangItem,
|
||||
) -> hir::Expr<'hir> {
|
||||
let path = self.lang_item_path(span, lang_item);
|
||||
self.expr(span, hir::ExprKind::Path(path))
|
||||
}
|
||||
|
||||
pub(super) fn lang_item_path(
|
||||
&mut self,
|
||||
span: Span,
|
||||
lang_item: hir::LangItem,
|
||||
) -> hir::QPath<'hir> {
|
||||
hir::QPath::LangItem(lang_item, self.lower_span(span))
|
||||
let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span), None);
|
||||
self.expr(span, hir::ExprKind::Path(qpath))
|
||||
}
|
||||
|
||||
/// `<LangItem>::name`
|
||||
|
||||
@@ -391,7 +391,8 @@ fn make_format_spec<'hir>(
|
||||
let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp);
|
||||
let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp);
|
||||
let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp);
|
||||
let placeholder = ctx.arena.alloc(hir::QPath::LangItem(hir::LangItem::FormatPlaceholder, sp));
|
||||
let placeholder =
|
||||
ctx.arena.alloc(ctx.make_lang_item_qpath(hir::LangItem::FormatPlaceholder, sp, None));
|
||||
let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]);
|
||||
ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None))
|
||||
}
|
||||
|
||||
@@ -138,9 +138,11 @@ struct LoweringContext<'a, 'hir> {
|
||||
#[cfg(debug_assertions)]
|
||||
node_id_to_local_id: NodeMap<hir::ItemLocalId>,
|
||||
|
||||
allow_contracts: Arc<[Symbol]>,
|
||||
allow_try_trait: Arc<[Symbol]>,
|
||||
allow_gen_future: Arc<[Symbol]>,
|
||||
allow_pattern_type: Arc<[Symbol]>,
|
||||
allow_async_gen: Arc<[Symbol]>,
|
||||
allow_async_iterator: Arc<[Symbol]>,
|
||||
allow_for_await: Arc<[Symbol]>,
|
||||
allow_async_fn_traits: Arc<[Symbol]>,
|
||||
@@ -183,6 +185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
current_item: None,
|
||||
impl_trait_defs: Vec::new(),
|
||||
impl_trait_bounds: Vec::new(),
|
||||
allow_contracts: [sym::contracts_internals].into(),
|
||||
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
|
||||
allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
|
||||
allow_gen_future: if tcx.features().async_fn_track_caller() {
|
||||
@@ -190,8 +193,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
} else {
|
||||
[sym::gen_future].into()
|
||||
},
|
||||
allow_for_await: [sym::async_iterator].into(),
|
||||
allow_for_await: [sym::async_gen_internals, sym::async_iterator].into(),
|
||||
allow_async_fn_traits: [sym::async_fn_traits].into(),
|
||||
allow_async_gen: [sym::async_gen_internals].into(),
|
||||
// FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
|
||||
// interact with `gen`/`async gen` blocks
|
||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||
@@ -2531,8 +2535,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
lang_item: hir::LangItem,
|
||||
fields: &'hir [hir::PatField<'hir>],
|
||||
) -> &'hir hir::Pat<'hir> {
|
||||
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span));
|
||||
self.pat(span, hir::PatKind::Struct(qpath, fields, None))
|
||||
let path = self.make_lang_item_qpath(lang_item, self.lower_span(span), None);
|
||||
self.pat(span, hir::PatKind::Struct(path, fields, None))
|
||||
}
|
||||
|
||||
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) {
|
||||
|
||||
@@ -503,8 +503,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
}
|
||||
if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
|
||||
call_expr.kind
|
||||
&& let hir::ExprKind::Path(qpath) = call_expr.kind
|
||||
&& tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter)
|
||||
{
|
||||
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
|
||||
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
|
||||
@@ -2312,6 +2312,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
let typeck_results = tcx.typeck(self.mir_def_id());
|
||||
|
||||
struct ExprFinder<'hir> {
|
||||
tcx: TyCtxt<'hir>,
|
||||
issue_span: Span,
|
||||
expr_span: Span,
|
||||
body_expr: Option<&'hir hir::Expr<'hir>>,
|
||||
@@ -2336,9 +2337,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
// };
|
||||
// corresponding to the desugaring of a for loop `for <pat> in <head> { <body> }`.
|
||||
if let hir::ExprKind::Call(path, [arg]) = ex.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
|
||||
path.kind
|
||||
&& let hir::ExprKind::Path(qpath) = path.kind
|
||||
&& self.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter)
|
||||
&& arg.span.contains(self.issue_span)
|
||||
&& ex.span.desugaring_kind() == Some(DesugaringKind::ForLoop)
|
||||
{
|
||||
// Find `IntoIterator::into_iter(<head>)`
|
||||
self.head = Some(arg);
|
||||
@@ -2355,10 +2357,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
..
|
||||
}) = stmt.kind
|
||||
&& let hir::ExprKind::Call(path, _args) = call.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _)) =
|
||||
path.kind
|
||||
&& let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind
|
||||
&& let hir::QPath::LangItem(LangItem::OptionSome, pat_span) = path
|
||||
&& let hir::ExprKind::Path(qpath) = path.kind
|
||||
&& self.tcx.qpath_is_lang_item(qpath, LangItem::IteratorNext)
|
||||
&& let hir::PatKind::Struct(qpath, [field, ..], _) = bind.pat.kind
|
||||
&& self.tcx.qpath_is_lang_item(qpath, LangItem::OptionSome)
|
||||
&& call.span.contains(self.issue_span)
|
||||
{
|
||||
// Find `<pat>` and the span for the whole `for` loop.
|
||||
@@ -2370,7 +2372,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
self.loop_bind = Some(ident);
|
||||
}
|
||||
self.head_span = Some(*head_span);
|
||||
self.pat_span = Some(pat_span);
|
||||
self.pat_span = Some(bind.pat.span);
|
||||
self.loop_span = Some(stmt.span);
|
||||
}
|
||||
|
||||
@@ -2385,6 +2387,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
let mut finder = ExprFinder {
|
||||
tcx,
|
||||
expr_span: span,
|
||||
issue_span,
|
||||
loop_bind: None,
|
||||
|
||||
@@ -23,13 +23,14 @@ use rustc_index::IndexVec;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_span::{
|
||||
BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, Span, Symbol, kw, sym,
|
||||
};
|
||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||
use smallvec::SmallVec;
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::LangItem;
|
||||
use crate::attrs::AttributeKind;
|
||||
use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res};
|
||||
use crate::def_id::{DefId, LocalDefIdMap};
|
||||
@@ -2418,9 +2419,6 @@ impl Expr<'_> {
|
||||
allow_projections_from(base) || base.is_place_expr(allow_projections_from)
|
||||
}
|
||||
|
||||
// Lang item paths cannot currently be local variables or statics.
|
||||
ExprKind::Path(QPath::LangItem(..)) => false,
|
||||
|
||||
// Suppress errors for bad expressions.
|
||||
ExprKind::Err(_guar)
|
||||
| ExprKind::Let(&LetExpr { recovered: ast::Recovered::Yes(_guar), .. }) => true,
|
||||
@@ -2590,112 +2588,27 @@ impl Expr<'_> {
|
||||
pub fn equivalent_for_indexing(&self, other: &Expr<'_>) -> bool {
|
||||
match (self.kind, other.kind) {
|
||||
(ExprKind::Lit(lit1), ExprKind::Lit(lit2)) => lit1.node == lit2.node,
|
||||
(
|
||||
ExprKind::Path(QPath::LangItem(item1, _)),
|
||||
ExprKind::Path(QPath::LangItem(item2, _)),
|
||||
) => item1 == item2,
|
||||
(
|
||||
ExprKind::Path(QPath::Resolved(None, path1)),
|
||||
ExprKind::Path(QPath::Resolved(None, path2)),
|
||||
) => path1.res == path2.res,
|
||||
(
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeTo, _),
|
||||
[val1],
|
||||
&QPath::Resolved(None, &Path { res: Res::Def(_, path1_def_id), .. }),
|
||||
args1,
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeTo, _),
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeToInclusive, _),
|
||||
[val1],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeToInclusive, _),
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
|
||||
[val1],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeFrom, _),
|
||||
[val1],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeFrom, _),
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeFromCopy, _),
|
||||
[val1],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeFromCopy, _),
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
) => val1.expr.equivalent_for_indexing(val2.expr),
|
||||
(
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::Range, _),
|
||||
[val1, val3],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::Range, _),
|
||||
[val2, val4],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeCopy, _),
|
||||
[val1, val3],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeCopy, _),
|
||||
[val2, val4],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
|
||||
[val1, val3],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
|
||||
[val2, val4],
|
||||
&QPath::Resolved(None, &Path { res: Res::Def(_, path2_def_id), .. }),
|
||||
args2,
|
||||
StructTailExpr::None,
|
||||
),
|
||||
) => {
|
||||
val1.expr.equivalent_for_indexing(val2.expr)
|
||||
&& val3.expr.equivalent_for_indexing(val4.expr)
|
||||
path2_def_id == path1_def_id
|
||||
&& is_range_literal(self)
|
||||
&& is_range_literal(other)
|
||||
&& std::iter::zip(args1, args2)
|
||||
.all(|(a, b)| a.expr.equivalent_for_indexing(b.expr))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@@ -2713,30 +2626,29 @@ impl Expr<'_> {
|
||||
/// Checks if the specified expression is a built-in range literal.
|
||||
/// (See: `LoweringContext::lower_expr()`).
|
||||
pub fn is_range_literal(expr: &Expr<'_>) -> bool {
|
||||
match expr.kind {
|
||||
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
|
||||
ExprKind::Struct(ref qpath, _, _) => matches!(
|
||||
**qpath,
|
||||
QPath::LangItem(
|
||||
LangItem::Range
|
||||
| LangItem::RangeTo
|
||||
| LangItem::RangeFrom
|
||||
| LangItem::RangeFull
|
||||
| LangItem::RangeToInclusive
|
||||
| LangItem::RangeCopy
|
||||
| LangItem::RangeFromCopy
|
||||
| LangItem::RangeInclusiveCopy
|
||||
| LangItem::RangeToInclusiveCopy,
|
||||
..
|
||||
)
|
||||
),
|
||||
|
||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||
ExprKind::Call(ref func, _) => {
|
||||
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
|
||||
}
|
||||
|
||||
_ => false,
|
||||
if let ExprKind::Struct(QPath::Resolved(None, path), _, StructTailExpr::None) = expr.kind
|
||||
&& let [.., segment] = path.segments
|
||||
&& let sym::RangeFrom
|
||||
| sym::RangeFull
|
||||
| sym::Range
|
||||
| sym::RangeToInclusive
|
||||
| sym::RangeTo
|
||||
| sym::RangeFromCopy
|
||||
| sym::RangeCopy
|
||||
| sym::RangeInclusiveCopy
|
||||
| sym::RangeToInclusiveCopy = segment.ident.name
|
||||
&& expr.span.is_desugaring(DesugaringKind::RangeExpr)
|
||||
{
|
||||
true
|
||||
} else if let ExprKind::Call(func, _) = &expr.kind
|
||||
&& let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
|
||||
&& let [.., segment] = path.segments
|
||||
&& let sym::range_inclusive_new = segment.ident.name
|
||||
&& expr.span.is_desugaring(DesugaringKind::RangeExpr)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2930,9 +2842,6 @@ pub enum QPath<'hir> {
|
||||
/// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
|
||||
/// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
|
||||
TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
|
||||
|
||||
/// Reference to a `#[lang = "foo"]` item.
|
||||
LangItem(LangItem, Span),
|
||||
}
|
||||
|
||||
impl<'hir> QPath<'hir> {
|
||||
@@ -2941,7 +2850,6 @@ impl<'hir> QPath<'hir> {
|
||||
match *self {
|
||||
QPath::Resolved(_, path) => path.span,
|
||||
QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span),
|
||||
QPath::LangItem(_, span) => span,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2951,7 +2859,6 @@ impl<'hir> QPath<'hir> {
|
||||
match *self {
|
||||
QPath::Resolved(_, path) => path.span,
|
||||
QPath::TypeRelative(qself, _) => qself.span,
|
||||
QPath::LangItem(_, span) => span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1416,7 +1416,6 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(
|
||||
try_visit!(visitor.visit_ty_unambig(qself));
|
||||
visitor.visit_path_segment(segment)
|
||||
}
|
||||
QPath::LangItem(..) => V::Result::output(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2240,13 +2240,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
)
|
||||
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
|
||||
}
|
||||
hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
|
||||
ty::Const::new_error_with_message(
|
||||
tcx,
|
||||
qpath.span(),
|
||||
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
|
||||
)
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon),
|
||||
hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span),
|
||||
}
|
||||
@@ -2561,17 +2554,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
.map(|(ty, _, _)| ty)
|
||||
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
|
||||
}
|
||||
&hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
|
||||
let def_id = tcx.require_lang_item(lang_item, span);
|
||||
let (args, _) = self.lower_generic_args_of_path(
|
||||
span,
|
||||
def_id,
|
||||
&[],
|
||||
&hir::PathSegment::invalid(),
|
||||
None,
|
||||
);
|
||||
tcx.at(span).type_of(def_id).instantiate(tcx, args)
|
||||
}
|
||||
hir::TyKind::Array(ty, length) => {
|
||||
let length = self.lower_const_arg(length, FeedConstTy::No);
|
||||
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
|
||||
|
||||
@@ -1774,11 +1774,6 @@ impl<'a> State<'a> {
|
||||
self.print_ident(item_segment.ident);
|
||||
self.print_generic_args(item_segment.args(), colons_before_params)
|
||||
}
|
||||
hir::QPath::LangItem(lang_item, span) => {
|
||||
self.word("#[lang = \"");
|
||||
self.print_ident(Ident::new(lang_item.name(), span));
|
||||
self.word("\"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1196,6 +1196,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr.hir_id) else {
|
||||
return;
|
||||
};
|
||||
if parent_expr.span.desugaring_kind().is_some() {
|
||||
return;
|
||||
}
|
||||
enum CallableKind {
|
||||
Function,
|
||||
Method,
|
||||
|
||||
@@ -19,7 +19,7 @@ use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, HirId, QPath, find_attr};
|
||||
use rustc_hir::{ExprKind, HirId, QPath, find_attr, is_range_literal};
|
||||
use rustc_hir_analysis::NoVariantNamed;
|
||||
use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
|
||||
use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, RegionVariableOrigin};
|
||||
@@ -545,9 +545,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ExprKind::AddrOf(kind, mutbl, oprnd) => {
|
||||
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
|
||||
}
|
||||
ExprKind::Path(QPath::LangItem(lang_item, _)) => {
|
||||
self.check_lang_item_path(lang_item, expr)
|
||||
}
|
||||
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None),
|
||||
ExprKind::InlineAsm(asm) => {
|
||||
// We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
|
||||
@@ -748,14 +745,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_lang_item_path(
|
||||
&self,
|
||||
lang_item: hir::LangItem,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
|
||||
}
|
||||
|
||||
pub(crate) fn check_expr_path(
|
||||
&self,
|
||||
qpath: &'tcx hir::QPath<'tcx>,
|
||||
@@ -763,6 +752,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
call_expr_and_args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
if let Some((_, [arg])) = call_expr_and_args
|
||||
&& let QPath::Resolved(_, path) = qpath
|
||||
&& let Res::Def(_, def_id) = path.res
|
||||
&& let Some(lang_item) = tcx.lang_items().from_def_id(def_id)
|
||||
{
|
||||
let code = match lang_item {
|
||||
LangItem::IntoFutureIntoFuture
|
||||
if expr.span.is_desugaring(DesugaringKind::Await) =>
|
||||
{
|
||||
Some(ObligationCauseCode::AwaitableExpr(arg.hir_id))
|
||||
}
|
||||
LangItem::IntoIterIntoIter | LangItem::IteratorNext
|
||||
if expr.span.is_desugaring(DesugaringKind::ForLoop) =>
|
||||
{
|
||||
Some(ObligationCauseCode::ForLoopIterator)
|
||||
}
|
||||
LangItem::TryTraitFromOutput
|
||||
if expr.span.is_desugaring(DesugaringKind::TryBlock) =>
|
||||
{
|
||||
// FIXME it's a try block, not a question mark
|
||||
Some(ObligationCauseCode::QuestionMark)
|
||||
}
|
||||
LangItem::TryTraitBranch | LangItem::TryTraitFromResidual
|
||||
if expr.span.is_desugaring(DesugaringKind::QuestionMark) =>
|
||||
{
|
||||
Some(ObligationCauseCode::QuestionMark)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if let Some(code) = code {
|
||||
let args = self.fresh_args_for_item(expr.span, def_id);
|
||||
self.add_required_obligations_with_code(expr.span, def_id, args, |_, _| {
|
||||
code.clone()
|
||||
});
|
||||
return tcx.type_of(def_id).instantiate(tcx, args);
|
||||
}
|
||||
}
|
||||
|
||||
let (res, opt_ty, segs) =
|
||||
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
|
||||
let ty = match res {
|
||||
@@ -2483,9 +2511,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
args: GenericArgsRef<'tcx>,
|
||||
mut err: Diag<'_>,
|
||||
) {
|
||||
// I don't use 'is_range_literal' because only double-sided, half-open ranges count.
|
||||
if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [range_start, range_end], _) =
|
||||
last_expr_field.expr.kind
|
||||
if is_range_literal(last_expr_field.expr)
|
||||
&& let ExprKind::Struct(&qpath, [range_start, range_end], _) = last_expr_field.expr.kind
|
||||
&& self.tcx.qpath_is_lang_item(qpath, LangItem::Range)
|
||||
&& let variant_field =
|
||||
variant.fields.iter().find(|field| field.ident(self.tcx) == last_expr_field.ident)
|
||||
&& let range_def_id = self.tcx.lang_items().range_struct()
|
||||
|
||||
@@ -671,9 +671,6 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
|
||||
path.segments.last().expect("paths should have a segment")
|
||||
}
|
||||
hir::QPath::TypeRelative(_, segment) => segment,
|
||||
hir::QPath::LangItem(..) => {
|
||||
return hir::intravisit::walk_qpath(self, qpath, id);
|
||||
}
|
||||
};
|
||||
// Alternatively, try to turbofish `::<_, (), _>`.
|
||||
if let Some(def_id) = self.fcx.typeck_results.borrow().qpath_res(qpath, id).opt_def_id()
|
||||
|
||||
@@ -691,53 +691,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
vec![ty_error; len]
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_lang_item_path(
|
||||
&self,
|
||||
lang_item: hir::LangItem,
|
||||
span: Span,
|
||||
hir_id: HirId,
|
||||
) -> (Res, Ty<'tcx>) {
|
||||
let def_id = self.tcx.require_lang_item(lang_item, span);
|
||||
let def_kind = self.tcx.def_kind(def_id);
|
||||
|
||||
let item_ty = if let DefKind::Variant = def_kind {
|
||||
self.tcx.type_of(self.tcx.parent(def_id))
|
||||
} else {
|
||||
self.tcx.type_of(def_id)
|
||||
};
|
||||
let args = self.fresh_args_for_item(span, def_id);
|
||||
let ty = item_ty.instantiate(self.tcx, args);
|
||||
|
||||
self.write_args(hir_id, args);
|
||||
self.write_resolution(hir_id, Ok((def_kind, def_id)));
|
||||
|
||||
let code = match lang_item {
|
||||
hir::LangItem::IntoFutureIntoFuture => {
|
||||
if let hir::Node::Expr(into_future_call) = self.tcx.parent_hir_node(hir_id)
|
||||
&& let hir::ExprKind::Call(_, [arg0]) = &into_future_call.kind
|
||||
{
|
||||
Some(ObligationCauseCode::AwaitableExpr(arg0.hir_id))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
|
||||
Some(ObligationCauseCode::ForLoopIterator)
|
||||
}
|
||||
hir::LangItem::TryTraitFromOutput
|
||||
| hir::LangItem::TryTraitFromResidual
|
||||
| hir::LangItem::TryTraitBranch => Some(ObligationCauseCode::QuestionMark),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(code) = code {
|
||||
self.add_required_obligations_with_code(span, def_id, args, move |_, _| code.clone());
|
||||
} else {
|
||||
self.add_required_obligations_for_hir(span, def_id, args, hir_id);
|
||||
}
|
||||
|
||||
(Res::Def(def_kind, def_id), ty)
|
||||
}
|
||||
|
||||
/// Resolves an associated value path into a base type and associated constant, or method
|
||||
/// resolution. The newly resolved definition is written into `type_dependent_defs`.
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
@@ -768,9 +721,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let ty = self.lowerer().lower_ty(qself);
|
||||
(LoweredTy::from_raw(self, span, ty), qself, segment)
|
||||
}
|
||||
QPath::LangItem(..) => {
|
||||
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
|
||||
}
|
||||
};
|
||||
|
||||
self.register_wf_obligation(
|
||||
@@ -1035,8 +985,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// inherent impl, we need to record the
|
||||
// `T` for posterity (see `UserSelfTy` for
|
||||
// details).
|
||||
let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw;
|
||||
user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
|
||||
// Generated desugaring code may have a path without a self.
|
||||
user_self_ty = self_ty.map(|self_ty| UserSelfTy {
|
||||
impl_def_id: container_id,
|
||||
self_ty: self_ty.raw,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1374,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, code, span, args))]
|
||||
fn add_required_obligations_with_code(
|
||||
pub(crate) fn add_required_obligations_with_code(
|
||||
&self,
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
|
||||
@@ -419,7 +419,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
|
||||
@@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, lis
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath};
|
||||
use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath, is_range_literal};
|
||||
use rustc_hir_analysis::check::potentially_plural_count;
|
||||
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
|
||||
use rustc_index::IndexVec;
|
||||
@@ -1290,10 +1290,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
|
||||
}
|
||||
QPath::LangItem(lang_item, span) => {
|
||||
let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
|
||||
(res, LoweredTy::from_raw(self, path_span, ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2051,8 +2047,9 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> {
|
||||
fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) {
|
||||
if let ty::Adt(adt, _) = ty.kind()
|
||||
&& self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
|
||||
&& let hir::ExprKind::Struct(hir::QPath::LangItem(hir::LangItem::RangeFull, _), [], _) =
|
||||
expr.kind
|
||||
&& is_range_literal(expr)
|
||||
&& let hir::ExprKind::Struct(&path, [], _) = expr.kind
|
||||
&& self.tcx().qpath_is_lang_item(path, hir::LangItem::RangeFull)
|
||||
{
|
||||
// We have `Foo(a, .., c)`, where the user might be trying to use the "rest" syntax
|
||||
// from default field values, which is not supported on tuples.
|
||||
|
||||
@@ -11,7 +11,7 @@ use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind,
|
||||
GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
|
||||
WherePredicateKind, expr_needs_parens,
|
||||
WherePredicateKind, expr_needs_parens, is_range_literal,
|
||||
};
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_hir_analysis::suggest_impl_trait;
|
||||
@@ -1664,7 +1664,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
match expr.kind {
|
||||
ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [start, end], _) => {
|
||||
ExprKind::Struct(&qpath, [start, end], _)
|
||||
if is_range_literal(expr)
|
||||
&& self.tcx.qpath_is_lang_item(qpath, LangItem::Range) =>
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
start.expr.span.shrink_to_hi().with_hi(end.expr.span.lo()),
|
||||
"remove the unnecessary `.` operator for a floating point literal",
|
||||
@@ -1673,24 +1676,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
true
|
||||
}
|
||||
ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, ..), [start], _) => {
|
||||
ExprKind::Struct(&qpath, [arg], _)
|
||||
if is_range_literal(expr)
|
||||
&& let Some(qpath @ (LangItem::RangeFrom | LangItem::RangeTo)) =
|
||||
self.tcx.qpath_lang_item(qpath) =>
|
||||
{
|
||||
let range_span = expr.span.parent_callsite().unwrap();
|
||||
match qpath {
|
||||
LangItem::RangeFrom => {
|
||||
err.span_suggestion_verbose(
|
||||
range_span.with_lo(start.expr.span.hi()),
|
||||
range_span.with_lo(arg.expr.span.hi()),
|
||||
"remove the unnecessary `.` operator for a floating point literal",
|
||||
'.',
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
true
|
||||
}
|
||||
ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, ..), [end], _) => {
|
||||
let range_span = expr.span.parent_callsite().unwrap();
|
||||
_ => {
|
||||
err.span_suggestion_verbose(
|
||||
range_span.until(end.expr.span),
|
||||
range_span.until(arg.expr.span),
|
||||
"remove the unnecessary `.` operator and add an integer part for a floating point literal",
|
||||
"0.",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
ExprKind::Lit(Spanned {
|
||||
@@ -3497,11 +3506,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if !hir::is_range_literal(expr) {
|
||||
return;
|
||||
}
|
||||
let hir::ExprKind::Struct(hir::QPath::LangItem(LangItem::Range, ..), [start, end], _) =
|
||||
expr.kind
|
||||
else {
|
||||
let hir::ExprKind::Struct(&qpath, [start, end], _) = expr.kind else {
|
||||
return;
|
||||
};
|
||||
if !self.tcx.qpath_is_lang_item(qpath, LangItem::Range) {
|
||||
return;
|
||||
}
|
||||
if let hir::Node::ExprField(_) = self.tcx.parent_hir_node(expr.hir_id) {
|
||||
// Ignore `Foo { field: a..Default::default() }`
|
||||
return;
|
||||
|
||||
@@ -19,7 +19,9 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr};
|
||||
use rustc_hir::{
|
||||
self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr, is_range_literal,
|
||||
};
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
|
||||
@@ -2412,22 +2414,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let SelfSource::MethodCall(expr) = source {
|
||||
for (_, parent) in tcx.hir_parent_iter(expr.hir_id).take(5) {
|
||||
if let Node::Expr(parent_expr) = parent {
|
||||
if !is_range_literal(parent_expr) {
|
||||
continue;
|
||||
}
|
||||
let lang_item = match parent_expr.kind {
|
||||
ExprKind::Struct(qpath, _, _) => match *qpath {
|
||||
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
|
||||
QPath::LangItem(LangItem::RangeCopy, ..) => Some(LangItem::RangeCopy),
|
||||
QPath::LangItem(LangItem::RangeInclusiveCopy, ..) => {
|
||||
Some(LangItem::RangeInclusiveCopy)
|
||||
}
|
||||
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
|
||||
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
|
||||
Some(LangItem::RangeToInclusive)
|
||||
}
|
||||
ExprKind::Struct(qpath, _, _) => match tcx.qpath_lang_item(*qpath) {
|
||||
Some(
|
||||
lang_item @ (LangItem::Range
|
||||
| LangItem::RangeCopy
|
||||
| LangItem::RangeInclusiveCopy
|
||||
| LangItem::RangeTo
|
||||
| LangItem::RangeToInclusive),
|
||||
) => Some(lang_item),
|
||||
_ => None,
|
||||
},
|
||||
ExprKind::Call(func, _) => match func.kind {
|
||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||
ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
|
||||
ExprKind::Path(qpath)
|
||||
if tcx.qpath_is_lang_item(qpath, LangItem::RangeInclusiveNew) =>
|
||||
{
|
||||
Some(LangItem::RangeInclusiveStruct)
|
||||
}
|
||||
_ => None,
|
||||
|
||||
@@ -718,7 +718,7 @@ impl<'tcx> LateContext<'tcx> {
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, path) => path.res,
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
hir::QPath::TypeRelative(..) => self
|
||||
.maybe_typeck_results()
|
||||
.filter(|typeck_results| typeck_results.hir_owner == id.owner)
|
||||
.or_else(|| {
|
||||
|
||||
@@ -132,8 +132,8 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
|
||||
&& let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) =
|
||||
&parent_expr.kind
|
||||
&& let hir::ExprKind::Call(path, [_]) = &arg.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoIterIntoIter, ..)) =
|
||||
&path.kind
|
||||
&& let hir::ExprKind::Path(qpath) = path.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter)
|
||||
{
|
||||
Some(ShadowedIntoIterDiagSub::RemoveIntoIter {
|
||||
span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
|
||||
@@ -2598,8 +2598,6 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: Loc
|
||||
// FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty
|
||||
// contains const arguments. Is there a *concise* way to check for this?
|
||||
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple,
|
||||
// FIXME: Can they contain const arguments and thus leak private struct fields?
|
||||
hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple,
|
||||
_ => Complex,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::lints::DelayedLint;
|
||||
use rustc_hir::*;
|
||||
@@ -203,6 +203,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn qpath_is_lang_item(self, qpath: QPath<'_>, lang_item: LangItem) -> bool {
|
||||
self.qpath_lang_item(qpath) == Some(lang_item)
|
||||
}
|
||||
|
||||
/// This does not use typeck results since this is intended to be used with generated code.
|
||||
pub fn qpath_lang_item(self, qpath: QPath<'_>) -> Option<LangItem> {
|
||||
if let QPath::Resolved(_, path) = qpath
|
||||
&& let Res::Def(_, def_id) = path.res
|
||||
{
|
||||
return self.lang_items().from_def_id(def_id);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Hashes computed by [`TyCtxt::hash_owner_nodes`] if necessary.
|
||||
|
||||
@@ -266,7 +266,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, path) => path.res,
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
hir::QPath::TypeRelative(..) => self
|
||||
.type_dependent_def(id)
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
}
|
||||
|
||||
@@ -425,7 +425,6 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1268,7 +1268,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
Res::Def(kind, def_id) => Some((kind, def_id)),
|
||||
_ => None,
|
||||
},
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
|
||||
hir::QPath::TypeRelative(..) => {
|
||||
match self.maybe_typeck_results {
|
||||
Some(typeck_results) => typeck_results.type_dependent_def(id),
|
||||
// FIXME: Check type-relative associated types in signatures.
|
||||
@@ -1287,9 +1287,6 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
|
||||
if !self.item_is_accessible(def_id) && !is_local_static {
|
||||
let name = match *qpath {
|
||||
hir::QPath::LangItem(it, ..) => {
|
||||
self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
|
||||
}
|
||||
hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
|
||||
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
|
||||
};
|
||||
|
||||
@@ -517,6 +517,7 @@ symbols! {
|
||||
async_fn_track_caller,
|
||||
async_fn_traits,
|
||||
async_for_loop,
|
||||
async_gen_internals,
|
||||
async_iterator,
|
||||
async_iterator_poll_next,
|
||||
async_trait_bounds,
|
||||
|
||||
@@ -1147,7 +1147,6 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
|
||||
Box::new(segment.into_iter())
|
||||
}
|
||||
hir::QPath::LangItem(_, _) => Box::new(iter::empty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1703,7 +1703,6 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
|
||||
trait_,
|
||||
}))
|
||||
}
|
||||
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,6 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
|
||||
let segments = match *p {
|
||||
hir::QPath::Resolved(_, path) => &path.segments,
|
||||
hir::QPath::TypeRelative(_, segment) => return segment.ident.to_string(),
|
||||
hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
|
||||
};
|
||||
|
||||
join_path_idents(segments.iter().map(|seg| seg.ident))
|
||||
|
||||
@@ -300,7 +300,6 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
||||
intravisit::walk_path(self, path);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -550,7 +550,6 @@ fn get_item_name(item: &Item<'_>) -> Option<String> {
|
||||
// This case doesn't exist in the clippy tests codebase.
|
||||
None
|
||||
},
|
||||
QPath::LangItem(_, _) => None,
|
||||
}
|
||||
} else {
|
||||
// Impls for anything that isn't a named type can be skipped.
|
||||
|
||||
@@ -4,7 +4,7 @@ use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::{is_in_const_context, is_in_test};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, QPath, RustcVersion, StabilityLevel, StableSince};
|
||||
use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, RustcVersion, StabilityLevel, StableSince};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::impl_lint_pass;
|
||||
@@ -193,10 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv {
|
||||
self.emit_lint_if_under_msrv(cx, method_did, expr.hir_id, span);
|
||||
}
|
||||
},
|
||||
// Desugaring into function calls by the compiler will use `QPath::LangItem` variants. Those should
|
||||
// not be linted as they will not be generated in older compilers if the function is not available,
|
||||
// and the compiler is allowed to call unstable functions.
|
||||
ExprKind::Path(qpath @ (QPath::Resolved(..) | QPath::TypeRelative(..))) => {
|
||||
ExprKind::Path(qpath) => {
|
||||
if let Some(path_def_id) = cx.qpath_res(&qpath, expr.hir_id).opt_def_id() {
|
||||
self.emit_lint_if_under_msrv(cx, path_def_id, expr.hir_id, expr.span);
|
||||
}
|
||||
@@ -206,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv {
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
|
||||
if let hir::TyKind::Path(qpath @ (QPath::Resolved(..) | QPath::TypeRelative(..))) = hir_ty.kind
|
||||
if let hir::TyKind::Path(qpath) = hir_ty.kind
|
||||
&& let Some(ty_def_id) = cx.qpath_res(&qpath, hir_ty.hir_id).opt_def_id()
|
||||
// `CStr` and `CString` have been moved around but have been available since Rust 1.0.0
|
||||
&& !matches!(cx.tcx.get_diagnostic_name(ty_def_id), Some(sym::cstr_type | sym::cstring_type))
|
||||
|
||||
@@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
|
||||
let note = "the suggestion might not be applicable in constant blocks";
|
||||
let ty = cx.typeck_results().expr_ty(array).peel_refs();
|
||||
let allowed_in_tests = self.allow_indexing_slicing_in_tests && is_in_test(cx.tcx, expr.hir_id);
|
||||
if let Some(range) = higher::Range::hir(index) {
|
||||
if let Some(range) = higher::Range::hir(cx, index) {
|
||||
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
|
||||
if let ty::Array(_, s) = ty.kind() {
|
||||
let size: u128 = if let Some(size) = s.try_to_target_usize(cx.tcx) {
|
||||
|
||||
@@ -178,7 +178,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
||||
Finite
|
||||
}
|
||||
},
|
||||
ExprKind::Struct(..) => higher::Range::hir(expr).is_some_and(|r| r.end.is_none()).into(),
|
||||
ExprKind::Struct(..) => higher::Range::hir(cx, expr).is_some_and(|r| r.end.is_none()).into(),
|
||||
_ => Finite,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_abi::Size;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
||||
@@ -58,7 +58,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Match(scrutinee, _, MatchSource::AwaitDesugar) = expr.kind
|
||||
&& let ExprKind::Call(func, [arg]) = scrutinee.kind
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::IntoFutureIntoFuture, ..)) = func.kind
|
||||
&& let ExprKind::Path(qpath) = func.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoFutureIntoFuture)
|
||||
&& !expr.span.from_expansion()
|
||||
&& let ty = cx.typeck_results().expr_ty(arg)
|
||||
&& let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
|
||||
|
||||
@@ -131,7 +131,7 @@ fn check_index_usage<'tcx>(
|
||||
fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
|
||||
for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) {
|
||||
match node {
|
||||
Node::Expr(expr) if higher::Range::hir(expr).is_some() => {},
|
||||
Node::Expr(expr) if higher::Range::hir(cx, expr).is_some() => {},
|
||||
Node::ExprField(_) => {},
|
||||
Node::Expr(expr) => return Some(expr),
|
||||
_ => break,
|
||||
|
||||
@@ -29,7 +29,7 @@ pub(super) fn check<'tcx>(
|
||||
end: Some(end),
|
||||
limits,
|
||||
span: _,
|
||||
}) = higher::Range::hir(arg)
|
||||
}) = higher::Range::hir(cx, arg)
|
||||
// the var must be a single name
|
||||
&& let PatKind::Binding(_, canonical_id, _, _) = pat.kind
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
|
||||
end: Some(end),
|
||||
limits: RangeLimits::HalfOpen,
|
||||
span: _,
|
||||
}) = higher::Range::hir(arg)
|
||||
}) = higher::Range::hir(cx, arg)
|
||||
&& let ExprKind::Lit(Spanned {
|
||||
node: LitKind::Int(Pu128(0), _),
|
||||
..
|
||||
|
||||
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
|
||||
start: Some(start),
|
||||
end: Some(end),
|
||||
..
|
||||
}) = higher::Range::hir(arg)
|
||||
}) = higher::Range::hir(cx, arg)
|
||||
&& let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end))
|
||||
&& (mut_id_start.is_some() || mut_id_end.is_some())
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(
|
||||
ref end,
|
||||
limits,
|
||||
span,
|
||||
}) = higher::Range::hir(arg)
|
||||
}) = higher::Range::hir(cx, arg)
|
||||
// the var must be a single name
|
||||
&& let PatKind::Binding(_, canonical_id, ident, _) = pat.kind
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ pub(super) fn check<'tcx>(
|
||||
arg_snip = format!("({arg_snip})").into();
|
||||
}
|
||||
|
||||
if clippy_utils::higher::Range::hir(arg_expression).is_some() {
|
||||
if clippy_utils::higher::Range::hir(cx, arg_expression).is_some() {
|
||||
let range_expr = snippet(cx, arg_expression.span, "?").to_string();
|
||||
|
||||
let sugg = snippet(cx, arg_expression.span, "..");
|
||||
|
||||
@@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
|
||||
end: Some(end),
|
||||
limits: RangeLimits::Closed,
|
||||
span: _,
|
||||
}) = higher::Range::hir(receiver)
|
||||
}) = higher::Range::hir(cx, receiver)
|
||||
&& !matches!(cx.typeck_results().expr_ty(arg).peel_refs().kind(), ty::Param(_))
|
||||
{
|
||||
let arg = peel_ref_operators(cx, arg);
|
||||
|
||||
@@ -207,7 +207,7 @@ fn is_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
ExprKind::Index(arr, range, _) => match arr.kind {
|
||||
ExprKind::Array([]) => is_range_literal(range),
|
||||
ExprKind::Array(_) => {
|
||||
let Some(range) = clippy_utils::higher::Range::hir(range) else {
|
||||
let Some(range) = clippy_utils::higher::Range::hir(cx, range) else {
|
||||
return false;
|
||||
};
|
||||
range.end.is_some_and(|e| clippy_utils::is_integer_const(cx, e, 0))
|
||||
|
||||
@@ -237,7 +237,7 @@ fn find_stripping<'tcx>(
|
||||
if is_ref_str(self.cx, ex)
|
||||
&& let unref = peel_ref(ex)
|
||||
&& let ExprKind::Index(indexed, index, _) = &unref.kind
|
||||
&& let Some(higher::Range { start, end, .. }) = higher::Range::hir(index)
|
||||
&& let Some(higher::Range { start, end, .. }) = higher::Range::hir(self.cx, index)
|
||||
&& let ExprKind::Path(path) = &indexed.kind
|
||||
&& self.cx.qpath_res(path, ex.hir_id) == self.target
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::option_arg_ty;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::LangItem::ResultErr;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{hygiene, sym};
|
||||
@@ -23,8 +23,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
|
||||
// val,
|
||||
// };
|
||||
if let ExprKind::Call(match_fun, [try_arg]) = scrutinee.kind
|
||||
&& let ExprKind::Path(ref match_fun_path) = match_fun.kind
|
||||
&& matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..))
|
||||
&& let ExprKind::Path(match_fun_path) = match_fun.kind
|
||||
&& cx.tcx.qpath_is_lang_item(match_fun_path, LangItem::TryTraitBranch)
|
||||
&& let ExprKind::Call(err_fun, [err_arg]) = try_arg.kind
|
||||
&& err_fun.res(cx).ctor_parent(cx).is_lang_item(cx, ResultErr)
|
||||
&& let Some(return_ty) = find_return_type(cx, &expr.kind)
|
||||
|
||||
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::is_copy;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingMode, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
|
||||
use rustc_hir::{BindingMode, ByRef, Expr, ExprKind, MatchSource, Node, PatKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
@@ -47,7 +47,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>)
|
||||
// ? is a Call, makes sure not to rec *x?, but rather (*x)?
|
||||
ExprKind::Call(hir_callee, [_]) => matches!(
|
||||
hir_callee.kind,
|
||||
ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, ..))
|
||||
ExprKind::Path(qpath)
|
||||
if cx.tcx.qpath_is_lang_item(qpath, rustc_hir::LangItem::TryTraitBranch)
|
||||
),
|
||||
ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true,
|
||||
ExprKind::Match(_, _, MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar)
|
||||
|
||||
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal
|
||||
end: None,
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
span: _,
|
||||
}) = higher::Range::hir(index_expr)
|
||||
}) = higher::Range::hir(cx, index_expr)
|
||||
&& let hir::ExprKind::Lit(start_lit) = &start_expr.kind
|
||||
&& let ast::LitKind::Int(start_idx, _) = start_lit.node
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ pub(super) fn check(
|
||||
method_name_span: Span,
|
||||
) {
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
if let Some(range) = higher::Range::hir(receiver)
|
||||
if let Some(range) = higher::Range::hir(cx, receiver)
|
||||
&& let ExprKind::Closure(Closure { body, .. }) = arg.kind
|
||||
&& let body_hir = cx.tcx.hir_body(*body)
|
||||
&& let Body {
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::RANGE_ZIP_WITH_LEN;
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, zip_arg: &'tcx Expr<'_>) {
|
||||
if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
|
||||
// range expression in `.zip()` call: `0..x.len()`
|
||||
&& let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg)
|
||||
&& let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(cx, zip_arg)
|
||||
&& is_integer_const(cx, start, 0)
|
||||
// `.len()` call
|
||||
&& let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind
|
||||
|
||||
@@ -9,7 +9,7 @@ use clippy_utils::{paths, sym};
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
BindingMode, Expr, ExprKind, HirId, LangItem, LetStmt, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind,
|
||||
BindingMode, Expr, ExprKind, HirId, LangItem, LetStmt, MatchSource, Node, Pat, PatKind, Stmt, StmtKind,
|
||||
};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
@@ -332,12 +332,12 @@ fn parse_iter_usage<'tcx>(
|
||||
let (unwrap_kind, span) = if let Some((_, Node::Expr(e))) = iter.next() {
|
||||
match e.kind {
|
||||
ExprKind::Call(
|
||||
Expr {
|
||||
kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)),
|
||||
&Expr {
|
||||
kind: ExprKind::Path(qpath),
|
||||
..
|
||||
},
|
||||
[_],
|
||||
) => {
|
||||
) if cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitBranch) => {
|
||||
let parent_span = e.span.parent_callsite().unwrap();
|
||||
if parent_span.ctxt() == ctxt {
|
||||
(Some(UnwrapKind::QuestionMark), parent_span)
|
||||
|
||||
@@ -181,7 +181,6 @@ pub(super) fn check_function(cx: &LateContext<'_>, expr: &Expr<'_>, callee: &Exp
|
||||
QPath::TypeRelative(_, seg) => Some(SpansKind::Fn {
|
||||
fn_span: seg.ident.span,
|
||||
}),
|
||||
QPath::LangItem(_, _) => unreachable!("`TryFrom` and `TryInto` are not lang items"),
|
||||
};
|
||||
|
||||
check(
|
||||
|
||||
@@ -220,14 +220,14 @@ impl<'hir> IndexEntry<'hir> {
|
||||
///
|
||||
/// E.g. for `5` this returns `Some(5)`, for `..5` this returns `Some(4)`,
|
||||
/// for `..=5` this returns `Some(5)`
|
||||
fn upper_index_expr(expr: &Expr<'_>) -> Option<usize> {
|
||||
fn upper_index_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<usize> {
|
||||
if let ExprKind::Lit(lit) = &expr.kind
|
||||
&& let LitKind::Int(Pu128(index), _) = lit.node
|
||||
{
|
||||
Some(index as usize)
|
||||
} else if let Some(higher::Range {
|
||||
end: Some(end), limits, ..
|
||||
}) = higher::Range::hir(expr)
|
||||
}) = higher::Range::hir(cx, expr)
|
||||
&& let ExprKind::Lit(lit) = &end.kind
|
||||
&& let LitKind::Int(Pu128(index @ 1..), _) = lit.node
|
||||
{
|
||||
@@ -244,7 +244,7 @@ fn upper_index_expr(expr: &Expr<'_>) -> Option<usize> {
|
||||
fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnindexMap<u64, Vec<IndexEntry<'hir>>>) {
|
||||
if let ExprKind::Index(slice, index_lit, _) = expr.kind
|
||||
&& cx.typeck_results().expr_ty_adjusted(slice).peel_refs().is_slice()
|
||||
&& let Some(index) = upper_index_expr(index_lit)
|
||||
&& let Some(index) = upper_index_expr(cx, index_lit)
|
||||
{
|
||||
let hash = hash_expr(cx, slice);
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) {
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for NeedlessParensOnRangeLiterals {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let Some(higher::Range { start, end, .. }) = higher::Range::hir(expr) {
|
||||
if let Some(higher::Range { start, end, .. }) = higher::Range::hir(cx, expr) {
|
||||
if let Some(start) = start {
|
||||
check_for_parens(cx, start, true);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||
use clippy_utils::res::MaybeQPath;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{Block, Body, Expr, ExprKind, LangItem, MatchSource, QPath};
|
||||
use rustc_hir::{Block, Body, Expr, ExprKind, LangItem, MatchSource};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
||||
@@ -105,7 +105,8 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
}
|
||||
&& let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind
|
||||
&& let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind
|
||||
&& let ExprKind::Path(qpath) = called.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitBranch)
|
||||
&& expr.span.eq_ctxt(inner_expr.span)
|
||||
&& let expr_ty = cx.typeck_results().expr_ty(expr)
|
||||
&& let inner_ty = cx.typeck_results().expr_ty(inner_expr)
|
||||
|
||||
@@ -530,11 +530,13 @@ impl QuestionMark {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_try_block(bl: &Block<'_>) -> bool {
|
||||
fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool {
|
||||
if let Some(expr) = bl.expr
|
||||
&& let ExprKind::Call(callee, [_]) = expr.kind
|
||||
&& let ExprKind::Path(qpath) = callee.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitFromOutput)
|
||||
{
|
||||
callee.opt_lang_path() == Some(LangItem::TryTraitFromOutput)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -590,8 +592,8 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_block(&mut self, _: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
|
||||
if is_try_block(block) {
|
||||
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
|
||||
if is_try_block(cx, block) {
|
||||
*self
|
||||
.try_block_depth_stack
|
||||
.last_mut()
|
||||
@@ -607,8 +609,8 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
|
||||
self.try_block_depth_stack.pop();
|
||||
}
|
||||
|
||||
fn check_block_post(&mut self, _: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
|
||||
if is_try_block(block) {
|
||||
fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
|
||||
if is_try_block(cx, block) {
|
||||
*self
|
||||
.try_block_depth_stack
|
||||
.last_mut()
|
||||
|
||||
@@ -2,7 +2,7 @@ use clippy_config::Conf;
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::res::{MaybeQPath, MaybeResPath};
|
||||
use clippy_utils::res::MaybeResPath;
|
||||
use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
@@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass, Lint};
|
||||
use rustc_middle::ty::{self, ClauseKind, GenericArgKind, PredicatePolarity, Ty};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::{DesugaringKind, Span, sym};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
declare_clippy_lint! {
|
||||
@@ -368,7 +368,9 @@ fn can_switch_ranges<'tcx>(
|
||||
// Check if `expr` is the argument of a compiler-generated `IntoIter::into_iter(expr)`
|
||||
if let ExprKind::Call(func, [arg]) = parent_expr.kind
|
||||
&& arg.hir_id == use_ctxt.child_id
|
||||
&& func.opt_lang_path() == Some(LangItem::IntoIterIntoIter)
|
||||
&& let ExprKind::Path(qpath) = func.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter)
|
||||
&& parent_expr.span.is_desugaring(DesugaringKind::ForLoop)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -501,7 +503,7 @@ fn check_range_switch<'tcx>(
|
||||
msg: &'static str,
|
||||
operator: &str,
|
||||
) {
|
||||
if let Some(range) = higher::Range::hir(expr)
|
||||
if let Some(range) = higher::Range::hir(cx, expr)
|
||||
&& let higher::Range {
|
||||
start,
|
||||
end: Some(end),
|
||||
@@ -569,7 +571,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
end: Some(end),
|
||||
limits,
|
||||
span,
|
||||
}) = higher::Range::hir(expr)
|
||||
}) = higher::Range::hir(cx, expr)
|
||||
&& let ty = cx.typeck_results().expr_ty(start)
|
||||
&& let ty::Int(_) | ty::Uint(_) = ty.kind()
|
||||
&& let ecx = ConstEvalCtxt::new(cx)
|
||||
|
||||
@@ -97,7 +97,6 @@ fn extract_fn_ty<'tcx>(
|
||||
// let a: String = String::new();
|
||||
// let a: String = String::get_string();
|
||||
hir::QPath::TypeRelative(..) => func_hir_id_to_func_ty(cx, call.hir_id),
|
||||
hir::QPath::LangItem(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use clippy_utils::{
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, Expr, ExprKind, HirId, LangItem, MatchSource, QPath, StmtKind};
|
||||
use rustc_hir::{Body, Expr, ExprKind, HirId, LangItem, MatchSource, StmtKind};
|
||||
use rustc_lint::{LateContext, Level, LintContext};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
@@ -134,7 +134,8 @@ fn check_final_expr<'tcx>(
|
||||
let replacement = if let Some(inner_expr) = inner {
|
||||
// if desugar of `do yeet`, don't lint
|
||||
if let ExprKind::Call(path_expr, [_]) = inner_expr.kind
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, ..)) = path_expr.kind
|
||||
&& let ExprKind::Path(qpath) = path_expr.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitFromYeet)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use clippy_utils::ty::implements_trait;
|
||||
use clippy_utils::{is_no_std_crate, sym};
|
||||
use rustc_ast::{LitIntType, LitKind, UintTy};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr};
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, StructTailExpr};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
@@ -86,12 +86,12 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
|
||||
return;
|
||||
};
|
||||
|
||||
let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], StructTailExpr::None) = inner_expr.kind
|
||||
let ExprKind::Struct(&qpath, [start, end], StructTailExpr::None) = inner_expr.kind
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if matches!(lang_item, LangItem::Range)
|
||||
if cx.tcx.qpath_is_lang_item(qpath, LangItem::Range)
|
||||
&& let ty = cx.typeck_results().expr_ty(start.expr)
|
||||
&& let Some(snippet) = span.get_source_text(cx)
|
||||
// `is_from_proc_macro` will skip any `vec![]`. Let's not!
|
||||
|
||||
@@ -6,7 +6,7 @@ use clippy_utils::{
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath};
|
||||
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
@@ -266,7 +266,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
||||
&& expressions[0].1.is_empty()
|
||||
|
||||
// Check for slicer
|
||||
&& let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind
|
||||
&& let ExprKind::Struct(&qpath, _, _) = right.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::Range)
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let string_expression = &expressions[0].0;
|
||||
|
||||
@@ -655,7 +655,6 @@ impl Types {
|
||||
}
|
||||
}
|
||||
},
|
||||
QPath::LangItem(..) => {},
|
||||
}
|
||||
},
|
||||
TyKind::Path(ref qpath) => {
|
||||
|
||||
@@ -106,7 +106,6 @@ fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Op
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
QPath::LangItem(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +290,6 @@ fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>,
|
||||
}
|
||||
get_hir_ty_def_id(tcx, *ty) == Some(implemented_ty_id)
|
||||
},
|
||||
QPath::LangItem(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
|
||||
}
|
||||
},
|
||||
hir::QPath::TypeRelative(_, path) => path.ident.name,
|
||||
hir::QPath::LangItem(..) => return,
|
||||
};
|
||||
match constructor_symbol {
|
||||
sym::Some | sym::Ok if path.ident.name == sym::map => (),
|
||||
|
||||
@@ -192,9 +192,9 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
|
||||
|
||||
fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option<IoOp> {
|
||||
inner = unpack_match(inner);
|
||||
inner = unpack_try(inner);
|
||||
inner = unpack_try(cx, inner);
|
||||
inner = unpack_call_chain(inner);
|
||||
inner = unpack_await(inner);
|
||||
inner = unpack_await(cx, inner);
|
||||
// we type-check it to get whether it's a read/write or their vectorized forms
|
||||
// and keep only the ones that are produce io amount
|
||||
check_io_mode(cx, inner)
|
||||
@@ -256,12 +256,10 @@ fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
expr
|
||||
}
|
||||
|
||||
fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
fn unpack_try<'a>(cx: &LateContext<'_>, mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
while let ExprKind::Call(func, [arg_0]) = expr.kind
|
||||
&& matches!(
|
||||
func.kind,
|
||||
ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
|
||||
)
|
||||
&& let ExprKind::Path(qpath) = func.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, hir::LangItem::TryTraitBranch)
|
||||
{
|
||||
expr = arg_0;
|
||||
}
|
||||
@@ -277,13 +275,11 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
|
||||
/// If `expr` is an (e).await, return the inner expression "e" that's being
|
||||
/// waited on. Otherwise return None.
|
||||
fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
fn unpack_await<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind
|
||||
&& let ExprKind::Call(func, [arg_0]) = expr.kind
|
||||
&& matches!(
|
||||
func.kind,
|
||||
ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
|
||||
)
|
||||
&& let ExprKind::Path(qpath) = func.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, hir::LangItem::IntoFutureIntoFuture)
|
||||
{
|
||||
return arg_0;
|
||||
}
|
||||
|
||||
@@ -270,9 +270,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn qpath(&self, qpath: &Binding<&QPath<'_>>, hir_id_binding: &str, hir_id: HirId) {
|
||||
if let QPath::LangItem(lang_item, ..) = *qpath.value {
|
||||
chain!(self, "matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _))");
|
||||
} else if let Some(def_id) = self.cx.qpath_res(qpath.value, hir_id).opt_def_id()
|
||||
if let Some(def_id) = self.cx.qpath_res(qpath.value, hir_id).opt_def_id()
|
||||
&& !def_id.is_local()
|
||||
{
|
||||
bind!(self, def_id);
|
||||
|
||||
@@ -121,7 +121,6 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
|
||||
(start, end)
|
||||
},
|
||||
QPath::TypeRelative(_, name) => (Pat::Str(""), Pat::Sym(name.ident.name)),
|
||||
QPath::LangItem(..) => (Pat::Str(""), Pat::Str("")),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,6 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
||||
QPath::TypeRelative(_, name) => {
|
||||
self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, !args.is_empty());
|
||||
},
|
||||
QPath::LangItem(..) => self.eagerness = Lazy,
|
||||
},
|
||||
_ => self.eagerness = Lazy,
|
||||
},
|
||||
|
||||
@@ -215,14 +215,12 @@ pub struct Range<'a> {
|
||||
impl<'a> Range<'a> {
|
||||
/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
|
||||
#[expect(clippy::similar_names)]
|
||||
pub fn hir(expr: &'a Expr<'_>) -> Option<Range<'a>> {
|
||||
pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<Range<'a>> {
|
||||
let span = expr.range_span()?;
|
||||
match expr.kind {
|
||||
ExprKind::Call(path, [arg1, arg2])
|
||||
if matches!(
|
||||
path.kind,
|
||||
ExprKind::Path(QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..))
|
||||
) =>
|
||||
if let ExprKind::Path(qpath) = path.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, hir::LangItem::RangeInclusiveNew) =>
|
||||
{
|
||||
Some(Range {
|
||||
start: Some(arg1),
|
||||
@@ -231,14 +229,14 @@ impl<'a> Range<'a> {
|
||||
span,
|
||||
})
|
||||
},
|
||||
ExprKind::Struct(path, fields, StructTailExpr::None) => match (path, fields) {
|
||||
(QPath::LangItem(hir::LangItem::RangeFull, ..), []) => Some(Range {
|
||||
ExprKind::Struct(&qpath, fields, StructTailExpr::None) => match (cx.tcx.qpath_lang_item(qpath)?, fields) {
|
||||
(hir::LangItem::RangeFull, []) => Some(Range {
|
||||
start: None,
|
||||
end: None,
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
span,
|
||||
}),
|
||||
(QPath::LangItem(hir::LangItem::RangeFrom, ..), [field]) if field.ident.name == sym::start => {
|
||||
(hir::LangItem::RangeFrom, [field]) if field.ident.name == sym::start => {
|
||||
Some(Range {
|
||||
start: Some(field.expr),
|
||||
end: None,
|
||||
@@ -246,7 +244,7 @@ impl<'a> Range<'a> {
|
||||
span,
|
||||
})
|
||||
},
|
||||
(QPath::LangItem(hir::LangItem::Range, ..), [field1, field2]) => {
|
||||
(hir::LangItem::Range, [field1, field2]) => {
|
||||
let (start, end) = match (field1.ident.name, field2.ident.name) {
|
||||
(sym::start, sym::end) => (field1.expr, field2.expr),
|
||||
(sym::end, sym::start) => (field2.expr, field1.expr),
|
||||
@@ -259,7 +257,7 @@ impl<'a> Range<'a> {
|
||||
span,
|
||||
})
|
||||
},
|
||||
(QPath::LangItem(hir::LangItem::RangeToInclusive, ..), [field]) if field.ident.name == sym::end => {
|
||||
(hir::LangItem::RangeToInclusive, [field]) if field.ident.name == sym::end => {
|
||||
Some(Range {
|
||||
start: None,
|
||||
end: Some(field.expr),
|
||||
@@ -267,7 +265,7 @@ impl<'a> Range<'a> {
|
||||
span,
|
||||
})
|
||||
},
|
||||
(QPath::LangItem(hir::LangItem::RangeTo, ..), [field]) if field.ident.name == sym::end => Some(Range {
|
||||
(hir::LangItem::RangeTo, [field]) if field.ident.name == sym::end => Some(Range {
|
||||
start: None,
|
||||
end: Some(field.expr),
|
||||
limits: ast::RangeLimits::HalfOpen,
|
||||
|
||||
@@ -555,7 +555,6 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||
(QPath::TypeRelative(lty, lseg), QPath::TypeRelative(rty, rseg)) => {
|
||||
self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
|
||||
},
|
||||
(QPath::LangItem(llang_item, ..), QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -1092,9 +1091,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
QPath::TypeRelative(_, path) => {
|
||||
self.hash_name(path.ident.name);
|
||||
},
|
||||
QPath::LangItem(lang_item, ..) => {
|
||||
std::mem::discriminant(lang_item).hash(&mut self.s);
|
||||
},
|
||||
}
|
||||
// self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
|
||||
}
|
||||
|
||||
@@ -361,7 +361,6 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
|
||||
match *path {
|
||||
QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
|
||||
QPath::TypeRelative(_, seg) => seg,
|
||||
QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1282,7 +1281,7 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
|
||||
/// If the given `Expr` is not some kind of range, the function returns `false`.
|
||||
pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if let Some(Range { start, end, limits, .. }) = Range::hir(expr) {
|
||||
if let Some(Range { start, end, limits, .. }) = Range::hir(cx, expr) {
|
||||
let start_is_none_or_min = start.is_none_or(|start| {
|
||||
if let rustc_ty::Adt(_, subst) = ty.kind()
|
||||
&& let bnd_ty = subst.type_at(0)
|
||||
|
||||
@@ -99,15 +99,6 @@ pub trait MaybeQPath<'a>: Copy {
|
||||
/// use for type dependant lookup.
|
||||
fn opt_qpath(self) -> Option<QPathId<'a>>;
|
||||
|
||||
/// If this node is a `QPath::LangItem` gets the item it resolves to.
|
||||
#[inline]
|
||||
fn opt_lang_path(self) -> Option<LangItem> {
|
||||
match self.opt_qpath() {
|
||||
Some((&QPath::LangItem(item, _), _)) => Some(item),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If this is a path gets its resolution. Returns `Res::Err` otherwise.
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
@@ -116,10 +107,10 @@ pub trait MaybeQPath<'a>: Copy {
|
||||
fn f(qpath: &QPath<'_>, id: HirId, typeck: &TypeckResults<'_>) -> Res {
|
||||
match *qpath {
|
||||
QPath::Resolved(_, p) => p.res,
|
||||
QPath::TypeRelative(..) | QPath::LangItem(..) if let Some((kind, id)) = typeck.ty_based_def(id) => {
|
||||
QPath::TypeRelative(..) if let Some((kind, id)) = typeck.ty_based_def(id) => {
|
||||
Res::Def(kind, id)
|
||||
},
|
||||
QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err,
|
||||
QPath::TypeRelative(..) => Res::Err,
|
||||
}
|
||||
}
|
||||
match self.opt_qpath() {
|
||||
@@ -148,7 +139,7 @@ pub trait MaybeQPath<'a>: Copy {
|
||||
{
|
||||
Res::Def(kind, id)
|
||||
},
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err,
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err,
|
||||
}
|
||||
}
|
||||
match self.opt_qpath() {
|
||||
@@ -168,7 +159,7 @@ pub trait MaybeQPath<'a>: Copy {
|
||||
QPath::TypeRelative(_, seg) if let Some((kind, id)) = typeck.ty_based_def(id) => {
|
||||
(Res::Def(kind, id), Some(seg))
|
||||
},
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => (Res::Err, None),
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) => (Res::Err, None),
|
||||
}
|
||||
}
|
||||
match self.opt_qpath() {
|
||||
@@ -202,7 +193,7 @@ pub trait MaybeQPath<'a>: Copy {
|
||||
},
|
||||
_,
|
||||
) if let Some((kind, id)) = typeck.ty_based_def(id) => Res::Def(kind, id),
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err,
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err,
|
||||
}
|
||||
}
|
||||
match self.opt_qpath() {
|
||||
@@ -244,7 +235,7 @@ pub trait MaybeQPath<'a>: Copy {
|
||||
{
|
||||
Res::Def(kind, id)
|
||||
},
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err,
|
||||
QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err,
|
||||
}
|
||||
}
|
||||
match self.opt_qpath() {
|
||||
|
||||
@@ -59,7 +59,7 @@ impl<'a> Sugg<'a> {
|
||||
pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> {
|
||||
let ctxt = expr.span.ctxt();
|
||||
let get_snippet = |span| snippet_with_context(cx, span, ctxt, "", &mut Applicability::Unspecified).0;
|
||||
snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(expr, get_snippet))
|
||||
snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(cx, expr, get_snippet))
|
||||
}
|
||||
|
||||
/// Convenience function around `hir_opt` for suggestions with a default
|
||||
@@ -115,7 +115,7 @@ impl<'a> Sugg<'a> {
|
||||
Box::new(Self::hir_with_context(cx, inner, ctxt, default, applicability)),
|
||||
)
|
||||
} else {
|
||||
Self::hir_from_snippet(expr, |span| {
|
||||
Self::hir_from_snippet(cx, expr, |span| {
|
||||
snippet_with_context(cx, span, ctxt, default, applicability).0
|
||||
})
|
||||
}
|
||||
@@ -127,8 +127,8 @@ impl<'a> Sugg<'a> {
|
||||
|
||||
/// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*`
|
||||
/// function variants of `Sugg`, since these use different snippet functions.
|
||||
fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
|
||||
if let Some(range) = higher::Range::hir(expr) {
|
||||
fn hir_from_snippet(cx: &LateContext<'_>, expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
|
||||
if let Some(range) = higher::Range::hir(cx, expr) {
|
||||
let op = AssocOp::Range(range.limits);
|
||||
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
|
||||
let end = range.end.map_or("".into(), |expr| get_snippet(expr.span));
|
||||
@@ -166,7 +166,7 @@ impl<'a> Sugg<'a> {
|
||||
| ExprKind::Use(..)
|
||||
| ExprKind::Err(_)
|
||||
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
|
||||
ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
|
||||
ExprKind::DropTemps(inner) => Self::hir_from_snippet(cx, inner, get_snippet),
|
||||
ExprKind::Assign(lhs, rhs, _) => {
|
||||
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
||||
},
|
||||
|
||||
@@ -197,19 +197,6 @@ fn qpath_certainty(cx: &LateContext<'_>, qpath: &QPath<'_>, resolves_to_type: bo
|
||||
QPath::TypeRelative(ty, path_segment) => {
|
||||
path_segment_certainty(cx, type_certainty(cx, ty), path_segment, resolves_to_type)
|
||||
},
|
||||
|
||||
QPath::LangItem(lang_item, ..) => cx
|
||||
.tcx
|
||||
.lang_items()
|
||||
.get(*lang_item)
|
||||
.map_or(Certainty::Uncertain, |def_id| {
|
||||
let generics = cx.tcx.generics_of(def_id);
|
||||
if generics.is_empty() {
|
||||
Certainty::Certain(if resolves_to_type { Some(def_id) } else { None })
|
||||
} else {
|
||||
Certainty::Uncertain
|
||||
}
|
||||
}),
|
||||
};
|
||||
debug_assert!(resolves_to_type || certainty.to_def_id().is_none());
|
||||
certainty
|
||||
|
||||
@@ -2,7 +2,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo
|
||||
&& let PatKind::Binding(BindingMode::NONE, _, name, None) = pat.kind
|
||||
&& name.as_str() == "y"
|
||||
&& let ExprKind::Struct(qpath, fields, None) = arg.kind
|
||||
&& matches!(qpath, QPath::LangItem(LangItem::Range, _))
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
|
||||
&& paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed
|
||||
&& fields.len() == 2
|
||||
&& fields[0].ident.as_str() == "start"
|
||||
&& let ExprKind::Lit(ref lit) = fields[0].expr.kind
|
||||
@@ -23,7 +24,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo
|
||||
if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
|
||||
&& let PatKind::Wild = pat.kind
|
||||
&& let ExprKind::Struct(qpath, fields, None) = arg.kind
|
||||
&& matches!(qpath, QPath::LangItem(LangItem::Range, _))
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
|
||||
&& paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed
|
||||
&& fields.len() == 2
|
||||
&& fields[0].ident.as_str() == "start"
|
||||
&& let ExprKind::Lit(ref lit) = fields[0].expr.kind
|
||||
@@ -43,7 +45,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo
|
||||
if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
|
||||
&& let PatKind::Wild = pat.kind
|
||||
&& let ExprKind::Struct(qpath, fields, None) = arg.kind
|
||||
&& matches!(qpath, QPath::LangItem(LangItem::Range, _))
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
|
||||
&& paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed
|
||||
&& fields.len() == 2
|
||||
&& fields[0].ident.as_str() == "start"
|
||||
&& let ExprKind::Lit(ref lit) = fields[0].expr.kind
|
||||
|
||||
@@ -2,7 +2,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo
|
||||
&& let PatKind::Binding(BindingMode::NONE, _, name, None) = pat.kind
|
||||
&& name.as_str() == "i"
|
||||
&& let ExprKind::Struct(qpath, fields, None) = arg.kind
|
||||
&& matches!(qpath, QPath::LangItem(LangItem::Range, _))
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
|
||||
&& paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed
|
||||
&& fields.len() == 2
|
||||
&& fields[0].ident.as_str() == "start"
|
||||
&& let ExprKind::Lit(ref lit) = fields[0].expr.kind
|
||||
|
||||
@@ -29,11 +29,9 @@ impl Foo<'_> {
|
||||
fn d<'a>(&self, x: &'a u32) { }
|
||||
|
||||
// FIXME: impl Traits printed as just `/*impl Trait*/`, ugh
|
||||
fn iter1<'a>(&self)
|
||||
-> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } }
|
||||
fn iter1<'a>(&self) -> /*impl Trait*/ { Range { start: 0, end: 1 } }
|
||||
|
||||
fn iter2(&self)
|
||||
-> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } }
|
||||
fn iter2(&self) -> /*impl Trait*/ { Range { start: 0, end: 1 } }
|
||||
}
|
||||
|
||||
fn a(x: Foo<'_>) { }
|
||||
|
||||
@@ -167,12 +167,12 @@ mod expressions {
|
||||
let x;
|
||||
{
|
||||
let _t =
|
||||
match #[lang = "into_iter"](x) {
|
||||
match into_iter(x) {
|
||||
mut iter =>
|
||||
loop {
|
||||
match #[lang = "next"](&mut iter) {
|
||||
#[lang = "None"] {} => break,
|
||||
#[lang = "Some"] { 0: _ } => { }
|
||||
match next(&mut iter) {
|
||||
None {} => break,
|
||||
Some { 0: _ } => { }
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -180,12 +180,12 @@ mod expressions {
|
||||
};
|
||||
{
|
||||
let _t =
|
||||
match #[lang = "into_iter"](x) {
|
||||
match into_iter(x) {
|
||||
mut iter =>
|
||||
'a: loop {
|
||||
match #[lang = "next"](&mut iter) {
|
||||
#[lang = "None"] {} => break,
|
||||
#[lang = "Some"] { 0: _ } => { }
|
||||
match next(&mut iter) {
|
||||
None {} => break,
|
||||
Some { 0: _ } => { }
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -253,10 +253,7 @@ mod expressions {
|
||||
}
|
||||
|
||||
/// ExprKind::TryBlock
|
||||
fn expr_try_block() {
|
||||
{ #[lang = "from_output"](()) }
|
||||
{ return; #[lang = "from_output"](()) }
|
||||
}
|
||||
fn expr_try_block() { { from_output(()) } { return; from_output(()) } }
|
||||
|
||||
/// ExprKind::Assign
|
||||
fn expr_assign() { let expr; expr = true; }
|
||||
@@ -273,14 +270,14 @@ mod expressions {
|
||||
/// ExprKind::Range
|
||||
fn expr_range() {
|
||||
let (lo, hi);
|
||||
#[lang = "RangeFull"] { };
|
||||
#[lang = "RangeTo"] { end: hi };
|
||||
#[lang = "RangeFrom"] { start: lo };
|
||||
#[lang = "Range"] { start: lo, end: hi };
|
||||
#[lang = "Range"] { start: lo, end: hi };
|
||||
#[lang = "RangeToInclusive"] { end: hi };
|
||||
#[lang = "range_inclusive_new"](lo, hi);
|
||||
#[lang = "range_inclusive_new"](-2, -1);
|
||||
RangeFull { };
|
||||
RangeTo { end: hi };
|
||||
RangeFrom { start: lo };
|
||||
Range { start: lo, end: hi };
|
||||
Range { start: lo, end: hi };
|
||||
RangeToInclusive { end: hi };
|
||||
range_inclusive_new(lo, hi);
|
||||
range_inclusive_new(-2, -1);
|
||||
}
|
||||
|
||||
/// ExprKind::Underscore
|
||||
@@ -373,20 +370,17 @@ mod expressions {
|
||||
/// ExprKind::Try
|
||||
fn expr_try() {
|
||||
let expr;
|
||||
match #[lang = "branch"](expr) {
|
||||
#[lang = "Break"] { 0: residual } => #[allow(unreachable_code)]
|
||||
return #[lang = "from_residual"](residual),
|
||||
#[lang = "Continue"] { 0: val } => #[allow(unreachable_code)]
|
||||
match branch(expr) {
|
||||
Break { 0: residual } => #[allow(unreachable_code)]
|
||||
return from_residual(residual),
|
||||
Continue { 0: val } => #[allow(unreachable_code)]
|
||||
val,
|
||||
};
|
||||
}
|
||||
/// ExprKind::Yield
|
||||
fn expr_yield() { yield (); yield true; }
|
||||
/// ExprKind::Yeet
|
||||
fn expr_yeet() {
|
||||
return #[lang = "from_yeet"](());
|
||||
return #[lang = "from_yeet"](0);
|
||||
}
|
||||
fn expr_yeet() { return from_yeet(()); return from_yeet(0); }
|
||||
/// ExprKind::Become
|
||||
fn expr_become() { become true; }
|
||||
/// ExprKind::IncludedBytes
|
||||
|
||||
Reference in New Issue
Block a user