mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-26 05:44:26 +00:00
Merge #1562
1562: Continue support for .await r=matklad a=unrealhoang - add await expr to ast and HIR Expr - infer type for `.await` Co-authored-by: Unreal Hoang <unrealhoang@gmail.com>
This commit is contained in:
commit
dac6adbef9
@ -220,6 +220,9 @@ pub enum Expr {
|
||||
expr: ExprId,
|
||||
name: Name,
|
||||
},
|
||||
Await {
|
||||
expr: ExprId,
|
||||
},
|
||||
Try {
|
||||
expr: ExprId,
|
||||
},
|
||||
@ -359,6 +362,7 @@ impl Expr {
|
||||
f(*rhs);
|
||||
}
|
||||
Expr::Field { expr, .. }
|
||||
| Expr::Await { expr }
|
||||
| Expr::Try { expr }
|
||||
| Expr::Cast { expr, .. }
|
||||
| Expr::Ref { expr, .. }
|
||||
@ -729,6 +733,10 @@ where
|
||||
};
|
||||
self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
|
||||
}
|
||||
ast::ExprKind::AwaitExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
self.alloc_expr(Expr::Await { expr }, syntax_ptr)
|
||||
}
|
||||
ast::ExprKind::TryExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
self.alloc_expr(Expr::Try { expr }, syntax_ptr)
|
||||
|
@ -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 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 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 {
|
||||
let raw_start = "r#";
|
||||
|
@ -1114,6 +1114,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
.unwrap_or(Ty::Unknown);
|
||||
self.insert_type_vars(ty)
|
||||
}
|
||||
Expr::Await { expr } => {
|
||||
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 } => {
|
||||
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||
let ty = match self.resolve_ops_try_ok() {
|
||||
@ -1368,6 +1387,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
_ => 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.
|
||||
|
@ -20,6 +20,41 @@ use crate::{
|
||||
// against snapshots of the expected results using insta. Use cargo-insta to
|
||||
// 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]
|
||||
fn infer_try() {
|
||||
let (mut db, pos) = MockDatabase::with_position(
|
||||
|
@ -175,6 +175,32 @@ impl Attr {
|
||||
}
|
||||
}
|
||||
|
||||
// AwaitExpr
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct AwaitExpr {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
|
||||
impl AstNode for AwaitExpr {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
AWAIT_EXPR => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) { Some(AwaitExpr { syntax }) } else { None }
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
|
||||
|
||||
impl AwaitExpr {
|
||||
pub fn expr(&self) -> Option<Expr> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// BinExpr
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct BinExpr {
|
||||
@ -566,7 +592,7 @@ pub struct Expr {
|
||||
impl AstNode for Expr {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
| TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | STRUCT_LIT | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR | FIELD_EXPR | TRY_EXPR | TRY_BLOCK_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL => true,
|
||||
| TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | STRUCT_LIT | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -599,6 +625,7 @@ pub enum ExprKind {
|
||||
IndexExpr(IndexExpr),
|
||||
MethodCallExpr(MethodCallExpr),
|
||||
FieldExpr(FieldExpr),
|
||||
AwaitExpr(AwaitExpr),
|
||||
TryExpr(TryExpr),
|
||||
TryBlockExpr(TryBlockExpr),
|
||||
CastExpr(CastExpr),
|
||||
@ -669,6 +696,9 @@ impl From<MethodCallExpr> for Expr {
|
||||
impl From<FieldExpr> for Expr {
|
||||
fn from(n: FieldExpr) -> Expr { Expr { syntax: n.syntax } }
|
||||
}
|
||||
impl From<AwaitExpr> for Expr {
|
||||
fn from(n: AwaitExpr) -> Expr { Expr { syntax: n.syntax } }
|
||||
}
|
||||
impl From<TryExpr> for Expr {
|
||||
fn from(n: TryExpr) -> Expr { Expr { syntax: n.syntax } }
|
||||
}
|
||||
@ -719,6 +749,7 @@ impl Expr {
|
||||
INDEX_EXPR => ExprKind::IndexExpr(IndexExpr::cast(self.syntax.clone()).unwrap()),
|
||||
METHOD_CALL_EXPR => ExprKind::MethodCallExpr(MethodCallExpr::cast(self.syntax.clone()).unwrap()),
|
||||
FIELD_EXPR => ExprKind::FieldExpr(FieldExpr::cast(self.syntax.clone()).unwrap()),
|
||||
AWAIT_EXPR => ExprKind::AwaitExpr(AwaitExpr::cast(self.syntax.clone()).unwrap()),
|
||||
TRY_EXPR => ExprKind::TryExpr(TryExpr::cast(self.syntax.clone()).unwrap()),
|
||||
TRY_BLOCK_EXPR => ExprKind::TryBlockExpr(TryBlockExpr::cast(self.syntax.clone()).unwrap()),
|
||||
CAST_EXPR => ExprKind::CastExpr(CastExpr::cast(self.syntax.clone()).unwrap()),
|
||||
|
@ -477,6 +477,7 @@ Grammar(
|
||||
),
|
||||
"IndexExpr": (),
|
||||
"FieldExpr": (options: ["Expr", "NameRef"]),
|
||||
"AwaitExpr": (options: ["Expr"]),
|
||||
"TryExpr": (options: ["Expr"]),
|
||||
"CastExpr": (options: ["Expr", "TypeRef"]),
|
||||
"RefExpr": (options: ["Expr"]),
|
||||
@ -508,6 +509,7 @@ Grammar(
|
||||
"IndexExpr",
|
||||
"MethodCallExpr",
|
||||
"FieldExpr",
|
||||
"AwaitExpr",
|
||||
"TryExpr",
|
||||
"TryBlockExpr",
|
||||
"CastExpr",
|
||||
|
Loading…
Reference in New Issue
Block a user