mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Desugar async fn completely
This commit is contained in:
parent
a6464392c1
commit
c26b12d01c
5 changed files with 56 additions and 21 deletions
|
@ -353,8 +353,9 @@ impl Body {
|
||||||
let _p = profile::span("body_with_source_map_query");
|
let _p = profile::span("body_with_source_map_query");
|
||||||
let mut params = None;
|
let mut params = None;
|
||||||
|
|
||||||
let (file_id, module, body) = match def {
|
let (file_id, module, body, is_async_fn) = match def {
|
||||||
DefWithBodyId::FunctionId(f) => {
|
DefWithBodyId::FunctionId(f) => {
|
||||||
|
let data = db.function_data(f);
|
||||||
let f = f.lookup(db);
|
let f = f.lookup(db);
|
||||||
let src = f.source(db);
|
let src = f.source(db);
|
||||||
params = src.value.param_list().map(|param_list| {
|
params = src.value.param_list().map(|param_list| {
|
||||||
|
@ -371,27 +372,33 @@ impl Body {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
(src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
|
(
|
||||||
|
src.file_id,
|
||||||
|
f.module(db),
|
||||||
|
src.value.body().map(ast::Expr::from),
|
||||||
|
data.has_async_kw(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
DefWithBodyId::ConstId(c) => {
|
DefWithBodyId::ConstId(c) => {
|
||||||
let c = c.lookup(db);
|
let c = c.lookup(db);
|
||||||
let src = c.source(db);
|
let src = c.source(db);
|
||||||
(src.file_id, c.module(db), src.value.body())
|
(src.file_id, c.module(db), src.value.body(), false)
|
||||||
}
|
}
|
||||||
DefWithBodyId::StaticId(s) => {
|
DefWithBodyId::StaticId(s) => {
|
||||||
let s = s.lookup(db);
|
let s = s.lookup(db);
|
||||||
let src = s.source(db);
|
let src = s.source(db);
|
||||||
(src.file_id, s.module(db), src.value.body())
|
(src.file_id, s.module(db), src.value.body(), false)
|
||||||
}
|
}
|
||||||
DefWithBodyId::VariantId(v) => {
|
DefWithBodyId::VariantId(v) => {
|
||||||
let e = v.parent.lookup(db);
|
let e = v.parent.lookup(db);
|
||||||
let src = v.parent.child_source(db);
|
let src = v.parent.child_source(db);
|
||||||
let variant = &src.value[v.local_id];
|
let variant = &src.value[v.local_id];
|
||||||
(src.file_id, e.container, variant.expr())
|
(src.file_id, e.container, variant.expr(), false)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let expander = Expander::new(db, file_id, module);
|
let expander = Expander::new(db, file_id, module);
|
||||||
let (mut body, source_map) = Body::new(db, expander, params, body, module.krate);
|
let (mut body, source_map) =
|
||||||
|
Body::new(db, expander, params, body, module.krate, is_async_fn);
|
||||||
body.shrink_to_fit();
|
body.shrink_to_fit();
|
||||||
|
|
||||||
(Arc::new(body), Arc::new(source_map))
|
(Arc::new(body), Arc::new(source_map))
|
||||||
|
@ -421,8 +428,9 @@ impl Body {
|
||||||
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
|
is_async_fn: bool,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
lower::lower(db, expander, params, body, krate)
|
lower::lower(db, expander, params, body, krate, is_async_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shrink_to_fit(&mut self) {
|
fn shrink_to_fit(&mut self) {
|
||||||
|
|
|
@ -84,6 +84,7 @@ pub(super) fn lower(
|
||||||
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
|
is_async_fn: bool,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
ExprCollector {
|
ExprCollector {
|
||||||
db,
|
db,
|
||||||
|
@ -105,7 +106,7 @@ pub(super) fn lower(
|
||||||
is_lowering_assignee_expr: false,
|
is_lowering_assignee_expr: false,
|
||||||
is_lowering_generator: false,
|
is_lowering_generator: false,
|
||||||
}
|
}
|
||||||
.collect(params, body)
|
.collect(params, body, is_async_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExprCollector<'a> {
|
struct ExprCollector<'a> {
|
||||||
|
@ -141,6 +142,7 @@ impl ExprCollector<'_> {
|
||||||
mut self,
|
mut self,
|
||||||
param_list: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
param_list: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
|
is_async_fn: bool,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
if let Some((param_list, mut attr_enabled)) = param_list {
|
if let Some((param_list, mut attr_enabled)) = param_list {
|
||||||
if let Some(self_param) =
|
if let Some(self_param) =
|
||||||
|
@ -170,7 +172,25 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.body.body_expr = self.collect_expr_opt(body);
|
self.body.body_expr = if is_async_fn {
|
||||||
|
self.current_try_block =
|
||||||
|
Some(self.alloc_label_desugared(Label { name: Name::generate_new_name() }));
|
||||||
|
let expr = self.collect_expr_opt(body);
|
||||||
|
let expr = self.alloc_expr_desugared(Expr::Block {
|
||||||
|
id: None,
|
||||||
|
statements: Box::new([]),
|
||||||
|
tail: Some(expr),
|
||||||
|
label: self.current_try_block,
|
||||||
|
});
|
||||||
|
let expr = self.alloc_expr_desugared(Expr::Async {
|
||||||
|
id: None,
|
||||||
|
statements: Box::new([]),
|
||||||
|
tail: Some(expr),
|
||||||
|
});
|
||||||
|
expr
|
||||||
|
} else {
|
||||||
|
self.collect_expr_opt(body)
|
||||||
|
};
|
||||||
(self.body, self.source_map)
|
(self.body, self.source_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -459,7 +459,6 @@ pub(crate) struct InferenceContext<'a> {
|
||||||
resume_yield_tys: Option<(Ty, Ty)>,
|
resume_yield_tys: Option<(Ty, Ty)>,
|
||||||
diverges: Diverges,
|
diverges: Diverges,
|
||||||
breakables: Vec<BreakableContext>,
|
breakables: Vec<BreakableContext>,
|
||||||
is_async_fn: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -527,7 +526,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
resolver,
|
resolver,
|
||||||
diverges: Diverges::Maybe,
|
diverges: Diverges::Maybe,
|
||||||
breakables: Vec::new(),
|
breakables: Vec::new(),
|
||||||
is_async_fn: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,9 +637,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
self.infer_top_pat(*pat, &ty);
|
self.infer_top_pat(*pat, &ty);
|
||||||
}
|
}
|
||||||
let return_ty = &*data.ret_type;
|
let return_ty = &*data.ret_type;
|
||||||
if data.has_async_kw() {
|
|
||||||
self.is_async_fn = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
|
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
|
||||||
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
|
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
|
||||||
|
|
|
@ -293,7 +293,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
// FIXME: lift these out into a struct
|
// FIXME: lift these out into a struct
|
||||||
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||||
let prev_is_async_fn = mem::replace(&mut self.is_async_fn, false);
|
|
||||||
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
||||||
let prev_ret_coercion =
|
let prev_ret_coercion =
|
||||||
mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty)));
|
mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty)));
|
||||||
|
@ -307,7 +306,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
self.diverges = prev_diverges;
|
self.diverges = prev_diverges;
|
||||||
self.return_ty = prev_ret_ty;
|
self.return_ty = prev_ret_ty;
|
||||||
self.return_coercion = prev_ret_coercion;
|
self.return_coercion = prev_ret_coercion;
|
||||||
self.is_async_fn = prev_is_async_fn;
|
|
||||||
self.resume_yield_tys = prev_resume_yield_tys;
|
self.resume_yield_tys = prev_resume_yield_tys;
|
||||||
|
|
||||||
ty
|
ty
|
||||||
|
@ -963,11 +961,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("infer_return called outside function body")
|
.expect("infer_return called outside function body")
|
||||||
.expected_ty();
|
.expected_ty();
|
||||||
let return_expr_ty = if self.is_async_fn {
|
let return_expr_ty = self.infer_expr_inner(expr, &Expectation::HasType(ret_ty));
|
||||||
self.infer_async_block(expr, &None, &[], &Some(expr))
|
|
||||||
} else {
|
|
||||||
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty))
|
|
||||||
};
|
|
||||||
let mut coerce_many = self.return_coercion.take().unwrap();
|
let mut coerce_many = self.return_coercion.take().unwrap();
|
||||||
coerce_many.coerce(self, Some(expr), &return_expr_ty);
|
coerce_many.coerce(self, Some(expr), &return_expr_ty);
|
||||||
self.return_coercion = Some(coerce_many);
|
self.return_coercion = Some(coerce_many);
|
||||||
|
|
|
@ -2094,6 +2094,24 @@ async fn main() {
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn async_fn_and_try_operator() {
|
||||||
|
check_no_mismatches(
|
||||||
|
r#"
|
||||||
|
//- minicore: future, result, fn, try, from
|
||||||
|
async fn foo() -> Result<(), ()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn bar() -> Result<(), ()> {
|
||||||
|
let x = foo().await?;
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn async_block_early_return() {
|
fn async_block_early_return() {
|
||||||
check_infer(
|
check_infer(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue