aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/expr.rs6
-rw-r--r--crates/ra_hir/src/expr/lower.rs4
-rw-r--r--crates/ra_hir/src/name.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs26
-rw-r--r--crates/ra_hir/src/ty/tests.rs31
-rw-r--r--crates/ra_syntax/src/ast/generated.rs40
-rw-r--r--crates/ra_syntax/src/grammar.ron2
7 files changed, 107 insertions, 4 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 698fa671b..b1bec2a68 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -237,6 +237,9 @@ pub enum Expr {
237 expr: ExprId, 237 expr: ExprId,
238 mutability: Mutability, 238 mutability: Mutability,
239 }, 239 },
240 Box {
241 expr: ExprId,
242 },
240 UnaryOp { 243 UnaryOp {
241 expr: ExprId, 244 expr: ExprId,
242 op: UnaryOp, 245 op: UnaryOp,
@@ -413,7 +416,8 @@ impl Expr {
413 | Expr::Try { expr } 416 | Expr::Try { expr }
414 | Expr::Cast { expr, .. } 417 | Expr::Cast { expr, .. }
415 | Expr::Ref { expr, .. } 418 | Expr::Ref { expr, .. }
416 | Expr::UnaryOp { expr, .. } => { 419 | Expr::UnaryOp { expr, .. }
420 | Expr::Box { expr } => {
417 f(*expr); 421 f(*expr);
418 } 422 }
419 Expr::Tuple { exprs } => { 423 Expr::Tuple { exprs } => {
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index 8bd041ff0..2be6f5421 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -389,6 +389,10 @@ where
389 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); 389 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
390 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) 390 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
391 } 391 }
392 ast::Expr::BoxExpr(e) => {
393 let expr = self.collect_expr_opt(e.expr());
394 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
395 }
392 396
393 ast::Expr::ArrayExpr(e) => { 397 ast::Expr::ArrayExpr(e) => {
394 let kind = e.kind(); 398 let kind = e.kind();
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 13bc901bc..abdfec296 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -119,6 +119,8 @@ pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6,
119pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); 119pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
120pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); 120pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
121pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); 121pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target"));
122pub(crate) const BOXED_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed"));
123pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
122 124
123fn resolve_name(text: &SmolStr) -> SmolStr { 125fn resolve_name(text: &SmolStr) -> SmolStr {
124 let raw_start = "r#"; 126 let raw_start = "r#";
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 9244ff3cb..1057bbbec 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -1259,6 +1259,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1259 let inner_ty = self.infer_expr(*expr, &expectation); 1259 let inner_ty = self.infer_expr(*expr, &expectation);
1260 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 1260 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
1261 } 1261 }
1262 Expr::Box { expr } => {
1263 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1264 if let Some(box_) = self.resolve_boxed_box() {
1265 Ty::apply_one(TypeCtor::Adt(box_), inner_ty)
1266 } else {
1267 Ty::Unknown
1268 }
1269 }
1262 Expr::UnaryOp { expr, op } => { 1270 Expr::UnaryOp { expr, op } => {
1263 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 1271 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1264 match op { 1272 match op {
@@ -1499,6 +1507,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1499 _ => None, 1507 _ => None,
1500 } 1508 }
1501 } 1509 }
1510
1511 fn resolve_boxed_box(&self) -> Option<AdtDef> {
1512 let boxed_box_path = Path {
1513 kind: PathKind::Abs,
1514 segments: vec![
1515 PathSegment { name: name::STD, args_and_bindings: None },
1516 PathSegment { name: name::BOXED_MOD, args_and_bindings: None },
1517 PathSegment { name: name::BOX_TYPE, args_and_bindings: None },
1518 ],
1519 };
1520
1521 match self.resolver.resolve_path_segments(self.db, &boxed_box_path).into_fully_resolved() {
1522 PerNs { types: Some(Def(ModuleDef::Struct(struct_))), .. } => {
1523 Some(AdtDef::Struct(struct_))
1524 }
1525 _ => None,
1526 }
1527 }
1502} 1528}
1503 1529
1504/// The ID of a type variable. 1530/// The ID of a type variable.
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 869ae13f1..9a5f6949d 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -56,6 +56,37 @@ mod future {
56} 56}
57 57
58#[test] 58#[test]
59fn infer_box() {
60 let (mut db, pos) = MockDatabase::with_position(
61 r#"
62//- /main.rs
63
64fn test() {
65 let x = box 1;
66 let t = (x, box x, box &1, box [1]);
67 t<|>;
68}
69
70//- /std.rs
71#[prelude_import] use prelude::*;
72mod prelude {}
73
74mod boxed {
75 pub struct Box<T: ?Sized> {
76 inner: *mut T,
77 }
78}
79
80"#,
81 );
82 db.set_crate_graph_from_fixture(crate_graph! {
83 "main": ("/main.rs", ["std"]),
84 "std": ("/std.rs", []),
85 });
86 assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos));
87}
88
89#[test]
59fn infer_try() { 90fn infer_try() {
60 let (mut db, pos) = MockDatabase::with_position( 91 let (mut db, pos) = MockDatabase::with_position(
61 r#" 92 r#"
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index d274b6fbc..a8a231ef3 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -307,6 +307,33 @@ impl BlockExpr {
307 } 307 }
308} 308}
309#[derive(Debug, Clone, PartialEq, Eq, Hash)] 309#[derive(Debug, Clone, PartialEq, Eq, Hash)]
310pub struct BoxExpr {
311 pub(crate) syntax: SyntaxNode,
312}
313impl AstNode for BoxExpr {
314 fn can_cast(kind: SyntaxKind) -> bool {
315 match kind {
316 BOX_EXPR => true,
317 _ => false,
318 }
319 }
320 fn cast(syntax: SyntaxNode) -> Option<Self> {
321 if Self::can_cast(syntax.kind()) {
322 Some(Self { syntax })
323 } else {
324 None
325 }
326 }
327 fn syntax(&self) -> &SyntaxNode {
328 &self.syntax
329 }
330}
331impl BoxExpr {
332 pub fn expr(&self) -> Option<Expr> {
333 AstChildren::new(&self.syntax).next()
334 }
335}
336#[derive(Debug, Clone, PartialEq, Eq, Hash)]
310pub struct BoxPat { 337pub struct BoxPat {
311 pub(crate) syntax: SyntaxNode, 338 pub(crate) syntax: SyntaxNode,
312} 339}
@@ -649,6 +676,7 @@ pub enum Expr {
649 BinExpr(BinExpr), 676 BinExpr(BinExpr),
650 Literal(Literal), 677 Literal(Literal),
651 MacroCall(MacroCall), 678 MacroCall(MacroCall),
679 BoxExpr(BoxExpr),
652} 680}
653impl From<TupleExpr> for Expr { 681impl From<TupleExpr> for Expr {
654 fn from(node: TupleExpr) -> Expr { 682 fn from(node: TupleExpr) -> Expr {
@@ -800,6 +828,11 @@ impl From<MacroCall> for Expr {
800 Expr::MacroCall(node) 828 Expr::MacroCall(node)
801 } 829 }
802} 830}
831impl From<BoxExpr> for Expr {
832 fn from(node: BoxExpr) -> Expr {
833 Expr::BoxExpr(node)
834 }
835}
803impl AstNode for Expr { 836impl AstNode for Expr {
804 fn can_cast(kind: SyntaxKind) -> bool { 837 fn can_cast(kind: SyntaxKind) -> bool {
805 match kind { 838 match kind {
@@ -807,9 +840,8 @@ impl AstNode for Expr {
807 | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL 840 | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
808 | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR 841 | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
809 | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR 842 | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR
810 | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL => { 843 | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL
811 true 844 | BOX_EXPR => true,
812 }
813 _ => false, 845 _ => false,
814 } 846 }
815 } 847 }
@@ -845,6 +877,7 @@ impl AstNode for Expr {
845 BIN_EXPR => Expr::BinExpr(BinExpr { syntax }), 877 BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
846 LITERAL => Expr::Literal(Literal { syntax }), 878 LITERAL => Expr::Literal(Literal { syntax }),
847 MACRO_CALL => Expr::MacroCall(MacroCall { syntax }), 879 MACRO_CALL => Expr::MacroCall(MacroCall { syntax }),
880 BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }),
848 _ => return None, 881 _ => return None,
849 }; 882 };
850 Some(res) 883 Some(res)
@@ -881,6 +914,7 @@ impl AstNode for Expr {
881 Expr::BinExpr(it) => &it.syntax, 914 Expr::BinExpr(it) => &it.syntax,
882 Expr::Literal(it) => &it.syntax, 915 Expr::Literal(it) => &it.syntax,
883 Expr::MacroCall(it) => &it.syntax, 916 Expr::MacroCall(it) => &it.syntax,
917 Expr::BoxExpr(it) => &it.syntax,
884 } 918 }
885 } 919 }
886} 920}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 993e58e64..8f064711d 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -483,6 +483,7 @@ Grammar(
483 "CastExpr": (options: ["Expr", "TypeRef"]), 483 "CastExpr": (options: ["Expr", "TypeRef"]),
484 "RefExpr": (options: ["Expr"]), 484 "RefExpr": (options: ["Expr"]),
485 "PrefixExpr": (options: ["Expr"]), 485 "PrefixExpr": (options: ["Expr"]),
486 "BoxExpr": (options: ["Expr"]),
486 "RangeExpr": (), 487 "RangeExpr": (),
487 "BinExpr": (), 488 "BinExpr": (),
488 489
@@ -520,6 +521,7 @@ Grammar(
520 "BinExpr", 521 "BinExpr",
521 "Literal", 522 "Literal",
522 "MacroCall", 523 "MacroCall",
524 "BoxExpr",
523 ], 525 ],
524 ), 526 ),
525 527