summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast_lowering/src/expr.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_ast_lowering/src/expr.rs
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ast_lowering/src/expr.rs')
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs159
1 files changed, 120 insertions, 39 deletions
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<hir::FnRetTy<'hir>>,
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? |()| -> () {
+ /// <body>
+ /// }
+ /// ```
+ pub(super) fn make_gen_expr(
+ &mut self,
+ capture_clause: CaptureBy,
+ closure_node_id: NodeId,
+ _yield_ty: Option<hir::FnRetTy<'hir>>,
+ 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<hir::GeneratorKind>,
+ coroutine_kind: Option<hir::CoroutineKind>,
movability: Movability,
) -> Option<hir::Movability> {
- 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 =