mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
hir_ty: use async ret type for inference inside async bodies
This commit is contained in:
parent
3fa3343e47
commit
54d60fdee9
6 changed files with 65 additions and 4 deletions
|
@ -22,6 +22,7 @@ pub struct FunctionData {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub params: Vec<Interned<TypeRef>>,
|
pub params: Vec<Interned<TypeRef>>,
|
||||||
pub ret_type: Interned<TypeRef>,
|
pub ret_type: Interned<TypeRef>,
|
||||||
|
pub async_ret_type: Option<Interned<TypeRef>>,
|
||||||
pub attrs: Attrs,
|
pub attrs: Attrs,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
pub abi: Option<Interned<str>>,
|
pub abi: Option<Interned<str>>,
|
||||||
|
@ -63,6 +64,7 @@ impl FunctionData {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
ret_type: func.ret_type.clone(),
|
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()),
|
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
|
||||||
visibility: item_tree[func.visibility].clone(),
|
visibility: item_tree[func.visibility].clone(),
|
||||||
abi: func.abi.clone(),
|
abi: func.abi.clone(),
|
||||||
|
|
|
@ -580,6 +580,7 @@ pub struct Function {
|
||||||
pub abi: Option<Interned<str>>,
|
pub abi: Option<Interned<str>>,
|
||||||
pub params: IdRange<Param>,
|
pub params: IdRange<Param>,
|
||||||
pub ret_type: Interned<TypeRef>,
|
pub ret_type: Interned<TypeRef>,
|
||||||
|
pub async_ret_type: Option<Interned<TypeRef>>,
|
||||||
pub ast_id: FileAstId<ast::Fn>,
|
pub ast_id: FileAstId<ast::Fn>,
|
||||||
pub(crate) flags: FnFlags,
|
pub(crate) flags: FnFlags,
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,12 +356,13 @@ impl<'a> Ctx<'a> {
|
||||||
_ => TypeRef::unit(),
|
_ => 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 future_impl = desugar_future_path(ret_type);
|
||||||
let ty_bound = Interned::new(TypeBound::Path(future_impl));
|
let ty_bound = Interned::new(TypeBound::Path(future_impl));
|
||||||
TypeRef::ImplTrait(vec![ty_bound])
|
(TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
|
||||||
} else {
|
} else {
|
||||||
ret_type
|
(ret_type, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let abi = func.abi().map(lower_abi);
|
let abi = func.abi().map(lower_abi);
|
||||||
|
@ -395,6 +396,7 @@ impl<'a> Ctx<'a> {
|
||||||
abi,
|
abi,
|
||||||
params,
|
params,
|
||||||
ret_type: Interned::new(ret_type),
|
ret_type: Interned::new(ret_type),
|
||||||
|
async_ret_type: async_ret_type.map(Interned::new),
|
||||||
ast_id,
|
ast_id,
|
||||||
flags,
|
flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -235,6 +235,7 @@ impl<'a> Printer<'a> {
|
||||||
abi,
|
abi,
|
||||||
params,
|
params,
|
||||||
ret_type,
|
ret_type,
|
||||||
|
async_ret_type: _,
|
||||||
ast_id: _,
|
ast_id: _,
|
||||||
flags,
|
flags,
|
||||||
} = &self.tree[it];
|
} = &self.tree[it];
|
||||||
|
|
|
@ -558,7 +558,13 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
self.infer_pat(*pat, &ty, BindingMode::default());
|
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;
|
self.return_ty = return_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue