Skip to content

Commit cebf957

Browse files
committed
Find IntoFuture::IntoFuture's poll method
1 parent dc3219b commit cebf957

File tree

4 files changed

+65
-10
lines changed

4 files changed

+65
-10
lines changed

crates/hir/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2777,9 +2777,10 @@ impl Type {
27772777
self.ty.is_unknown()
27782778
}
27792779

2780-
/// Checks that particular type `ty` implements `std::future::Future`.
2780+
/// Checks that particular type `ty` implements `std::future::IntoFuture` or
2781+
/// `std::future::Future`.
27812782
/// This function is used in `.await` syntax completion.
2782-
pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
2783+
pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
27832784
let trait_ = db
27842785
.lang_item(self.env.krate, SmolStr::new_inline("into_future"))
27852786
.and_then(|it| {

crates/hir/src/source_analyzer.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use hir_def::{
2727
use hir_expand::{
2828
builtin_fn_macro::BuiltinFnLikeExpander,
2929
hygiene::Hygiene,
30+
mod_path::path,
3031
name,
3132
name::{AsName, Name},
3233
HirFileId, InFile,
@@ -269,16 +270,35 @@ impl SourceAnalyzer {
269270
db: &dyn HirDatabase,
270271
await_expr: &ast::AwaitExpr,
271272
) -> Option<FunctionId> {
272-
// FIXME This should be pointing to the poll of IntoFuture::Output's Future impl, but I
273-
// don't know how to resolve the Output type so that we can query for its poll method.
274-
let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?;
273+
let mut ty = self.ty_of_expr(db, &await_expr.expr()?.into())?.clone();
274+
275+
let into_future_trait = self
276+
.resolver
277+
.resolve_known_trait(db.upcast(), &path![core::future::IntoFuture])
278+
.map(Trait::from);
279+
280+
if let Some(into_future_trait) = into_future_trait {
281+
let type_ = Type::new_with_resolver(db, &self.resolver, ty.clone());
282+
if type_.impls_trait(db, into_future_trait, &[]) {
283+
let items = into_future_trait.items(db);
284+
let into_future_type = items.into_iter().find_map(|item| match item {
285+
AssocItem::TypeAlias(alias)
286+
if alias.name(db) == hir_expand::name![IntoFuture] =>
287+
{
288+
Some(alias)
289+
}
290+
_ => None,
291+
})?;
292+
let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?;
293+
ty = future_trait.ty;
294+
}
295+
}
275296

276-
let op_fn = db
297+
let poll_fn = db
277298
.lang_item(self.resolver.krate(), hir_expand::name![poll].to_smol_str())?
278299
.as_function()?;
279-
let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
280-
281-
Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
300+
let substs = hir_ty::TyBuilder::subst_for_def(db, poll_fn).push(ty.clone()).build();
301+
Some(self.resolve_impl_method_or_trait_def(db, poll_fn, &substs))
282302
}
283303

284304
pub(crate) fn resolve_prefix_expr(

crates/ide-completion/src/completions/dot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub(crate) fn complete_dot(
1919
};
2020

2121
// Suggest .await syntax for types that implement Future trait
22-
if receiver_ty.impls_future(ctx.db) {
22+
if receiver_ty.impls_into_future(ctx.db) {
2323
let mut item =
2424
CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
2525
item.detail("expr.await");

crates/ide/src/goto_definition.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,40 @@ fn f() {
16641664
);
16651665
}
16661666

1667+
#[test]
1668+
fn goto_await_into_future_poll() {
1669+
check(
1670+
r#"
1671+
//- minicore: future
1672+
1673+
struct Futurable;
1674+
1675+
impl core::future::IntoFuture for Futurable {
1676+
type IntoFuture = MyFut;
1677+
}
1678+
1679+
struct MyFut;
1680+
1681+
impl core::future::Future for MyFut {
1682+
type Output = ();
1683+
1684+
fn poll(
1685+
//^^^^
1686+
self: std::pin::Pin<&mut Self>,
1687+
cx: &mut std::task::Context<'_>
1688+
) -> std::task::Poll<Self::Output>
1689+
{
1690+
()
1691+
}
1692+
}
1693+
1694+
fn f() {
1695+
Futurable.await$0;
1696+
}
1697+
"#,
1698+
);
1699+
}
1700+
16671701
#[test]
16681702
fn goto_try_op() {
16691703
check(

0 commit comments

Comments
 (0)