Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mohe2015 committed Dec 25, 2023
1 parent af6a414 commit da18904
Show file tree
Hide file tree
Showing 37 changed files with 1,159 additions and 147 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 @@ -126,6 +126,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 All @@ -146,7 +147,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 @@ -169,7 +172,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 @@ -209,8 +212,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
187 changes: 167 additions & 20 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,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 @@ -85,7 +86,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 @@ -191,6 +192,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 {
if let Some(self_param) =
Expand All @@ -212,23 +214,73 @@ impl ExprCollector<'_> {
self.body.params.push(param_pat);
}
};
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 expr = this.collect_expr(e);
this.alloc_expr_desugared(Expr::Async {
id: None,
statements: Box::new([]),
tail: Some(expr),

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 @@ -268,6 +320,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 @@ -288,13 +341,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 Down Expand Up @@ -504,6 +620,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 @@ -536,9 +653,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_generator = prev_is_lowering_generator;
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 @@ -7,8 +7,8 @@ use syntax::ast::HasName;

use crate::{
hir::{
Array, BindingAnnotation, BindingId, 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 @@ -383,38 +383,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 @@ -454,9 +471,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
2 changes: 1 addition & 1 deletion crates/hir-def/src/body/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
Expr::Const(_) => {
// FIXME: This is broken.
}
Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => {
Expr::Unsafe { id, statements, tail } => {
let mut scope = scopes.new_block_scope(*scope, *id, None);
// Overwrite the old scope for the block expr, so that every block scope can be found
// via the block itself (important for blocks that only contain items, no expressions).
Expand Down
Loading

0 comments on commit da18904

Please sign in to comment.