Skip to content

Commit 5810c81

Browse files
committed
Implement IntoFuture type inference
1 parent 3792720 commit 5810c81

File tree

9 files changed

+75
-22
lines changed

9 files changed

+75
-22
lines changed

crates/hir-expand/src/mod_path.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ macro_rules! __known_path {
257257
(core::ops::RangeToInclusive) => {};
258258
(core::ops::RangeInclusive) => {};
259259
(core::future::Future) => {};
260+
(core::future::IntoFuture) => {};
260261
(core::ops::Try) => {};
261262
($path:path) => {
262263
compile_error!("Please register your known path in the path module")

crates/hir-expand/src/name.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ pub mod known {
258258
Try,
259259
Ok,
260260
Future,
261+
IntoFuture,
261262
Result,
262263
Option,
263264
Output,
@@ -391,6 +392,7 @@ pub mod known {
391392
future_trait,
392393
index,
393394
index_mut,
395+
into_future,
394396
mul_assign,
395397
mul,
396398
neg,

crates/hir-ty/src/infer.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,10 @@ impl<'a> InferenceContext<'a> {
875875
}
876876

877877
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
878-
let trait_ = self.resolve_lang_item(name![future_trait])?.as_trait()?;
878+
let trait_ = self
879+
.resolver
880+
.resolve_known_trait(self.db.upcast(), &path![core::future::IntoFuture])
881+
.or_else(|| self.resolve_lang_item(name![future_trait])?.as_trait())?;
879882
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
880883
}
881884

crates/hir-ty/src/tests/traits.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,31 @@ fn not_send() -> Box<dyn Future<Output = ()> + 'static> {
137137
);
138138
}
139139

140+
#[test]
141+
fn into_future_trait() {
142+
check_types(
143+
r#"
144+
//- minicore: future
145+
struct Futurable;
146+
impl core::future::IntoFuture for Futurable {
147+
type Output = u64;
148+
type IntoFuture = IntFuture;
149+
}
150+
151+
struct IntFuture;
152+
impl core::future::Future for IntFuture {
153+
type Output = u64;
154+
}
155+
156+
fn test() {
157+
let r = Futurable;
158+
let v = r.await;
159+
v;
160+
} //^ u64
161+
"#,
162+
);
163+
}
164+
140165
#[test]
141166
fn infer_try() {
142167
check_types(

crates/hir/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,6 +2780,8 @@ impl Type {
27802780
/// Checks that particular type `ty` implements `std::future::Future`.
27812781
/// This function is used in `.await` syntax completion.
27822782
pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
2783+
// FIXME: This should be checking for IntoFuture trait, but I don't know how to find the
2784+
// right TraitId in this crate.
27832785
let std_future_trait = db
27842786
.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))
27852787
.and_then(|it| it.as_trait());

crates/hir/src/source_analyzer.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ impl SourceAnalyzer {
269269
db: &dyn HirDatabase,
270270
await_expr: &ast::AwaitExpr,
271271
) -> 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.
272274
let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?;
273275

274276
let op_fn = db

crates/ide-assists/src/utils/suggest_name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const USELESS_METHODS: &[&str] = &[
5555
"iter",
5656
"into_iter",
5757
"iter_mut",
58+
"into_future",
5859
];
5960

6061
pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr {

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

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,17 @@ impl Future for A {}
7575
fn foo(a: A) { a.$0 }
7676
"#,
7777
expect![[r#"
78-
kw await expr.await
79-
sn box Box::new(expr)
80-
sn call function(expr)
81-
sn dbg dbg!(expr)
82-
sn dbgr dbg!(&expr)
83-
sn let let
84-
sn letm let mut
85-
sn match match expr {}
86-
sn ref &expr
87-
sn refm &mut expr
78+
kw await expr.await
79+
me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
80+
sn box Box::new(expr)
81+
sn call function(expr)
82+
sn dbg dbg!(expr)
83+
sn dbgr dbg!(&expr)
84+
sn let let
85+
sn letm let mut
86+
sn match match expr {}
87+
sn ref &expr
88+
sn refm &mut expr
8889
"#]],
8990
);
9091

@@ -98,18 +99,19 @@ fn foo() {
9899
}
99100
"#,
100101
expect![[r#"
101-
kw await expr.await
102-
sn box Box::new(expr)
103-
sn call function(expr)
104-
sn dbg dbg!(expr)
105-
sn dbgr dbg!(&expr)
106-
sn let let
107-
sn letm let mut
108-
sn match match expr {}
109-
sn ref &expr
110-
sn refm &mut expr
102+
kw await expr.await
103+
me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
104+
sn box Box::new(expr)
105+
sn call function(expr)
106+
sn dbg dbg!(expr)
107+
sn dbgr dbg!(&expr)
108+
sn let let
109+
sn letm let mut
110+
sn match match expr {}
111+
sn ref &expr
112+
sn refm &mut expr
111113
"#]],
112-
)
114+
);
113115
}
114116

115117
#[test]

crates/test-utils/src/minicore.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,21 @@ pub mod future {
471471
#[lang = "poll"]
472472
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
473473
}
474+
475+
pub trait IntoFuture {
476+
type Output;
477+
type IntoFuture: Future<Output = Self::Output>;
478+
#[lang = "into_future"]
479+
fn into_future(self) -> Self::IntoFuture;
480+
}
481+
482+
impl<F: Future> IntoFuture for F {
483+
type Output = F::Output;
484+
type IntoFuture = F;
485+
fn into_future(self) -> F {
486+
self
487+
}
488+
}
474489
}
475490
pub mod task {
476491
pub enum Poll<T> {

0 commit comments

Comments
 (0)