aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLenard Pratt <[email protected]>2019-03-30 11:17:31 +0000
committerLenard Pratt <[email protected]>2019-04-02 19:21:36 +0100
commit88e22e9d70ac3a35989ad1d45386f86697877c4c (patch)
tree274537eb5913369a7f226aca534fbf3821395181 /crates
parent7f3bf7cc738d02fde80d4fde9f32cbbe72896b87 (diff)
Added const bodies and static body to the ast
and added inference the inference test reduce code duplication
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model_api.rs87
-rw-r--r--crates/ra_hir/src/db.rs2
-rw-r--r--crates/ra_hir/src/expr.rs36
-rw-r--r--crates/ra_hir/src/expr/scope.rs3
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/source_binder.rs44
-rw-r--r--crates/ra_hir/src/ty/infer.rs20
-rw-r--r--crates/ra_hir/src/ty/tests.rs61
-rw-r--r--crates/ra_syntax/src/ast/generated.rs13
-rw-r--r--crates/ra_syntax/src/grammar.ron4
10 files changed, 180 insertions, 91 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index db6e67d7f..c3e5e26c3 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -436,65 +436,33 @@ impl Docs for EnumVariant {
436/// The defs which have a body. 436/// The defs which have a body.
437#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 437#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
438pub enum DefWithBody { 438pub enum DefWithBody {
439 Func(Function), 439 Function(Function),
440 Const(Const), 440 Const(Const),
441 Static(Static), 441 Static(Static),
442} 442}
443 443
444impl DefWithBody { 444impl_froms!(DefWithBody: Function, Const, Static);
445 pub fn get_funct(&self) -> &Function {
446 match *self {
447 DefWithBody::Func(ref f) => f,
448 _ => unreachable!()
449 }
450 }
451
452 pub fn const_source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) {
453 match *self {
454 DefWithBody::Const(ref c) => c.source(db),
455 _ => unreachable!()
456 }
457 }
458
459 pub fn func_source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::FnDef>) {
460 match *self {
461 DefWithBody::Func(ref f) => f.source(db),
462 _ => unreachable!()
463 }
464 }
465
466 pub fn static_source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) {
467 match *self {
468 DefWithBody::Static(ref s) => s.source(db),
469 _ => unreachable!()
470 }
471 }
472 445
446impl DefWithBody {
473 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 447 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
474 db.infer(*self) 448 db.infer(*self)
475 } 449 }
476 450
451 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
452 db.body_with_source_map(*self).1
453 }
454
477 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 455 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
478 db.body_hir(*self) 456 db.body_hir(*self)
479 } 457 }
480 458
481 /// Builds a resolver for code inside this item. 459 /// Builds a resolver for code inside this item.
482 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 460 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
483 // // take the outer scope... 461 match *self {
484 // let r = self 462 DefWithBody::Const(ref c) => c.resolver(db),
485 // .impl_block(db) 463 DefWithBody::Function(ref f) => f.resolver(db),
486 // .map(|ib| ib.resolver(db)) 464 DefWithBody::Static(ref s) => s.resolver(db),
487 // .unwrap_or_else(|| self.module(db).resolver(db)); 465 }
488 // // ...and add generic params, if present
489 // let p = self.generic_params(db);
490 // let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
491 // r
492 unimplemented!()
493 }
494
495 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
496 // db.fn_signature(*self)
497 unimplemented!()
498 } 466 }
499 467
500 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap { 468 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
@@ -502,7 +470,6 @@ impl DefWithBody {
502 let source_map = db.body_with_source_map(*self).1; 470 let source_map = db.body_with_source_map(*self).1;
503 ScopesWithSourceMap { scopes, source_map } 471 ScopesWithSourceMap { scopes, source_map }
504 } 472 }
505
506} 473}
507 474
508#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 475#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -555,11 +522,11 @@ impl Function {
555 } 522 }
556 523
557 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 524 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
558 db.body_with_source_map(DefWithBody::Func(*self)).1 525 db.body_with_source_map((*self).into()).1
559 } 526 }
560 527
561 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 528 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
562 db.body_hir(DefWithBody::Func(*self)) 529 db.body_hir((*self).into())
563 } 530 }
564 531
565 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 532 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
@@ -567,8 +534,8 @@ impl Function {
567 } 534 }
568 535
569 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap { 536 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
570 let scopes = db.expr_scopes( DefWithBody::Func(*self)); 537 let scopes = db.expr_scopes((*self).into());
571 let source_map = db.body_with_source_map(DefWithBody::Func(*self)).1; 538 let source_map = db.body_with_source_map((*self).into()).1;
572 ScopesWithSourceMap { scopes, source_map } 539 ScopesWithSourceMap { scopes, source_map }
573 } 540 }
574 541
@@ -577,7 +544,7 @@ impl Function {
577 } 544 }
578 545
579 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 546 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
580 db.infer(DefWithBody::Func(*self)) 547 db.infer((*self).into())
581 } 548 }
582 549
583 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { 550 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
@@ -633,6 +600,14 @@ impl Const {
633 db.const_signature(*self) 600 db.const_signature(*self)
634 } 601 }
635 602
603 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
604 db.infer((*self).into())
605 }
606
607 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
608 db.body_with_source_map((*self).into()).1
609 }
610
636 /// The containing impl block, if this is a method. 611 /// The containing impl block, if this is a method.
637 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 612 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
638 let module_impls = db.impls_in_module(self.module(db)); 613 let module_impls = db.impls_in_module(self.module(db));
@@ -697,6 +672,14 @@ impl Static {
697 // take the outer scope... 672 // take the outer scope...
698 self.module(db).resolver(db) 673 self.module(db).resolver(db)
699 } 674 }
675
676 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
677 db.infer((*self).into())
678 }
679
680 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
681 db.body_with_source_map((*self).into()).1
682 }
700} 683}
701 684
702impl Docs for Static { 685impl Docs for Static {
@@ -788,4 +771,4 @@ impl Docs for TypeAlias {
788 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> { 771 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
789 docs_from_ast(&*self.source(db).1) 772 docs_from_ast(&*self.source(db).1)
790 } 773 }
791} \ No newline at end of file 774}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index a2aff241c..be8a8c98b 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -87,7 +87,7 @@ pub trait HirDatabase: DefDatabase {
87 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>; 87 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
88 88
89 #[salsa::invoke(crate::ty::infer)] 89 #[salsa::invoke(crate::ty::infer)]
90 fn infer(&self, def:DefWithBody) -> Arc<InferenceResult>; 90 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
91 91
92 #[salsa::invoke(crate::ty::type_for_def)] 92 #[salsa::invoke(crate::ty::type_for_def)]
93 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; 93 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty;
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 280746761..bc4c63d3c 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -10,7 +10,7 @@ use ra_syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Function, Resolver,DefWithBody, 13 Path, Name, HirDatabase, Resolver,DefWithBody,
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
@@ -27,8 +27,7 @@ impl_arena_id!(ExprId);
27/// The body of an item (function, const etc.). 27/// The body of an item (function, const etc.).
28#[derive(Debug, Eq, PartialEq)] 28#[derive(Debug, Eq, PartialEq)]
29pub struct Body { 29pub struct Body {
30 // FIXME: this should be more general, consts & statics also have bodies 30 /// The def of the item this body belongs to
31 /// The Function of the item this body belongs to
32 owner: DefWithBody, 31 owner: DefWithBody,
33 exprs: Arena<ExprId, Expr>, 32 exprs: Arena<ExprId, Expr>,
34 pats: Arena<PatId, Pat>, 33 pats: Arena<PatId, Pat>,
@@ -503,9 +502,6 @@ impl ExprCollector {
503 self.exprs.alloc(block) 502 self.exprs.alloc(block)
504 } 503 }
505 504
506
507
508
509 fn collect_expr(&mut self, expr: &ast::Expr) -> ExprId { 505 fn collect_expr(&mut self, expr: &ast::Expr) -> ExprId {
510 let syntax_ptr = SyntaxNodePtr::new(expr.syntax()); 506 let syntax_ptr = SyntaxNodePtr::new(expr.syntax());
511 match expr.kind() { 507 match expr.kind() {
@@ -874,13 +870,14 @@ impl ExprCollector {
874 } 870 }
875 } 871 }
876 872
877 873 fn collect_const_body(&mut self, node: &ast::ConstDef) {
878 fn collect_const_body(&mut self,node:&ast::ConstDef) { 874 let body = self.collect_expr_opt(node.body());
879 875 self.body_expr = Some(body);
880 } 876 }
881 877
882 fn collect_static_body(&mut self,node:&ast::StaticDef) { 878 fn collect_static_body(&mut self, node: &ast::StaticDef) {
883 879 let body = self.collect_expr_opt(node.body());
880 self.body_expr = Some(body);
884 } 881 }
885 882
886 fn collect_fn_body(&mut self, node: &ast::FnDef) { 883 fn collect_fn_body(&mut self, node: &ast::FnDef) {
@@ -931,28 +928,27 @@ pub(crate) fn body_with_source_map_query(
931 db: &impl HirDatabase, 928 db: &impl HirDatabase,
932 def: DefWithBody, 929 def: DefWithBody,
933) -> (Arc<Body>, Arc<BodySourceMap>) { 930) -> (Arc<Body>, Arc<BodySourceMap>) {
934
935 let mut collector = ExprCollector::new(def); 931 let mut collector = ExprCollector::new(def);
936 932
937 // FIXME: do can this be turned into a method
938
939 match def { 933 match def {
940 DefWithBody::Const(ref c) => collector.collect_const_body(&def.const_source(db).1), 934 DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1),
941 DefWithBody::Func(ref f) => collector.collect_fn_body(&def.func_source(db).1), 935 DefWithBody::Function(ref f) => collector.collect_fn_body(&f.source(db).1),
942 DefWithBody::Static(ref s) => collector.collect_static_body(&def.static_source(db).1) 936 DefWithBody::Static(ref s) => collector.collect_static_body(&s.source(db).1),
943 } 937 }
944 938
945 let (body, source_map) = collector.finish(); 939 let (body, source_map) = collector.finish();
946 (Arc::new(body), Arc::new(source_map)) 940 (Arc::new(body), Arc::new(source_map))
947} 941}
948 942
949pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> { 943pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
950 db.body_with_source_map(def).0 944 db.body_with_source_map(def).0
951} 945}
952 946
953#[cfg(test)] 947#[cfg(test)]
948use crate::{Function};
949#[cfg(test)]
954fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) { 950fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
955 let mut collector = ExprCollector::new(function); 951 let mut collector = ExprCollector::new(DefWithBody::Function(function));
956 collector.collect_fn_body(node); 952 collector.collect_fn_body(node);
957 collector.finish() 953 collector.finish()
958} 954}
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 539da06c3..9d6b1eb2b 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -10,7 +10,7 @@ use ra_syntax::{
10use ra_arena::{Arena, RawId, impl_arena_id}; 10use ra_arena::{Arena, RawId, impl_arena_id};
11 11
12use crate::{ 12use crate::{
13 Name, AsName, Function,DefWithBody, 13 Name, AsName,DefWithBody,
14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap}, 14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap},
15 HirDatabase, 15 HirDatabase,
16}; 16};
@@ -297,6 +297,7 @@ mod tests {
297 use ra_syntax::{SourceFile, algo::find_node_at_offset}; 297 use ra_syntax::{SourceFile, algo::find_node_at_offset};
298 use test_utils::{extract_offset, assert_eq_text}; 298 use test_utils::{extract_offset, assert_eq_text};
299 use ra_arena::ArenaId; 299 use ra_arena::ArenaId;
300 use crate::{Function};
300 301
301 use crate::expr; 302 use crate::expr;
302 303
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 62cec72d9..5b6abcf6d 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -74,5 +74,4 @@ pub use self::code_model_api::{
74 StructField, FieldSource, 74 StructField, FieldSource,
75 Static, Const, ConstSignature, 75 Static, Const, ConstSignature,
76 Trait, TypeAlias, 76 Trait, TypeAlias,
77
78}; 77};
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 9dae4c3d1..430dbc522 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,7 +13,7 @@ use ra_syntax::{
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, Struct, Enum, 16 HirDatabase, Function, Struct, Enum,Const,Static,
17 AsName, Module, HirFileId, Crate, Trait, Resolver, 17 AsName, Module, HirFileId, Crate, Trait, Resolver,
18 ids::LocationCtx, 18 ids::LocationCtx,
19 expr, AstId 19 expr, AstId
@@ -87,6 +87,27 @@ fn module_from_source(
87 ) 87 )
88} 88}
89 89
90pub fn const_from_source(
91 db: &impl HirDatabase,
92 file_id: FileId,
93 const_def: &ast::ConstDef,
94) -> Option<Const> {
95 let module = module_from_child_node(db, file_id, const_def.syntax())?;
96 let res = const_from_module(db, module, const_def);
97 Some(res)
98}
99
100pub fn const_from_module(
101 db: &impl HirDatabase,
102 module: Module,
103 const_def: &ast::ConstDef,
104) -> Const {
105 let (file_id, _) = module.definition_source(db);
106 let file_id = file_id.into();
107 let ctx = LocationCtx::new(db, module, file_id);
108 Const { id: ctx.to_def(const_def) }
109}
110
90pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { 111pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
91 let file = db.parse(position.file_id); 112 let file = db.parse(position.file_id);
92 let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?; 113 let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
@@ -134,6 +155,27 @@ pub fn struct_from_module(
134 Struct { id: ctx.to_def(struct_def) } 155 Struct { id: ctx.to_def(struct_def) }
135} 156}
136 157
158pub fn static_from_source(
159 db: &impl HirDatabase,
160 file_id: FileId,
161 static_def: &ast::StaticDef,
162) -> Option<Static> {
163 let module = module_from_child_node(db, file_id, static_def.syntax())?;
164 let res = static_from_module(db, module, static_def);
165 Some(res)
166}
167
168pub fn static_from_module(
169 db: &impl HirDatabase,
170 module: Module,
171 static_def: &ast::StaticDef,
172) -> Static {
173 let (file_id, _) = module.definition_source(db);
174 let file_id = file_id.into();
175 let ctx = LocationCtx::new(db, module, file_id);
176 Static { id: ctx.to_def(static_def) }
177}
178
137pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { 179pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
138 let (file_id, _) = module.definition_source(db); 180 let (file_id, _) = module.definition_source(db);
139 let file_id = file_id.into(); 181 let file_id = file_id.into();
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 573115321..887153484 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -27,8 +27,9 @@ use test_utils::tested_by;
27 27
28use crate::{ 28use crate::{
29 Function, StructField, Path, Name, 29 Function, StructField, Path, Name,
30 FnSignature, AdtDef, 30 FnSignature, AdtDef,ConstSignature,
31 HirDatabase, 31 HirDatabase,
32 DefWithBody,
32 ImplItem, 33 ImplItem,
33 type_ref::{TypeRef, Mutability}, 34 type_ref::{TypeRef, Mutability},
34 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, 35 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
@@ -43,14 +44,17 @@ use crate::{
43use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; 44use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor};
44 45
45/// The entry point of type inference. 46/// The entry point of type inference.
46pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 47pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
47 db.check_canceled(); 48 db.check_canceled();
48 let body = func.body(db); 49 let body = def.body(db);
49 let resolver = func.resolver(db); 50 let resolver = def.resolver(db);
50 let mut ctx = InferenceContext::new(db, body, resolver); 51 let mut ctx = InferenceContext::new(db, body, resolver);
51 52
52 let signature = func.signature(db); 53 match def {
53 ctx.collect_fn_signature(&signature); 54 DefWithBody::Const(ref c) => ctx.collect_const_signature(&c.signature(db)),
55 DefWithBody::Function(ref f) => ctx.collect_fn_signature(&f.signature(db)),
56 DefWithBody::Static(ref s) => ctx.collect_const_signature(&s.signature(db)),
57 }
54 58
55 ctx.infer_body(); 59 ctx.infer_body();
56 60
@@ -1142,6 +1146,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1142 ty 1146 ty
1143 } 1147 }
1144 1148
1149 fn collect_const_signature(&mut self, signature: &ConstSignature) {
1150 self.return_ty = self.make_ty(signature.type_ref());
1151 }
1152
1145 fn collect_fn_signature(&mut self, signature: &FnSignature) { 1153 fn collect_fn_signature(&mut self, signature: &FnSignature) {
1146 let body = Arc::clone(&self.body); // avoid borrow checker problem 1154 let body = Arc::clone(&self.body); // avoid borrow checker problem
1147 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1155 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 655f3c522..1e84e2d06 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -11,6 +11,8 @@ use crate::{
11 source_binder, 11 source_binder,
12 mock::MockDatabase, 12 mock::MockDatabase,
13 ty::display::HirDisplay, 13 ty::display::HirDisplay,
14 ty::InferenceResult,
15 expr::BodySourceMap
14}; 16};
15 17
16// These tests compare the inference results for all expressions in a file 18// These tests compare the inference results for all expressions in a file
@@ -1267,6 +1269,9 @@ fn test() {
1267} 1269}
1268"#), 1270"#),
1269 @r###" 1271 @r###"
1272[52; 53) '1': u32
1273[103; 104) '2': u32
1274[211; 212) '5': u32
1270[227; 305) '{ ...:ID; }': () 1275[227; 305) '{ ...:ID; }': ()
1271[237; 238) 'x': u32 1276[237; 238) 'x': u32
1272[241; 252) 'Struct::FOO': u32 1277[241; 252) 'Struct::FOO': u32
@@ -1855,6 +1860,9 @@ fn test() {
1855} 1860}
1856"#), 1861"#),
1857 @r###" 1862 @r###"
1863[49; 50) '0': u32
1864[80; 83) '101': u32
1865[126; 128) '99': u32
1858[95; 213) '{ ...NST; }': () 1866[95; 213) '{ ...NST; }': ()
1859[138; 139) 'x': {unknown} 1867[138; 139) 'x': {unknown}
1860[142; 153) 'LOCAL_CONST': {unknown} 1868[142; 153) 'LOCAL_CONST': {unknown}
@@ -1881,6 +1889,10 @@ fn test() {
1881} 1889}
1882"#), 1890"#),
1883 @r###" 1891 @r###"
1892[29; 32) '101': u32
1893[70; 73) '101': u32
1894[118; 120) '99': u32
1895[161; 163) '99': u32
1884[85; 280) '{ ...MUT; }': () 1896[85; 280) '{ ...MUT; }': ()
1885[173; 174) 'x': {unknown} 1897[173; 174) 'x': {unknown}
1886[177; 189) 'LOCAL_STATIC': {unknown} 1898[177; 189) 'LOCAL_STATIC': {unknown}
@@ -2212,6 +2224,24 @@ fn test<T: Iterable<Item=u32>>() {
2212 ); 2224 );
2213} 2225}
2214 2226
2227#[test]
2228fn infer_const_body() {
2229 assert_snapshot_matches!(
2230 infer(r#"
2231const A: u32 = 1 + 1;
2232static B: u64 = { let x = 1; x };
2233"#),
2234 @r###"
2235[16; 17) '1': u32
2236[16; 21) '1 + 1': u32
2237[20; 21) '1': u32
2238[39; 55) '{ let ...1; x }': u64
2239[45; 46) 'x': u64
2240[49; 50) '1': u64
2241[52; 53) 'x': u64"###
2242 );
2243}
2244
2215fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 2245fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
2216 let func = source_binder::function_from_position(db, pos).unwrap(); 2246 let func = source_binder::function_from_position(db, pos).unwrap();
2217 let body_source_map = func.body_source_map(db); 2247 let body_source_map = func.body_source_map(db);
@@ -2228,11 +2258,11 @@ fn infer(content: &str) -> String {
2228 let source_file = db.parse(file_id); 2258 let source_file = db.parse(file_id);
2229 let mut acc = String::new(); 2259 let mut acc = String::new();
2230 acc.push_str("\n"); 2260 acc.push_str("\n");
2231 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) { 2261
2232 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); 2262 let mut infer_def = |inference_result: Arc<InferenceResult>,
2233 let inference_result = func.infer(&db); 2263 body_source_map: Arc<BodySourceMap>| {
2234 let body_source_map = func.body_source_map(&db);
2235 let mut types = Vec::new(); 2264 let mut types = Vec::new();
2265
2236 for (pat, ty) in inference_result.type_of_pat.iter() { 2266 for (pat, ty) in inference_result.type_of_pat.iter() {
2237 let syntax_ptr = match body_source_map.pat_syntax(pat) { 2267 let syntax_ptr = match body_source_map.pat_syntax(pat) {
2238 Some(sp) => sp, 2268 Some(sp) => sp,
@@ -2240,6 +2270,7 @@ fn infer(content: &str) -> String {
2240 }; 2270 };
2241 types.push((syntax_ptr, ty)); 2271 types.push((syntax_ptr, ty));
2242 } 2272 }
2273
2243 for (expr, ty) in inference_result.type_of_expr.iter() { 2274 for (expr, ty) in inference_result.type_of_expr.iter() {
2244 let syntax_ptr = match body_source_map.expr_syntax(expr) { 2275 let syntax_ptr = match body_source_map.expr_syntax(expr) {
2245 Some(sp) => sp, 2276 Some(sp) => sp,
@@ -2260,7 +2291,29 @@ fn infer(content: &str) -> String {
2260 ) 2291 )
2261 .unwrap(); 2292 .unwrap();
2262 } 2293 }
2294 };
2295
2296 for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) {
2297 let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap();
2298 let inference_result = konst.infer(&db);
2299 let body_source_map = konst.body_source_map(&db);
2300 infer_def(inference_result, body_source_map)
2263 } 2301 }
2302
2303 for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) {
2304 let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap();
2305 let inference_result = static_.infer(&db);
2306 let body_source_map = static_.body_source_map(&db);
2307 infer_def(inference_result, body_source_map)
2308 }
2309
2310 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) {
2311 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
2312 let inference_result = func.infer(&db);
2313 let body_source_map = func.body_source_map(&db);
2314 infer_def(inference_result, body_source_map)
2315 }
2316
2264 acc.truncate(acc.trim_end().len()); 2317 acc.truncate(acc.trim_end().len());
2265 acc 2318 acc
2266} 2319}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 31b4e73fb..84f39cda1 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -629,7 +629,11 @@ impl ast::TypeParamsOwner for ConstDef {}
629impl ast::AttrsOwner for ConstDef {} 629impl ast::AttrsOwner for ConstDef {}
630impl ast::DocCommentsOwner for ConstDef {} 630impl ast::DocCommentsOwner for ConstDef {}
631impl ast::TypeAscriptionOwner for ConstDef {} 631impl ast::TypeAscriptionOwner for ConstDef {}
632impl ConstDef {} 632impl ConstDef {
633 pub fn body(&self) -> Option<&Expr> {
634 super::child_opt(self)
635 }
636}
633 637
634// ContinueExpr 638// ContinueExpr
635#[derive(Debug, PartialEq, Eq, Hash)] 639#[derive(Debug, PartialEq, Eq, Hash)]
@@ -657,7 +661,6 @@ impl ToOwned for ContinueExpr {
657} 661}
658 662
659 663
660
661impl ContinueExpr {} 664impl ContinueExpr {}
662 665
663// DynTraitType 666// DynTraitType
@@ -3808,7 +3811,11 @@ impl ast::TypeParamsOwner for StaticDef {}
3808impl ast::AttrsOwner for StaticDef {} 3811impl ast::AttrsOwner for StaticDef {}
3809impl ast::DocCommentsOwner for StaticDef {} 3812impl ast::DocCommentsOwner for StaticDef {}
3810impl ast::TypeAscriptionOwner for StaticDef {} 3813impl ast::TypeAscriptionOwner for StaticDef {}
3811impl StaticDef {} 3814impl StaticDef {
3815 pub fn body(&self) -> Option<&Expr> {
3816 super::child_opt(self)
3817 }
3818}
3812 3819
3813// Stmt 3820// Stmt
3814#[derive(Debug, PartialEq, Eq, Hash)] 3821#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 19e50c9b8..a21c3917d 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -313,7 +313,7 @@ Grammar(
313 "DocCommentsOwner", 313 "DocCommentsOwner",
314 "TypeAscriptionOwner", 314 "TypeAscriptionOwner",
315 ], 315 ],
316 options: ["body","Block"], 316 options: [ ["body","Expr"]],
317 ), 317 ),
318 "StaticDef": ( 318 "StaticDef": (
319 traits: [ 319 traits: [
@@ -324,7 +324,7 @@ Grammar(
324 "DocCommentsOwner", 324 "DocCommentsOwner",
325 "TypeAscriptionOwner", 325 "TypeAscriptionOwner",
326 ], 326 ],
327 options: ["body","Block"], 327 options: [ ["body","Expr"]],
328 ), 328 ),
329 "TypeAliasDef": ( 329 "TypeAliasDef": (
330 traits: [ 330 traits: [