mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
infer type for await
by projecting inner_ty to Future::Output alias
This commit is contained in:
parent
5ac9f5cdc7
commit
bacf926a77
@ -118,6 +118,9 @@ pub(crate) const ITEM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item
|
|||||||
pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops"));
|
pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops"));
|
||||||
pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try"));
|
pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try"));
|
||||||
pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
|
pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
|
||||||
|
pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
|
||||||
|
pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
|
||||||
|
pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
|
||||||
|
|
||||||
fn resolve_name(text: &SmolStr) -> SmolStr {
|
fn resolve_name(text: &SmolStr) -> SmolStr {
|
||||||
let raw_start = "r#";
|
let raw_start = "r#";
|
||||||
|
@ -1114,8 +1114,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
.unwrap_or(Ty::Unknown);
|
.unwrap_or(Ty::Unknown);
|
||||||
self.insert_type_vars(ty)
|
self.insert_type_vars(ty)
|
||||||
}
|
}
|
||||||
Expr::Await { .. } => {
|
Expr::Await { expr } => {
|
||||||
Ty::Unknown
|
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||||
|
let ty = match self.resolve_future_future_output() {
|
||||||
|
Some(future_future_output_alias) => {
|
||||||
|
let ty = self.new_type_var();
|
||||||
|
let projection = ProjectionPredicate {
|
||||||
|
ty: ty.clone(),
|
||||||
|
projection_ty: ProjectionTy {
|
||||||
|
associated_ty: future_future_output_alias,
|
||||||
|
parameters: vec![inner_ty].into(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.obligations.push(Obligation::Projection(projection));
|
||||||
|
self.resolve_ty_as_possible(&mut vec![], ty)
|
||||||
|
}
|
||||||
|
None => Ty::Unknown,
|
||||||
|
};
|
||||||
|
ty
|
||||||
}
|
}
|
||||||
Expr::Try { expr } => {
|
Expr::Try { expr } => {
|
||||||
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||||
@ -1371,6 +1387,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_future_future_output(&self) -> Option<TypeAlias> {
|
||||||
|
let future_future_path = Path {
|
||||||
|
kind: PathKind::Abs,
|
||||||
|
segments: vec![
|
||||||
|
PathSegment { name: name::STD, args_and_bindings: None },
|
||||||
|
PathSegment { name: name::FUTURE_MOD, args_and_bindings: None },
|
||||||
|
PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
match self
|
||||||
|
.resolver
|
||||||
|
.resolve_path_segments(self.db, &future_future_path)
|
||||||
|
.into_fully_resolved()
|
||||||
|
{
|
||||||
|
PerNs { types: Some(Def(Trait(trait_))), .. } => {
|
||||||
|
Some(trait_.associated_type_by_name(self.db, name::OUTPUT)?)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ID of a type variable.
|
/// The ID of a type variable.
|
||||||
|
@ -20,6 +20,41 @@ use crate::{
|
|||||||
// against snapshots of the expected results using insta. Use cargo-insta to
|
// against snapshots of the expected results using insta. Use cargo-insta to
|
||||||
// update the snapshots.
|
// update the snapshots.
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_await() {
|
||||||
|
let (mut db, pos) = MockDatabase::with_position(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
|
||||||
|
struct IntFuture;
|
||||||
|
|
||||||
|
impl Future for IntFuture {
|
||||||
|
type Output = u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let r = IntFuture;
|
||||||
|
let v = r.await;
|
||||||
|
v<|>;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /std.rs
|
||||||
|
#[prelude_import] use future::*;
|
||||||
|
mod future {
|
||||||
|
trait Future {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
db.set_crate_graph_from_fixture(crate_graph! {
|
||||||
|
"main": ("/main.rs", ["std"]),
|
||||||
|
"std": ("/std.rs", []),
|
||||||
|
});
|
||||||
|
assert_eq!("u64", type_at_pos(&db, pos));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_try() {
|
fn infer_try() {
|
||||||
let (mut db, pos) = MockDatabase::with_position(
|
let (mut db, pos) = MockDatabase::with_position(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user