diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 766c120a1f19..ad0c901ede0c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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()` - 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()` - 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], diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 47a1ad0d9489..566da884c194 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -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 in { }`. 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()` 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 `` 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, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 0b1c725ba408..aff663ba8f59 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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 { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index dde6b8ce9b8b..2404ec4c706d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -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, diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index d296ae46f43e..45c32bfd1d5c 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -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()), diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index ac2cc11d3020..5c1a906599d3 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -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; } diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 27cba6560300..b5fa442dd247 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -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: _ } => { } } }, };