Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement IntoFuture type inference #12982

Merged
merged 3 commits into from
Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/hir-expand/src/mod_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ macro_rules! __known_path {
(core::ops::RangeToInclusive) => {};
(core::ops::RangeInclusive) => {};
(core::future::Future) => {};
(core::future::IntoFuture) => {};
(core::ops::Try) => {};
($path:path) => {
compile_error!("Please register your known path in the path module")
Expand Down
2 changes: 2 additions & 0 deletions crates/hir-expand/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ pub mod known {
Try,
Ok,
Future,
IntoFuture,
Result,
Option,
Output,
Expand Down Expand Up @@ -391,6 +392,7 @@ pub mod known {
future_trait,
index,
index_mut,
into_future,
mul_assign,
mul,
neg,
Expand Down
5 changes: 4 additions & 1 deletion crates/hir-ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,10 @@ impl<'a> InferenceContext<'a> {
}

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

Expand Down
25 changes: 25 additions & 0 deletions crates/hir-ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,31 @@ fn not_send() -> Box<dyn Future<Output = ()> + 'static> {
);
}

#[test]
fn into_future_trait() {
check_types(
r#"
//- minicore: future
struct Futurable;
impl core::future::IntoFuture for Futurable {
type Output = u64;
type IntoFuture = IntFuture;
}

struct IntFuture;
impl core::future::Future for IntFuture {
type Output = u64;
}

fn test() {
let r = Futurable;
let v = r.await;
v;
} //^ u64
"#,
);
}

#[test]
fn infer_try() {
check_types(
Expand Down
2 changes: 2 additions & 0 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2780,6 +2780,8 @@ impl Type {
/// Checks that particular type `ty` implements `std::future::Future`.
/// This function is used in `.await` syntax completion.
pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
// FIXME: This should be checking for IntoFuture trait, but I don't know how to find the
// right TraitId in this crate.
jridgewell marked this conversation as resolved.
Show resolved Hide resolved
let std_future_trait = db
.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))
.and_then(|it| it.as_trait());
Expand Down
2 changes: 2 additions & 0 deletions crates/hir/src/source_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ impl SourceAnalyzer {
db: &dyn HirDatabase,
await_expr: &ast::AwaitExpr,
) -> Option<FunctionId> {
// FIXME This should be pointing to the poll of IntoFuture::Output's Future impl, but I
// don't know how to resolve the Output type so that we can query for its poll method.
jridgewell marked this conversation as resolved.
Show resolved Hide resolved
let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?;

let op_fn = db
Expand Down
1 change: 1 addition & 0 deletions crates/ide-assists/src/utils/suggest_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const USELESS_METHODS: &[&str] = &[
"iter",
"into_iter",
"iter_mut",
"into_future",
];

pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr {
Expand Down
44 changes: 23 additions & 21 deletions crates/ide-completion/src/completions/keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,17 @@ impl Future for A {}
fn foo(a: A) { a.$0 }
"#,
expect![[r#"
kw await expr.await
sn box Box::new(expr)
sn call function(expr)
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn let let
sn letm let mut
sn match match expr {}
sn ref &expr
sn refm &mut expr
kw await expr.await
me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
sn box Box::new(expr)
sn call function(expr)
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn let let
sn letm let mut
sn match match expr {}
sn ref &expr
sn refm &mut expr
"#]],
);

Expand All @@ -98,18 +99,19 @@ fn foo() {
}
"#,
expect![[r#"
kw await expr.await
sn box Box::new(expr)
sn call function(expr)
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn let let
sn letm let mut
sn match match expr {}
sn ref &expr
sn refm &mut expr
kw await expr.await
me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
sn box Box::new(expr)
sn call function(expr)
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn let let
sn letm let mut
sn match match expr {}
sn ref &expr
sn refm &mut expr
"#]],
)
);
}

#[test]
Expand Down
15 changes: 15 additions & 0 deletions crates/test-utils/src/minicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,21 @@ pub mod future {
#[lang = "poll"]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

pub trait IntoFuture {
type Output;
type IntoFuture: Future<Output = Self::Output>;
#[lang = "into_future"]
fn into_future(self) -> Self::IntoFuture;
}

impl<F: Future> IntoFuture for F {
type Output = F::Output;
type IntoFuture = F;
fn into_future(self) -> F {
self
}
}
}
pub mod task {
pub enum Poll<T> {
Expand Down