Infer box expression

This commit is contained in:
uHOOCCOOHu 2019-09-11 23:53:41 +08:00
parent 6ce6744e18
commit 8c078a0164
No known key found for this signature in database
GPG key ID: CED392DE0C483D00
7 changed files with 107 additions and 4 deletions

View file

@ -237,6 +237,9 @@ pub enum Expr {
expr: ExprId, expr: ExprId,
mutability: Mutability, mutability: Mutability,
}, },
Box {
expr: ExprId,
},
UnaryOp { UnaryOp {
expr: ExprId, expr: ExprId,
op: UnaryOp, op: UnaryOp,
@ -413,7 +416,8 @@ impl Expr {
| Expr::Try { expr } | Expr::Try { expr }
| Expr::Cast { expr, .. } | Expr::Cast { expr, .. }
| Expr::Ref { expr, .. } | Expr::Ref { expr, .. }
| Expr::UnaryOp { expr, .. } => { | Expr::UnaryOp { expr, .. }
| Expr::Box { expr } => {
f(*expr); f(*expr);
} }
Expr::Tuple { exprs } => { Expr::Tuple { exprs } => {

View file

@ -389,6 +389,10 @@ where
let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
} }
ast::Expr::BoxExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
self.alloc_expr(Expr::Box { expr }, syntax_ptr)
}
ast::Expr::ArrayExpr(e) => { ast::Expr::ArrayExpr(e) => {
let kind = e.kind(); let kind = e.kind();

View file

@ -119,6 +119,8 @@ pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6,
pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target"));
pub(crate) const BOXED_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed"));
pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
fn resolve_name(text: &SmolStr) -> SmolStr { fn resolve_name(text: &SmolStr) -> SmolStr {
let raw_start = "r#"; let raw_start = "r#";

View file

@ -1259,6 +1259,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let inner_ty = self.infer_expr(*expr, &expectation); let inner_ty = self.infer_expr(*expr, &expectation);
Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
} }
Expr::Box { expr } => {
let inner_ty = self.infer_expr(*expr, &Expectation::none());
if let Some(box_) = self.resolve_boxed_box() {
Ty::apply_one(TypeCtor::Adt(box_), inner_ty)
} else {
Ty::Unknown
}
}
Expr::UnaryOp { expr, op } => { Expr::UnaryOp { expr, op } => {
let inner_ty = self.infer_expr(*expr, &Expectation::none()); let inner_ty = self.infer_expr(*expr, &Expectation::none());
match op { match op {
@ -1499,6 +1507,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
_ => None, _ => None,
} }
} }
fn resolve_boxed_box(&self) -> Option<AdtDef> {
let boxed_box_path = Path {
kind: PathKind::Abs,
segments: vec![
PathSegment { name: name::STD, args_and_bindings: None },
PathSegment { name: name::BOXED_MOD, args_and_bindings: None },
PathSegment { name: name::BOX_TYPE, args_and_bindings: None },
],
};
match self.resolver.resolve_path_segments(self.db, &boxed_box_path).into_fully_resolved() {
PerNs { types: Some(Def(ModuleDef::Struct(struct_))), .. } => {
Some(AdtDef::Struct(struct_))
}
_ => None,
}
}
} }
/// The ID of a type variable. /// The ID of a type variable.

View file

@ -55,6 +55,37 @@ mod future {
assert_eq!("u64", type_at_pos(&db, pos)); assert_eq!("u64", type_at_pos(&db, pos));
} }
#[test]
fn infer_box() {
let (mut db, pos) = MockDatabase::with_position(
r#"
//- /main.rs
fn test() {
let x = box 1;
let t = (x, box x, box &1, box [1]);
t<|>;
}
//- /std.rs
#[prelude_import] use prelude::*;
mod prelude {}
mod boxed {
pub struct Box<T: ?Sized> {
inner: *mut T,
}
}
"#,
);
db.set_crate_graph_from_fixture(crate_graph! {
"main": ("/main.rs", ["std"]),
"std": ("/std.rs", []),
});
assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", 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(

View file

@ -307,6 +307,33 @@ impl BlockExpr {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BoxExpr {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for BoxExpr {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
BOX_EXPR => true,
_ => false,
}
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl BoxExpr {
pub fn expr(&self) -> Option<Expr> {
AstChildren::new(&self.syntax).next()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BoxPat { pub struct BoxPat {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
@ -649,6 +676,7 @@ pub enum Expr {
BinExpr(BinExpr), BinExpr(BinExpr),
Literal(Literal), Literal(Literal),
MacroCall(MacroCall), MacroCall(MacroCall),
BoxExpr(BoxExpr),
} }
impl From<TupleExpr> for Expr { impl From<TupleExpr> for Expr {
fn from(node: TupleExpr) -> Expr { fn from(node: TupleExpr) -> Expr {
@ -800,6 +828,11 @@ impl From<MacroCall> for Expr {
Expr::MacroCall(node) Expr::MacroCall(node)
} }
} }
impl From<BoxExpr> for Expr {
fn from(node: BoxExpr) -> Expr {
Expr::BoxExpr(node)
}
}
impl AstNode for Expr { impl AstNode for Expr {
fn can_cast(kind: SyntaxKind) -> bool { fn can_cast(kind: SyntaxKind) -> bool {
match kind { match kind {
@ -807,9 +840,8 @@ impl AstNode for Expr {
| LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
| BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
| METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_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 => { | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL
true | BOX_EXPR => true,
}
_ => false, _ => false,
} }
} }
@ -845,6 +877,7 @@ impl AstNode for Expr {
BIN_EXPR => Expr::BinExpr(BinExpr { syntax }), BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
LITERAL => Expr::Literal(Literal { syntax }), LITERAL => Expr::Literal(Literal { syntax }),
MACRO_CALL => Expr::MacroCall(MacroCall { syntax }), MACRO_CALL => Expr::MacroCall(MacroCall { syntax }),
BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }),
_ => return None, _ => return None,
}; };
Some(res) Some(res)
@ -881,6 +914,7 @@ impl AstNode for Expr {
Expr::BinExpr(it) => &it.syntax, Expr::BinExpr(it) => &it.syntax,
Expr::Literal(it) => &it.syntax, Expr::Literal(it) => &it.syntax,
Expr::MacroCall(it) => &it.syntax, Expr::MacroCall(it) => &it.syntax,
Expr::BoxExpr(it) => &it.syntax,
} }
} }
} }

View file

@ -483,6 +483,7 @@ Grammar(
"CastExpr": (options: ["Expr", "TypeRef"]), "CastExpr": (options: ["Expr", "TypeRef"]),
"RefExpr": (options: ["Expr"]), "RefExpr": (options: ["Expr"]),
"PrefixExpr": (options: ["Expr"]), "PrefixExpr": (options: ["Expr"]),
"BoxExpr": (options: ["Expr"]),
"RangeExpr": (), "RangeExpr": (),
"BinExpr": (), "BinExpr": (),
@ -520,6 +521,7 @@ Grammar(
"BinExpr", "BinExpr",
"Literal", "Literal",
"MacroCall", "MacroCall",
"BoxExpr",
], ],
), ),