Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement gen block and function parsing #16173

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions crates/hir-def/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ impl Body {
let mut params = None;

let mut is_async_fn = false;
let mut is_gen_fn = false;
let InFile { file_id, value: body } = {
match def {
DefWithBodyId::FunctionId(f) => {
Expand Down Expand Up @@ -159,6 +160,7 @@ impl Body {
)
});
is_async_fn = data.has_async_kw();
is_gen_fn = data.has_gen_kw();
src.map(|it| it.body().map(ast::Expr::from))
}
DefWithBodyId::ConstId(c) => {
Expand All @@ -182,7 +184,7 @@ impl Body {
let module = def.module(db);
let expander = Expander::new(db, file_id, module);
let (mut body, mut source_map) =
Body::new(db, def, expander, params, body, module.krate, is_async_fn);
Body::new(db, def, expander, params, body, module.krate, is_async_fn, is_gen_fn);
body.shrink_to_fit();
source_map.shrink_to_fit();

Expand Down Expand Up @@ -222,8 +224,9 @@ impl Body {
body: Option<ast::Expr>,
krate: CrateId,
is_async_fn: bool,
is_gen_fn: bool,
) -> (Body, BodySourceMap) {
lower::lower(db, owner, expander, params, body, krate, is_async_fn)
lower::lower(db, owner, expander, params, body, krate, is_async_fn, is_gen_fn)
}

fn shrink_to_fit(&mut self) {
Expand Down
197 changes: 172 additions & 25 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub(super) fn lower(
body: Option<ast::Expr>,
krate: CrateId,
is_async_fn: bool,
is_gen_fn: bool,
) -> (Body, BodySourceMap) {
ExprCollector {
db,
Expand All @@ -73,7 +74,7 @@ pub(super) fn lower(
label_ribs: Vec::new(),
current_binding_owner: None,
}
.collect(params, body, is_async_fn)
.collect(params, body, is_async_fn, is_gen_fn)
}

struct ExprCollector<'a> {
Expand Down Expand Up @@ -179,6 +180,7 @@ impl ExprCollector<'_> {
param_list: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
is_async_fn: bool,
is_gen_fn: bool,
) -> (Body, BodySourceMap) {
if let Some((param_list, mut attr_enabled)) = param_list {
let mut params = vec![];
Expand All @@ -202,23 +204,76 @@ impl ExprCollector<'_> {
}
self.body.params = params.into_boxed_slice();
};
self.body.body_expr = self.with_label_rib(RibKind::Closure, |this| {
if is_async_fn {
match body {
self.body.body_expr =
self.with_label_rib(RibKind::Closure, |this| match (is_async_fn, is_gen_fn) {
(false, false) => this.collect_expr_opt(body),
// gen fn
(false, true) => match body {
Some(e) => {
let syntax_ptr = AstPtr::new(&e);
let expr = this.collect_expr(e);
this.alloc_expr_desugared_with_ptr(
Expr::Async { id: None, statements: Box::new([]), tail: Some(expr) },
syntax_ptr,
)

this.alloc_expr_desugared(Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: None, // FIXME maybe unspecified?
body: expr,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::Gen,
crate::hir::CoroutineSource::Fn,
),
Movability::Movable,
),
capture_by: CaptureBy::Ref,
})
}
None => this.missing_expr(),
}
} else {
this.collect_expr_opt(body)
}
});
},
// async fn
(true, false) => match body {
Some(e) => {
let expr = this.collect_expr(e);

this.alloc_expr_desugared(Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: None, // FIXME maybe unspecified?
body: expr,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::Async,
crate::hir::CoroutineSource::Fn,
),
Movability::Movable,
),
capture_by: CaptureBy::Ref,
})
}
None => this.missing_expr(),
},
// async gen fn
(true, true) => match body {
Some(e) => {
let expr = this.collect_expr(e);

this.alloc_expr_desugared(Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: None, // FIXME maybe unspecified?
body: expr,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::AsyncGen,
crate::hir::CoroutineSource::Fn,
),
Movability::Movable,
),
capture_by: CaptureBy::Ref,
})
}
None => this.missing_expr(),
},
});

(self.body, self.source_map)
}
Expand Down Expand Up @@ -258,6 +313,7 @@ impl ExprCollector<'_> {
let expr = self.collect_expr_opt(e.expr());
self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
}
// https://github.com/compiler-errors/rust/blob/bd0eec74026d5f967afeadc3611bdb674a7b9de4/compiler/rustc_ast/src/ast.rs#L1430
ast::Expr::BlockExpr(e) => match e.modifier() {
Some(ast::BlockModifier::Try(_)) => self.desugar_try_block(e),
Some(ast::BlockModifier::Unsafe(_)) => {
Expand All @@ -278,13 +334,76 @@ impl ExprCollector<'_> {
})
})
}
// https://github.com/compiler-errors/rust/blob/closure-kind/compiler/rustc_ast/src/ast.rs#L1430
// https://github.com/compiler-errors/rust/blob/bd0eec74026d5f967afeadc3611bdb674a7b9de4/compiler/rustc_ast_lowering/src/expr.rs#L186
Some(ast::BlockModifier::Async(_)) => {
self.with_label_rib(RibKind::Closure, |this| {
this.collect_block_(e, |id, statements, tail| Expr::Async {
id,
statements,
tail,
})
let (result_expr_id, _) = this.initialize_binding_owner(syntax_ptr);

let body = this.collect_block(e);

this.body.exprs[result_expr_id] = Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: None, // FIXME maybe unspecified?
body,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::Async,
crate::hir::CoroutineSource::Block,
),
Movability::Movable,
),
capture_by: CaptureBy::Ref,
};

result_expr_id
})
}
Some(ast::BlockModifier::Gen(_)) => self.with_label_rib(RibKind::Closure, |this| {
let (result_expr_id, _) = this.initialize_binding_owner(syntax_ptr);

let body = this.collect_block(e);

this.body.exprs[result_expr_id] = Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: None, // FIXME maybe unspecified?
body,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::Gen,
crate::hir::CoroutineSource::Block,
),
Movability::Movable,
),
capture_by: CaptureBy::Ref,
};

result_expr_id
}),
Some(ast::BlockModifier::AsyncGen(_)) => {
self.with_label_rib(RibKind::Closure, |this| {
let (result_expr_id, _) = this.initialize_binding_owner(syntax_ptr);

let body = this.collect_block(e);

this.body.exprs[result_expr_id] = Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: None, // FIXME maybe unspecified?
body,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::AsyncGen,
crate::hir::CoroutineSource::Block,
),
Movability::Movable,
),
capture_by: CaptureBy::Ref,
};

result_expr_id
})
}
Some(ast::BlockModifier::Const(_)) => {
Expand All @@ -301,10 +420,7 @@ impl ExprCollector<'_> {
result_expr_id
})
}
// FIXME
Some(ast::BlockModifier::AsyncGen(_)) | Some(ast::BlockModifier::Gen(_)) | None => {
self.collect_block(e)
}
None => self.collect_block(e),
},
ast::Expr::LoopExpr(e) => {
let label = e.label().map(|label| self.collect_label(label));
Expand Down Expand Up @@ -503,6 +619,7 @@ impl ExprCollector<'_> {
}
}
ast::Expr::ClosureExpr(e) => self.with_label_rib(RibKind::Closure, |this| {
// here
let (result_expr_id, prev_binding_owner) =
this.initialize_binding_owner(syntax_ptr);
let mut args = Vec::new();
Expand Down Expand Up @@ -535,9 +652,39 @@ impl ExprCollector<'_> {
} else {
Movability::Movable
};
ClosureKind::Coroutine(movability)
ClosureKind::Coroutine(crate::hir::CoroutineKind::Coroutine, movability)
} else if e.async_token().is_some() {
ClosureKind::Async
// https://github.com/compiler-errors/rust/blob/bd0eec74026d5f967afeadc3611bdb674a7b9de4/compiler/rustc_ast_lowering/src/expr.rs#L1199 ?

let capture_by =
if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };

let inner = Expr::Closure {
args: Box::new([]),
arg_types: Box::new([]),
ret_type: ret_type.clone(),
body,
closure_kind: ClosureKind::Coroutine(
crate::hir::CoroutineKind::Desugared(
crate::hir::CoroutineDesugaring::Async,
crate::hir::CoroutineSource::Closure,
),
Movability::Movable,
),
capture_by,
};
this.is_lowering_coroutine = prev_is_lowering_coroutine;
this.current_binding_owner = prev_binding_owner;
this.current_try_block_label = prev_try_block_label;
this.body.exprs[result_expr_id] = Expr::Closure {
args: args.into(),
arg_types: arg_types.into(),
ret_type,
body: this.alloc_expr_desugared(inner),
closure_kind: ClosureKind::Closure,
capture_by,
};
return result_expr_id;
} else {
ClosureKind::Closure
};
Expand Down
62 changes: 38 additions & 24 deletions crates/hir-def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use itertools::Itertools;

use crate::{
hir::{
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability,
Statement,
Array, BindingAnnotation, BindingId, CaptureBy, ClosureKind, CoroutineDesugaring,
CoroutineKind, Literal, LiteralOrConst, Movability, Statement,
},
pretty::{print_generic_args, print_path, print_type_ref},
type_ref::TypeRef,
Expand Down Expand Up @@ -400,38 +400,55 @@ impl Printer<'_> {
w!(self, "]");
}
Expr::Closure { args, arg_types, ret_type, body, closure_kind, capture_by } => {
if let ClosureKind::Coroutine(_, Movability::Static) = closure_kind {
w!(self, "static ");
}
match closure_kind {
ClosureKind::Coroutine(Movability::Static) => {
w!(self, "static ");
}
ClosureKind::Async => {
ClosureKind::Coroutine(
CoroutineKind::Desugared(CoroutineDesugaring::Async, _),
_,
) => {
w!(self, "async ");
}
_ => (),
ClosureKind::Coroutine(
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _),
_,
) => {
w!(self, "async gen ");
}
ClosureKind::Coroutine(
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _),
_,
) => {
w!(self, "gen ");
}
_ => {}
}
match capture_by {
CaptureBy::Value => {
w!(self, "move ");
}
CaptureBy::Ref => (),
}
w!(self, "|");
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
if i != 0 {
w!(self, ", ");
if let ClosureKind::Closure = closure_kind {
w!(self, "|");
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
if i != 0 {
w!(self, ", ");
}
self.print_pat(*pat);
if let Some(ty) = ty {
w!(self, ": ");
self.print_type_ref(ty);
}
}
self.print_pat(*pat);
if let Some(ty) = ty {
w!(self, ": ");
self.print_type_ref(ty);
w!(self, "|");
if let Some(ret_ty) = ret_type {
w!(self, " -> ");
self.print_type_ref(ret_ty);
}
self.whitespace();
}
w!(self, "|");
if let Some(ret_ty) = ret_type {
w!(self, " -> ");
self.print_type_ref(ret_ty);
}
self.whitespace();
self.print_expr(*body);
}
Expr::Tuple { exprs, is_assignee_expr: _ } => {
Expand Down Expand Up @@ -471,9 +488,6 @@ impl Printer<'_> {
Expr::Unsafe { id: _, statements, tail } => {
self.print_block(Some("unsafe "), statements, tail);
}
Expr::Async { id: _, statements, tail } => {
self.print_block(Some("async "), statements, tail);
}
Expr::Const(id) => {
w!(self, "const {{ /* {id:?} */ }}");
}
Expand Down
Loading
Loading