Remove QPath::LangItem from for loops
This commit is contained in:
parent
7e51a763c9
commit
e289f27329
7 changed files with 54 additions and 29 deletions
|
|
@ -1804,7 +1804,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ForLoopKind::For => {
|
||||
// `Iterator::next(&mut iter)`
|
||||
let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
|
||||
self.expr_call_lang_item_qpath_fn(
|
||||
self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IteratorNext,
|
||||
arena_vec![self; ref_mut_iter],
|
||||
|
|
@ -1819,7 +1819,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// `&mut iter`
|
||||
let iter = self.expr_mut_addr_of(head_span, iter);
|
||||
// `Pin::new_unchecked(...)`
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_qpath_fn_mut(
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||
head_span,
|
||||
hir::LangItem::PinNewUnchecked,
|
||||
arena_vec![self; iter],
|
||||
|
|
@ -1854,7 +1854,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let match_expr = match loop_kind {
|
||||
ForLoopKind::For => {
|
||||
// `::std::iter::IntoIterator::into_iter(<head>)`
|
||||
let into_iter_expr = self.expr_call_lang_item_qpath_fn(
|
||||
let into_iter_expr = self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IntoIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
|
|
@ -1874,7 +1874,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.pat_ident_binding_mode(head_span, iter_ident, hir::BindingMode::REF_MUT);
|
||||
let iter = self.expr_ident_mut(head_span, iter_ident, async_iter_pat_id);
|
||||
// `Pin::new_unchecked(...)`
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_qpath_fn_mut(
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||
head_span,
|
||||
hir::LangItem::PinNewUnchecked,
|
||||
arena_vec![self; iter],
|
||||
|
|
@ -1889,7 +1889,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
));
|
||||
|
||||
// `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
|
||||
let iter = self.expr_call_lang_item_qpath_fn(
|
||||
let iter = self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IntoAsyncIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -763,6 +763,29 @@ 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::IntoIterIntoIter | LangItem::IteratorNext
|
||||
if expr.span.is_desugaring(DesugaringKind::ForLoop) =>
|
||||
{
|
||||
Some(ObligationCauseCode::ForLoopIterator)
|
||||
}
|
||||
_ => 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 {
|
||||
|
|
|
|||
|
|
@ -721,9 +721,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None
|
||||
}
|
||||
}
|
||||
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
|
||||
Some(ObligationCauseCode::ForLoopIterator)
|
||||
}
|
||||
hir::LangItem::TryTraitFromOutput
|
||||
| hir::LangItem::TryTraitFromResidual
|
||||
| hir::LangItem::TryTraitBranch => Some(ObligationCauseCode::QuestionMark),
|
||||
|
|
@ -1374,7 +1371,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,
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: _ } => { }
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue