From bd13c30d98e54dc2e59f72e7071cfa86faf8dc8a Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 17 Aug 2025 07:44:53 -0500 Subject: [PATCH] Remove QPath::LangItem from async --- compiler/rustc_ast_lowering/src/expr.rs | 21 ++++++++++++------- compiler/rustc_ast_lowering/src/lib.rs | 4 +++- compiler/rustc_hir_typeck/src/expr.rs | 7 ++++++- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 9 -------- compiler/rustc_span/src/symbol.rs | 1 + .../clippy/clippy_lints/src/large_futures.rs | 5 +++-- .../clippy_lints/src/unused_io_amount.rs | 10 ++++----- 7 files changed, 30 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index aab22f334775..ca67fe7399d8 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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)), }; @@ -901,23 +902,23 @@ impl<'hir> LoweringContext<'_, 'hir> { let task_context = self.expr_ident_mut(span, task_context_ident, task_context_hid); - let new_unchecked = self.expr_call_lang_item_qpath_fn_mut( + let new_unchecked = self.expr_call_lang_item_fn_mut( span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_awaitee], ); - let get_context = self.expr_call_lang_item_qpath_fn_mut( + let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], ); let call = match await_kind { - FutureKind::Future => self.expr_call_lang_item_qpath_fn( + FutureKind::Future => self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], ), - FutureKind::AsyncIterator => self.expr_call_lang_item_qpath_fn( + FutureKind::AsyncIterator => self.expr_call_lang_item_fn( span, hir::LangItem::AsyncIteratorPollNext, arena_vec![self; new_unchecked, get_context], @@ -965,7 +966,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // async gen - task_context = yield ASYNC_GEN_PENDING; let yield_stmt = { let yielded = if is_async_gen { - self.arena.alloc(self.expr_lang_item_qpath(span, hir::LangItem::AsyncGenPending)) + self.arena.alloc(self.expr_lang_item_path(span, hir::LangItem::AsyncGenPending)) } else { self.expr_unit(span) }; @@ -1005,7 +1006,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_expr = match await_kind { - FutureKind::Future => self.expr_call_lang_item_qpath_fn( + FutureKind::Future => self.expr_call_lang_item_fn( span, hir::LangItem::IntoFutureIntoFuture, arena_vec![self; *expr], @@ -1720,8 +1721,12 @@ 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_qpath_fn( - span, + let wrapped_yielded = self.expr_call_lang_item_fn( + self.mark_span_with_reason( + DesugaringKind::Async, + span, + Some(Arc::clone(&self.allow_async_gen)), + ), hir::LangItem::AsyncGenReady, std::slice::from_ref(yielded), ); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a32144a266f8..173f535f6da3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -142,6 +142,7 @@ struct LoweringContext<'a, 'hir> { 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]>, @@ -192,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(), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 38216336cce8..ec95c113aa40 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -764,12 +764,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; - if let Some((_, [_arg])) = call_expr_and_args + 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) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 4a3237365d6f..c0167e35432f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -712,15 +712,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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::TryTraitFromOutput | hir::LangItem::TryTraitFromResidual | hir::LangItem::TryTraitBranch => Some(ObligationCauseCode::QuestionMark), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 223d818a2949..c1c9fa57f85b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -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, diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index fd7965d564d5..b11e89a9b566 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -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() 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 2884bbd9280d..755f9454e901 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -194,7 +194,7 @@ fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option inner = unpack_match(inner); inner = unpack_try(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) @@ -277,13 +277,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; }