mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Implement IntoFuture type inference
This commit is contained in:
parent
3792720086
commit
5810c8188a
9 changed files with 75 additions and 22 deletions
|
@ -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")
|
||||
|
|
|
@ -258,6 +258,7 @@ pub mod known {
|
|||
Try,
|
||||
Ok,
|
||||
Future,
|
||||
IntoFuture,
|
||||
Result,
|
||||
Option,
|
||||
Output,
|
||||
|
@ -391,6 +392,7 @@ pub mod known {
|
|||
future_trait,
|
||||
index,
|
||||
index_mut,
|
||||
into_future,
|
||||
mul_assign,
|
||||
mul,
|
||||
neg,
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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.
|
||||
let std_future_trait = db
|
||||
.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))
|
||||
.and_then(|it| it.as_trait());
|
||||
|
|
|
@ -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.
|
||||
let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?;
|
||||
|
||||
let op_fn = db
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
"#]],
|
||||
);
|
||||
|
||||
|
@ -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]
|
||||
|
|
|
@ -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> {
|
||||
|
|
Loading…
Reference in a new issue