hir_ty: use async ret type for inference inside async bodies

This commit is contained in:
cynecx 2021-05-29 18:16:20 +02:00
parent 3fa3343e47
commit 54d60fdee9
6 changed files with 65 additions and 4 deletions

View File

@ -22,6 +22,7 @@ pub struct FunctionData {
pub name: Name,
pub params: Vec<Interned<TypeRef>>,
pub ret_type: Interned<TypeRef>,
pub async_ret_type: Option<Interned<TypeRef>>,
pub attrs: Attrs,
pub visibility: RawVisibility,
pub abi: Option<Interned<str>>,
@ -63,6 +64,7 @@ impl FunctionData {
})
.collect(),
ret_type: func.ret_type.clone(),
async_ret_type: func.async_ret_type.clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
visibility: item_tree[func.visibility].clone(),
abi: func.abi.clone(),

View File

@ -580,6 +580,7 @@ pub struct Function {
pub abi: Option<Interned<str>>,
pub params: IdRange<Param>,
pub ret_type: Interned<TypeRef>,
pub async_ret_type: Option<Interned<TypeRef>>,
pub ast_id: FileAstId<ast::Fn>,
pub(crate) flags: FnFlags,
}

View File

@ -356,12 +356,13 @@ impl<'a> Ctx<'a> {
_ => TypeRef::unit(),
};
let ret_type = if func.async_token().is_some() {
let (ret_type, async_ret_type) = if func.async_token().is_some() {
let async_ret_type = ret_type.clone();
let future_impl = desugar_future_path(ret_type);
let ty_bound = Interned::new(TypeBound::Path(future_impl));
TypeRef::ImplTrait(vec![ty_bound])
(TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
} else {
ret_type
(ret_type, None)
};
let abi = func.abi().map(lower_abi);
@ -395,6 +396,7 @@ impl<'a> Ctx<'a> {
abi,
params,
ret_type: Interned::new(ret_type),
async_ret_type: async_ret_type.map(Interned::new),
ast_id,
flags,
};

View File

@ -235,6 +235,7 @@ impl<'a> Printer<'a> {
abi,
params,
ret_type,
async_ret_type: _,
ast_id: _,
flags,
} = &self.tree[it];

View File

@ -558,7 +558,13 @@ impl<'a> InferenceContext<'a> {
self.infer_pat(*pat, &ty, BindingMode::default());
}
let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT
let error_ty = &TypeRef::Error;
let return_ty = if data.is_async() {
data.async_ret_type.as_deref().unwrap_or(error_ty)
} else {
&*data.ret_type
};
let return_ty = self.make_ty_with_mode(return_ty, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT
self.return_ty = return_ty;
}

View File

@ -3660,3 +3660,52 @@ impl foo::Foo for u32 {
"#]],
);
}
#[test]
fn infer_async_ret_type() {
check_types(
r#"
//- /main.rs crate:main deps:core
enum Result<T, E> {
Ok(T),
Err(E),
}
use Result::*;
struct Fooey;
impl Fooey {
fn collect<B: Convert>(self) -> B {
B::new()
}
}
trait Convert {
fn new() -> Self;
}
impl Convert for u32 {
fn new() -> Self {
0
}
}
async fn get_accounts() -> Result<u32, ()> {
let ret = Fooey.collect();
// ^ u32
Ok(ret)
}
//- /core.rs crate:core
#[prelude_import] use future::*;
mod future {
#[lang = "future_trait"]
trait Future {
type Output;
}
}
"#,
);
}