From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_ast_lowering/src/expr.rs | 159 ++++++++++++++++++++++++-------- 1 file changed, 120 insertions(+), 39 deletions(-) (limited to 'compiler/rustc_ast_lowering/src/expr.rs') diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 57c54f854..0fff9a6be 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,8 +1,8 @@ use super::errors::{ - AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, - BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignment, - GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure, - UnderscoreExprLhsAssign, + AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, + BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, + FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, + NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; @@ -15,9 +15,10 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; use rustc_session::errors::report_lit_error; -use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; +use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::DUMMY_SP; +use rustc_span::{DesugaringKind, Span}; use thin_vec::{thin_vec, ThinVec}; impl<'hir> LoweringContext<'_, 'hir> { @@ -183,12 +184,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))), hir::MatchSource::Normal, ), - ExprKind::Async(capture_clause, block) => self.make_async_expr( + ExprKind::Gen(capture_clause, block, GenBlockKind::Async) => self.make_async_expr( *capture_clause, e.id, None, e.span, - hir::AsyncGeneratorKind::Block, + hir::CoroutineSource::Block, |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), @@ -317,6 +318,14 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } + ExprKind::Gen(capture_clause, block, GenBlockKind::Gen) => self.make_gen_expr( + *capture_clause, + e.id, + None, + e.span, + hir::CoroutineSource::Block, + |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err( self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"), @@ -583,7 +592,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - /// Lower an `async` construct to a generator that implements `Future`. + /// Lower an `async` construct to a coroutine that implements `Future`. /// /// This results in: /// @@ -598,7 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> { closure_node_id: NodeId, ret_ty: Option>, span: Span, - async_gen_kind: hir::AsyncGeneratorKind, + async_coroutine_source: hir::CoroutineSource, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); @@ -613,7 +622,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: unstable_span, }; - // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. + // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`. let fn_decl = self.arena.alloc(hir::FnDecl { inputs: arena_vec![self; input_ty], output, @@ -637,7 +646,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let params = arena_vec![self; param]; let body = self.lower_body(move |this| { - this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind)); + this.coroutine_kind = Some(hir::CoroutineKind::Async(async_coroutine_source)); let old_ctx = this.task_context; this.task_context = Some(task_context_hid); @@ -661,6 +670,57 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } + /// Lower a `gen` construct to a generator that implements `Iterator`. + /// + /// This results in: + /// + /// ```text + /// static move? |()| -> () { + /// + /// } + /// ``` + pub(super) fn make_gen_expr( + &mut self, + capture_clause: CaptureBy, + closure_node_id: NodeId, + _yield_ty: Option>, + span: Span, + coroutine_source: hir::CoroutineSource, + body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, + ) -> hir::ExprKind<'hir> { + let output = hir::FnRetTy::DefaultReturn(self.lower_span(span)); + + // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. + let fn_decl = self.arena.alloc(hir::FnDecl { + inputs: &[], + output, + c_variadic: false, + implicit_self: hir::ImplicitSelfKind::None, + lifetime_elision_allowed: false, + }); + + let body = self.lower_body(move |this| { + this.coroutine_kind = Some(hir::CoroutineKind::Gen(coroutine_source)); + + let res = body(this); + (&[], res) + }); + + // `static |()| -> () { body }`: + hir::ExprKind::Closure(self.arena.alloc(hir::Closure { + def_id: self.local_def_id(closure_node_id), + binder: hir::ClosureBinder::Default, + capture_clause, + bound_generic_params: &[], + fn_decl, + body, + fn_decl_span: self.lower_span(span), + fn_arg_span: None, + movability: Some(Movability::Movable), + constness: hir::Constness::NotConst, + })) + } + /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled. pub(super) fn maybe_forward_track_caller( @@ -673,12 +733,18 @@ impl<'hir> LoweringContext<'_, 'hir> { && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id) && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)) { - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + span, + self.allow_gen_future.clone(), + ); self.lower_attrs( inner_hir_id, &[Attribute { - kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(sym::track_caller, span)))), + kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new( + sym::track_caller, + span, + )))), id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(), style: AttrStyle::Outer, span: unstable_span, @@ -704,9 +770,9 @@ impl<'hir> LoweringContext<'_, 'hir> { /// ``` fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { let full_span = expr.span.to(await_kw_span); - match self.generator_kind { - Some(hir::GeneratorKind::Async(_)) => {} - Some(hir::GeneratorKind::Gen) | None => { + match self.coroutine_kind { + Some(hir::CoroutineKind::Async(_)) => {} + Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => { self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, item_span: self.current_item, @@ -881,19 +947,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let (body_id, generator_option) = self.with_new_scopes(move |this| { + let (body_id, coroutine_option) = self.with_new_scopes(move |this| { let prev = this.current_item; this.current_item = Some(fn_decl_span); - let mut generator_kind = None; + let mut coroutine_kind = None; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); - generator_kind = this.generator_kind; + coroutine_kind = this.coroutine_kind; e }); - let generator_option = - this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability); + let coroutine_option = + this.coroutine_movability_for_fn(&decl, fn_decl_span, coroutine_kind, movability); this.current_item = prev; - (body_id, generator_option) + (body_id, coroutine_option) }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); @@ -909,29 +975,29 @@ impl<'hir> LoweringContext<'_, 'hir> { body: body_id, fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), - movability: generator_option, + movability: coroutine_option, constness: self.lower_constness(constness), }); hir::ExprKind::Closure(c) } - fn generator_movability_for_fn( + fn coroutine_movability_for_fn( &mut self, decl: &FnDecl, fn_decl_span: Span, - generator_kind: Option, + coroutine_kind: Option, movability: Movability, ) -> Option { - match generator_kind { - Some(hir::GeneratorKind::Gen) => { + match coroutine_kind { + Some(hir::CoroutineKind::Coroutine) => { if decl.inputs.len() > 1 { - self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span }); + self.tcx.sess.emit_err(CoroutineTooManyParameters { fn_decl_span }); } Some(movability) } - Some(hir::GeneratorKind::Async(_)) => { - panic!("non-`async` closure body turned `async` during lowering"); + Some(hir::CoroutineKind::Gen(_)) | Some(hir::CoroutineKind::Async(_)) => { + panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering"); } None => { if movability == Movability::Static { @@ -999,7 +1065,7 @@ impl<'hir> LoweringContext<'_, 'hir> { inner_closure_id, async_ret_ty, body.span, - hir::AsyncGeneratorKind::Closure, + hir::CoroutineSource::Closure, |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), ); let hir_id = this.lower_node_id(inner_closure_id); @@ -1102,7 +1168,9 @@ impl<'hir> LoweringContext<'_, 'hir> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a tuple struct/variant pattern? if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { - if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() { + if let Some(res) = partial_res.full_res() + && !res.expected_in_tuple_struct_pat() + { return None; } } @@ -1122,7 +1190,9 @@ impl<'hir> LoweringContext<'_, 'hir> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a unit struct/variant pattern? if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { - if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() { + if let Some(res) = partial_res.full_res() + && !res.expected_in_unit_struct_pat() + { return None; } } @@ -1434,12 +1504,23 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { - match self.generator_kind { - Some(hir::GeneratorKind::Gen) => {} - Some(hir::GeneratorKind::Async(_)) => { - self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span }); + match self.coroutine_kind { + Some(hir::CoroutineKind::Gen(_)) => {} + Some(hir::CoroutineKind::Async(_)) => { + self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }); + } + Some(hir::CoroutineKind::Coroutine) | None => { + if !self.tcx.features().coroutines { + rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::coroutines, + span, + "yield syntax is experimental", + ) + .emit(); + } + self.coroutine_kind = Some(hir::CoroutineKind::Coroutine) } - None => self.generator_kind = Some(hir::GeneratorKind::Gen), } let expr = -- cgit v1.2.3