diff options
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 87 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/scope.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 61 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 13 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 4 |
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)] |
438 | pub enum DefWithBody { | 438 | pub enum DefWithBody { |
439 | Func(Function), | 439 | Function(Function), |
440 | Const(Const), | 440 | Const(Const), |
441 | Static(Static), | 441 | Static(Static), |
442 | } | 442 | } |
443 | 443 | ||
444 | impl DefWithBody { | 444 | impl_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 | ||
446 | impl 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 | ||
702 | impl Docs for Static { | 685 | impl 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 | ||
12 | use crate::{ | 12 | use 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)] |
29 | pub struct Body { | 29 | pub 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 | ||
949 | pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> { | 943 | pub(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)] |
948 | use crate::{Function}; | ||
949 | #[cfg(test)] | ||
954 | fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) { | 950 | fn 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::{ | |||
10 | use ra_arena::{Arena, RawId, impl_arena_id}; | 10 | use ra_arena::{Arena, RawId, impl_arena_id}; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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 | ||
15 | use crate::{ | 15 | use 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 | ||
90 | pub 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 | |||
100 | pub 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 | |||
90 | pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { | 111 | pub 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 | ||
158 | pub 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 | |||
168 | pub 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 | |||
137 | pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { | 179 | pub 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 | ||
28 | use crate::{ | 28 | use 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::{ | |||
43 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; | 44 | use 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. |
46 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | 47 | pub 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] | ||
2228 | fn infer_const_body() { | ||
2229 | assert_snapshot_matches!( | ||
2230 | infer(r#" | ||
2231 | const A: u32 = 1 + 1; | ||
2232 | static 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 | |||
2215 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2245 | fn 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 {} | |||
629 | impl ast::AttrsOwner for ConstDef {} | 629 | impl ast::AttrsOwner for ConstDef {} |
630 | impl ast::DocCommentsOwner for ConstDef {} | 630 | impl ast::DocCommentsOwner for ConstDef {} |
631 | impl ast::TypeAscriptionOwner for ConstDef {} | 631 | impl ast::TypeAscriptionOwner for ConstDef {} |
632 | impl ConstDef {} | 632 | impl 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 | |||
661 | impl ContinueExpr {} | 664 | impl ContinueExpr {} |
662 | 665 | ||
663 | // DynTraitType | 666 | // DynTraitType |
@@ -3808,7 +3811,11 @@ impl ast::TypeParamsOwner for StaticDef {} | |||
3808 | impl ast::AttrsOwner for StaticDef {} | 3811 | impl ast::AttrsOwner for StaticDef {} |
3809 | impl ast::DocCommentsOwner for StaticDef {} | 3812 | impl ast::DocCommentsOwner for StaticDef {} |
3810 | impl ast::TypeAscriptionOwner for StaticDef {} | 3813 | impl ast::TypeAscriptionOwner for StaticDef {} |
3811 | impl StaticDef {} | 3814 | impl 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: [ |