Skip to content

Commit

Permalink
Implement gen blocks and functions
Browse files Browse the repository at this point in the history
  • Loading branch information
mohe2015 authored and Veykril committed Jul 25, 2024
1 parent fa5ff86 commit 36aa3c3
Show file tree
Hide file tree
Showing 53 changed files with 1,384 additions and 274 deletions.
8 changes: 6 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 @@ -158,7 +159,9 @@ impl Body {
}),
)
});
// FIXME from here we know this only happens for functions, so maybe we can get the blockexpr directly and also onlive provide the keyword values then
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 +185,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 +225,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
194 changes: 169 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,73 @@ 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),
(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)
}
});
},
(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(),
},
(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 +310,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 +331,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 +417,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 +616,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 +649,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

0 comments on commit 36aa3c3

Please sign in to comment.