From a96e21b199b866e7e2b05cc7f47e327574f6f456 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 1 Sep 2025 15:08:46 -0500 Subject: [PATCH] Remove QPath::LangItem from try --- compiler/rustc_ast_lowering/src/expr.rs | 4 +-- compiler/rustc_hir_typeck/src/expr.rs | 23 ++++++------ .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 35 ------------------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 5 +-- .../clippy_lints/src/matches/try_err.rs | 6 ++-- .../clippy_lints/src/methods/clone_on_copy.rs | 5 +-- .../clippy_lints/src/methods/str_splitn.rs | 8 ++--- .../src/needless_question_mark.rs | 5 +-- .../clippy/clippy_lints/src/question_mark.rs | 14 ++++---- .../src/returns/needless_return.rs | 5 +-- .../clippy_lints/src/unused_io_amount.rs | 10 +++--- tests/ui/unpretty/exhaustive.hir.stdout | 18 ++++------ 12 files changed, 49 insertions(+), 89 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index ca67fe7399d8..c30af32ea234 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -609,7 +609,7 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = self.arena.alloc(self.expr_lang_item_qpath(method_span, lang_item)); + let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item)); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } @@ -1950,7 +1950,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // expand let sub_expr = self.lower_expr_mut(sub_expr); - self.expr_call_lang_item_qpath_fn( + self.expr_call_lang_item_fn( unstable_span, hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ec95c113aa40..c2e1cdef4ba3 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -545,9 +545,7 @@ 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(QPath::LangItem(..)) => unreachable!(), 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 +746,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>, @@ -780,6 +770,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { 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 { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c0167e35432f..bce171658c20 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -691,41 +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::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)] diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 88a38060091d..6dc795c9ed48 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1291,10 +1291,7 @@ 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)) - } + QPath::LangItem(..) => unreachable!(), } } diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs index 7358628f0f7e..401b8468135b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs @@ -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) diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index 2a0ae14a4b08..8980a22ad613 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -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) diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index eee7fb0c5a81..fff203296bce 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -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) diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 986a827c59c5..29c45168b61e 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -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) diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index e67ea1f5e370..1a6165d0af83 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -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() diff --git a/src/tools/clippy/clippy_lints/src/returns/needless_return.rs b/src/tools/clippy/clippy_lints/src/returns/needless_return.rs index 04739fc1b22a..7d836b610e5f 100644 --- a/src/tools/clippy/clippy_lints/src/returns/needless_return.rs +++ b/src/tools/clippy/clippy_lints/src/returns/needless_return.rs @@ -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; } diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 755f9454e901..ffce03cb5dbe 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -192,7 +192,7 @@ 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 { inner = unpack_match(inner); - inner = unpack_try(inner); + inner = unpack_try(cx, inner); inner = unpack_call_chain(inner); inner = unpack_await(cx, inner); // we type-check it to get whether it's a read/write or their vectorized forms @@ -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; } diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 9d4b027c21e8..ee22c3aeba9d 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -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; } @@ -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