aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/adt.rs28
-rw-r--r--crates/ra_hir/src/code_model_api.rs73
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs8
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs4
-rw-r--r--crates/ra_hir/src/db.rs9
-rw-r--r--crates/ra_hir/src/expr.rs84
-rw-r--r--crates/ra_hir/src/expr/scope.rs19
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir/src/nameres.rs7
-rw-r--r--crates/ra_hir/src/nameres/raw.rs73
-rw-r--r--crates/ra_hir/src/path.rs13
-rw-r--r--crates/ra_hir/src/source_binder.rs52
-rw-r--r--crates/ra_hir/src/ty/infer.rs20
-rw-r--r--crates/ra_hir/src/ty/tests.rs75
14 files changed, 330 insertions, 138 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 78ea8976b..e027eedd9 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
6use ra_arena::{RawId, Arena, impl_arena_id}; 6use ra_arena::{RawId, Arena, impl_arena_id};
7use ra_syntax::{ 7use ra_syntax::{
8 TreeArc, 8 TreeArc,
9 ast::{self, NameOwner, StructFlavor, TypeAscriptionOwner} 9 ast::{self, NameOwner, StructKind, TypeAscriptionOwner}
10}; 10};
11 11
12use crate::{ 12use crate::{
@@ -47,7 +47,7 @@ pub struct StructData {
47impl StructData { 47impl StructData {
48 fn new(struct_def: &ast::StructDef) -> StructData { 48 fn new(struct_def: &ast::StructDef) -> StructData {
49 let name = struct_def.name().map(|n| n.as_name()); 49 let name = struct_def.name().map(|n| n.as_name());
50 let variant_data = VariantData::new(struct_def.flavor()); 50 let variant_data = VariantData::new(struct_def.kind());
51 let variant_data = Arc::new(variant_data); 51 let variant_data = Arc::new(variant_data);
52 StructData { name, variant_data } 52 StructData { name, variant_data }
53 } 53 }
@@ -94,7 +94,7 @@ impl EnumData {
94 let variants = variants(&*enum_def) 94 let variants = variants(&*enum_def)
95 .map(|var| EnumVariantData { 95 .map(|var| EnumVariantData {
96 name: var.name().map(|it| it.as_name()), 96 name: var.name().map(|it| it.as_name()),
97 variant_data: Arc::new(VariantData::new(var.flavor())), 97 variant_data: Arc::new(VariantData::new(var.kind())),
98 }) 98 })
99 .collect(); 99 .collect();
100 Arc::new(EnumData { name, variants }) 100 Arc::new(EnumData { name, variants })
@@ -143,9 +143,9 @@ impl VariantData {
143} 143}
144 144
145impl VariantData { 145impl VariantData {
146 fn new(flavor: StructFlavor) -> Self { 146 fn new(flavor: StructKind) -> Self {
147 let inner = match flavor { 147 let inner = match flavor {
148 ast::StructFlavor::Tuple(fl) => { 148 ast::StructKind::Tuple(fl) => {
149 let fields = fl 149 let fields = fl
150 .fields() 150 .fields()
151 .enumerate() 151 .enumerate()
@@ -156,7 +156,7 @@ impl VariantData {
156 .collect(); 156 .collect();
157 VariantDataInner::Tuple(fields) 157 VariantDataInner::Tuple(fields)
158 } 158 }
159 ast::StructFlavor::Named(fl) => { 159 ast::StructKind::Named(fl) => {
160 let fields = fl 160 let fields = fl
161 .fields() 161 .fields()
162 .map(|fd| StructFieldData { 162 .map(|fd| StructFieldData {
@@ -166,7 +166,7 @@ impl VariantData {
166 .collect(); 166 .collect();
167 VariantDataInner::Struct(fields) 167 VariantDataInner::Struct(fields)
168 } 168 }
169 ast::StructFlavor::Unit => VariantDataInner::Unit, 169 ast::StructKind::Unit => VariantDataInner::Unit,
170 }; 170 };
171 VariantData(inner) 171 VariantData(inner)
172 } 172 }
@@ -200,27 +200,27 @@ impl StructField {
200 let fields = var_data.fields().unwrap(); 200 let fields = var_data.fields().unwrap();
201 let ss; 201 let ss;
202 let es; 202 let es;
203 let (file_id, struct_flavor) = match self.parent { 203 let (file_id, struct_kind) = match self.parent {
204 VariantDef::Struct(s) => { 204 VariantDef::Struct(s) => {
205 let (file_id, source) = s.source(db); 205 let (file_id, source) = s.source(db);
206 ss = source; 206 ss = source;
207 (file_id, ss.flavor()) 207 (file_id, ss.kind())
208 } 208 }
209 VariantDef::EnumVariant(e) => { 209 VariantDef::EnumVariant(e) => {
210 let (file_id, source) = e.source(db); 210 let (file_id, source) = e.source(db);
211 es = source; 211 es = source;
212 (file_id, es.flavor()) 212 (file_id, es.kind())
213 } 213 }
214 }; 214 };
215 215
216 let field_sources = match struct_flavor { 216 let field_sources = match struct_kind {
217 ast::StructFlavor::Tuple(fl) => { 217 ast::StructKind::Tuple(fl) => {
218 fl.fields().map(|it| FieldSource::Pos(it.to_owned())).collect() 218 fl.fields().map(|it| FieldSource::Pos(it.to_owned())).collect()
219 } 219 }
220 ast::StructFlavor::Named(fl) => { 220 ast::StructKind::Named(fl) => {
221 fl.fields().map(|it| FieldSource::Named(it.to_owned())).collect() 221 fl.fields().map(|it| FieldSource::Named(it.to_owned())).collect()
222 } 222 }
223 ast::StructFlavor::Unit => Vec::new(), 223 ast::StructKind::Unit => Vec::new(),
224 }; 224 };
225 let field = field_sources 225 let field = field_sources
226 .into_iter() 226 .into_iter()
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 624c25c4d..9e6170440 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -4,7 +4,7 @@ use ra_db::{CrateId, SourceRootId, Edition};
4use ra_syntax::{ast::self, TreeArc}; 4use ra_syntax::{ast::self, TreeArc};
5 5
6use crate::{ 6use crate::{
7 Name, ScopesWithSourceMap, Ty, HirFileId, 7 Name, ScopesWithSourceMap, Ty, HirFileId, ImportSource,
8 HirDatabase, DefDatabase, 8 HirDatabase, DefDatabase,
9 type_ref::TypeRef, 9 type_ref::TypeRef,
10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, 10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
@@ -117,11 +117,7 @@ impl Module {
117 } 117 }
118 118
119 /// Returns the syntax of the last path segment corresponding to this import 119 /// Returns the syntax of the last path segment corresponding to this import
120 pub fn import_source( 120 pub fn import_source(&self, db: &impl HirDatabase, import: ImportId) -> ImportSource {
121 &self,
122 db: &impl HirDatabase,
123 import: ImportId,
124 ) -> TreeArc<ast::PathSegment> {
125 self.import_source_impl(db, import) 121 self.import_source_impl(db, import)
126 } 122 }
127 123
@@ -433,6 +429,45 @@ impl Docs for EnumVariant {
433 } 429 }
434} 430}
435 431
432/// The defs which have a body.
433#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
434pub enum DefWithBody {
435 Function(Function),
436 Const(Const),
437 Static(Static),
438}
439
440impl_froms!(DefWithBody: Function, Const, Static);
441
442impl DefWithBody {
443 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
444 db.infer(*self)
445 }
446
447 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
448 db.body_with_source_map(*self).1
449 }
450
451 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
452 db.body_hir(*self)
453 }
454
455 /// Builds a resolver for code inside this item.
456 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
457 match *self {
458 DefWithBody::Const(ref c) => c.resolver(db),
459 DefWithBody::Function(ref f) => f.resolver(db),
460 DefWithBody::Static(ref s) => s.resolver(db),
461 }
462 }
463
464 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
465 let scopes = db.expr_scopes(*self);
466 let source_map = db.body_with_source_map(*self).1;
467 ScopesWithSourceMap { scopes, source_map }
468 }
469}
470
436#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 471#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
437pub struct Function { 472pub struct Function {
438 pub(crate) id: FunctionId, 473 pub(crate) id: FunctionId,
@@ -483,11 +518,11 @@ impl Function {
483 } 518 }
484 519
485 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 520 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
486 db.body_with_source_map(*self).1 521 db.body_with_source_map((*self).into()).1
487 } 522 }
488 523
489 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 524 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
490 db.body_hir(*self) 525 db.body_hir((*self).into())
491 } 526 }
492 527
493 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 528 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
@@ -495,8 +530,8 @@ impl Function {
495 } 530 }
496 531
497 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap { 532 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
498 let scopes = db.expr_scopes(*self); 533 let scopes = db.expr_scopes((*self).into());
499 let source_map = db.body_with_source_map(*self).1; 534 let source_map = db.body_with_source_map((*self).into()).1;
500 ScopesWithSourceMap { scopes, source_map } 535 ScopesWithSourceMap { scopes, source_map }
501 } 536 }
502 537
@@ -505,7 +540,7 @@ impl Function {
505 } 540 }
506 541
507 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 542 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
508 db.infer(*self) 543 db.infer((*self).into())
509 } 544 }
510 545
511 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { 546 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
@@ -561,6 +596,14 @@ impl Const {
561 db.const_signature(*self) 596 db.const_signature(*self)
562 } 597 }
563 598
599 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
600 db.infer((*self).into())
601 }
602
603 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
604 db.body_with_source_map((*self).into()).1
605 }
606
564 /// The containing impl block, if this is a method. 607 /// The containing impl block, if this is a method.
565 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 608 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
566 let module_impls = db.impls_in_module(self.module(db)); 609 let module_impls = db.impls_in_module(self.module(db));
@@ -625,6 +668,14 @@ impl Static {
625 // take the outer scope... 668 // take the outer scope...
626 self.module(db).resolver(db) 669 self.module(db).resolver(db)
627 } 670 }
671
672 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
673 db.infer((*self).into())
674 }
675
676 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
677 db.body_with_source_map((*self).into()).1
678 }
628} 679}
629 680
630impl Docs for Static { 681impl Docs for Static {
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index 334cb302b..f8bd0f784 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -20,12 +20,12 @@ impl FnSignature {
20 TypeRef::from_ast(type_ref) 20 TypeRef::from_ast(type_ref)
21 } else { 21 } else {
22 let self_type = TypeRef::Path(Name::self_type().into()); 22 let self_type = TypeRef::Path(Name::self_type().into());
23 match self_param.flavor() { 23 match self_param.kind() {
24 ast::SelfParamFlavor::Owned => self_type, 24 ast::SelfParamKind::Owned => self_type,
25 ast::SelfParamFlavor::Ref => { 25 ast::SelfParamKind::Ref => {
26 TypeRef::Reference(Box::new(self_type), Mutability::Shared) 26 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
27 } 27 }
28 ast::SelfParamFlavor::MutRef => { 28 ast::SelfParamKind::MutRef => {
29 TypeRef::Reference(Box::new(self_type), Mutability::Mut) 29 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
30 } 30 }
31 } 31 }
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 0edb8ade5..88dee3a69 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -5,7 +5,7 @@ use crate::{
5 Module, ModuleSource, Name, AstId, 5 Module, ModuleSource, Name, AstId,
6 nameres::{CrateModuleId, ImportId}, 6 nameres::{CrateModuleId, ImportId},
7 HirDatabase, DefDatabase, 7 HirDatabase, DefDatabase,
8 HirFileId, 8 HirFileId, ImportSource,
9}; 9};
10 10
11impl ModuleSource { 11impl ModuleSource {
@@ -72,7 +72,7 @@ impl Module {
72 &self, 72 &self,
73 db: &impl HirDatabase, 73 db: &impl HirDatabase,
74 import: ImportId, 74 import: ImportId,
75 ) -> TreeArc<ast::PathSegment> { 75 ) -> ImportSource {
76 let (file_id, source) = self.definition_source(db); 76 let (file_id, source) = self.definition_source(db);
77 let (_, source_map) = db.raw_items_with_source_map(file_id); 77 let (_, source_map) = db.raw_items_with_source_map(file_id);
78 source_map.get(&source, import) 78 source_map.get(&source, import)
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 147005848..be8a8c98b 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -8,6 +8,7 @@ use crate::{
8 Function, FnSignature, ExprScopes, TypeAlias, 8 Function, FnSignature, ExprScopes, TypeAlias,
9 Struct, Enum, StructField, 9 Struct, Enum, StructField,
10 Const, ConstSignature, Static, 10 Const, ConstSignature, Static,
11 DefWithBody,
11 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap}, 12 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap},
12 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig}, 13 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig},
13 adt::{StructData, EnumData}, 14 adt::{StructData, EnumData},
@@ -83,10 +84,10 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
83#[salsa::query_group(HirDatabaseStorage)] 84#[salsa::query_group(HirDatabaseStorage)]
84pub trait HirDatabase: DefDatabase { 85pub trait HirDatabase: DefDatabase {
85 #[salsa::invoke(ExprScopes::expr_scopes_query)] 86 #[salsa::invoke(ExprScopes::expr_scopes_query)]
86 fn expr_scopes(&self, func: Function) -> Arc<ExprScopes>; 87 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
87 88
88 #[salsa::invoke(crate::ty::infer)] 89 #[salsa::invoke(crate::ty::infer)]
89 fn infer(&self, func: Function) -> Arc<InferenceResult>; 90 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
90 91
91 #[salsa::invoke(crate::ty::type_for_def)] 92 #[salsa::invoke(crate::ty::type_for_def)]
92 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; 93 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty;
@@ -100,11 +101,11 @@ pub trait HirDatabase: DefDatabase {
100 #[salsa::invoke(crate::expr::body_with_source_map_query)] 101 #[salsa::invoke(crate::expr::body_with_source_map_query)]
101 fn body_with_source_map( 102 fn body_with_source_map(
102 &self, 103 &self,
103 func: Function, 104 def: DefWithBody,
104 ) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>); 105 ) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>);
105 106
106 #[salsa::invoke(crate::expr::body_hir_query)] 107 #[salsa::invoke(crate::expr::body_hir_query)]
107 fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>; 108 fn body_hir(&self, def: DefWithBody) -> Arc<crate::expr::Body>;
108 109
109 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 110 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
110 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 111 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index a85422955..b2a237ece 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -6,11 +6,11 @@ use rustc_hash::FxHashMap;
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_syntax::{ 7use ra_syntax::{
8 SyntaxNodePtr, AstPtr, AstNode, 8 SyntaxNodePtr, AstPtr, AstNode,
9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor, TypeAscriptionOwner} 9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind, TypeAscriptionOwner}
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Function, Resolver, 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,9 +27,8 @@ 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 31 owner: DefWithBody,
32 owner: Function,
33 exprs: Arena<ExprId, Expr>, 32 exprs: Arena<ExprId, Expr>,
34 pats: Arena<PatId, Pat>, 33 pats: Arena<PatId, Pat>,
35 /// The patterns for the function's parameters. While the parameter types are 34 /// The patterns for the function's parameters. While the parameter types are
@@ -66,7 +65,7 @@ impl Body {
66 self.body_expr 65 self.body_expr
67 } 66 }
68 67
69 pub fn owner(&self) -> Function { 68 pub fn owner(&self) -> DefWithBody {
70 self.owner 69 self.owner
71 } 70 }
72 71
@@ -463,8 +462,8 @@ impl Pat {
463 462
464// Queries 463// Queries
465 464
466struct ExprCollector { 465pub(crate) struct ExprCollector {
467 owner: Function, 466 owner: DefWithBody,
468 exprs: Arena<ExprId, Expr>, 467 exprs: Arena<ExprId, Expr>,
469 pats: Arena<PatId, Pat>, 468 pats: Arena<PatId, Pat>,
470 source_map: BodySourceMap, 469 source_map: BodySourceMap,
@@ -473,7 +472,7 @@ struct ExprCollector {
473} 472}
474 473
475impl ExprCollector { 474impl ExprCollector {
476 fn new(owner: Function) -> Self { 475 fn new(owner: DefWithBody) -> Self {
477 ExprCollector { 476 ExprCollector {
478 owner, 477 owner,
479 exprs: Arena::default(), 478 exprs: Arena::default(),
@@ -516,8 +515,8 @@ impl ExprCollector {
516 let else_branch = e 515 let else_branch = e
517 .else_branch() 516 .else_branch()
518 .map(|b| match b { 517 .map(|b| match b {
519 ast::ElseBranchFlavor::Block(it) => self.collect_block(it), 518 ast::ElseBranch::Block(it) => self.collect_block(it),
520 ast::ElseBranchFlavor::IfExpr(elif) => { 519 ast::ElseBranch::IfExpr(elif) => {
521 let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap(); 520 let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap();
522 self.collect_expr(expr) 521 self.collect_expr(expr)
523 } 522 }
@@ -533,8 +532,8 @@ impl ExprCollector {
533 let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); 532 let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr()));
534 let then_branch = self.collect_block_opt(e.then_branch()); 533 let then_branch = self.collect_block_opt(e.then_branch());
535 let else_branch = e.else_branch().map(|b| match b { 534 let else_branch = e.else_branch().map(|b| match b {
536 ast::ElseBranchFlavor::Block(it) => self.collect_block(it), 535 ast::ElseBranch::Block(it) => self.collect_block(it),
537 ast::ElseBranchFlavor::IfExpr(elif) => { 536 ast::ElseBranch::IfExpr(elif) => {
538 let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap(); 537 let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap();
539 self.collect_expr(expr) 538 self.collect_expr(expr)
540 } 539 }
@@ -726,14 +725,8 @@ impl ExprCollector {
726 self.alloc_expr(Expr::Array { exprs }, syntax_ptr) 725 self.alloc_expr(Expr::Array { exprs }, syntax_ptr)
727 } 726 }
728 ast::ExprKind::Literal(e) => { 727 ast::ExprKind::Literal(e) => {
729 let child = if let Some(child) = e.literal_expr() { 728 let lit = match e.kind() {
730 child 729 LiteralKind::IntNumber { suffix } => {
731 } else {
732 return self.alloc_expr(Expr::Missing, syntax_ptr);
733 };
734
735 let lit = match child.flavor() {
736 LiteralFlavor::IntNumber { suffix } => {
737 let known_name = suffix 730 let known_name = suffix
738 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known)); 731 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known));
739 732
@@ -742,7 +735,7 @@ impl ExprCollector {
742 known_name.unwrap_or(UncertainIntTy::Unknown), 735 known_name.unwrap_or(UncertainIntTy::Unknown),
743 ) 736 )
744 } 737 }
745 LiteralFlavor::FloatNumber { suffix } => { 738 LiteralKind::FloatNumber { suffix } => {
746 let known_name = suffix 739 let known_name = suffix
747 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known)); 740 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known));
748 741
@@ -751,13 +744,13 @@ impl ExprCollector {
751 known_name.unwrap_or(UncertainFloatTy::Unknown), 744 known_name.unwrap_or(UncertainFloatTy::Unknown),
752 ) 745 )
753 } 746 }
754 LiteralFlavor::ByteString => Literal::ByteString(Default::default()), 747 LiteralKind::ByteString => Literal::ByteString(Default::default()),
755 LiteralFlavor::String => Literal::String(Default::default()), 748 LiteralKind::String => Literal::String(Default::default()),
756 LiteralFlavor::Byte => { 749 LiteralKind::Byte => {
757 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8())) 750 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8()))
758 } 751 }
759 LiteralFlavor::Bool => Literal::Bool(Default::default()), 752 LiteralKind::Bool => Literal::Bool(Default::default()),
760 LiteralFlavor::Char => Literal::Char(Default::default()), 753 LiteralKind::Char => Literal::Char(Default::default()),
761 }; 754 };
762 self.alloc_expr(Expr::Literal(lit), syntax_ptr) 755 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
763 } 756 }
@@ -766,6 +759,7 @@ impl ExprCollector {
766 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 759 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
767 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 760 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
768 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 761 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
762 ast::ExprKind::MacroCall(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
769 } 763 }
770 } 764 }
771 765
@@ -871,12 +865,20 @@ impl ExprCollector {
871 } 865 }
872 } 866 }
873 867
868 fn collect_const_body(&mut self, node: &ast::ConstDef) {
869 let body = self.collect_expr_opt(node.body());
870 self.body_expr = Some(body);
871 }
872
873 fn collect_static_body(&mut self, node: &ast::StaticDef) {
874 let body = self.collect_expr_opt(node.body());
875 self.body_expr = Some(body);
876 }
877
874 fn collect_fn_body(&mut self, node: &ast::FnDef) { 878 fn collect_fn_body(&mut self, node: &ast::FnDef) {
875 if let Some(param_list) = node.param_list() { 879 if let Some(param_list) = node.param_list() {
876 if let Some(self_param) = param_list.self_param() { 880 if let Some(self_param) = param_list.self_param() {
877 let self_param = SyntaxNodePtr::new( 881 let self_param = SyntaxNodePtr::new(self_param.syntax());
878 self_param.self_kw().expect("self param without self keyword").syntax(),
879 );
880 let param_pat = self.alloc_pat( 882 let param_pat = self.alloc_pat(
881 Pat::Bind { 883 Pat::Bind {
882 name: Name::self_param(), 884 name: Name::self_param(),
@@ -917,24 +919,20 @@ impl ExprCollector {
917 919
918pub(crate) fn body_with_source_map_query( 920pub(crate) fn body_with_source_map_query(
919 db: &impl HirDatabase, 921 db: &impl HirDatabase,
920 func: Function, 922 def: DefWithBody,
921) -> (Arc<Body>, Arc<BodySourceMap>) { 923) -> (Arc<Body>, Arc<BodySourceMap>) {
922 let mut collector = ExprCollector::new(func); 924 let mut collector = ExprCollector::new(def);
923 925
924 // FIXME: consts, etc. 926 match def {
925 collector.collect_fn_body(&func.source(db).1); 927 DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1),
928 DefWithBody::Function(ref f) => collector.collect_fn_body(&f.source(db).1),
929 DefWithBody::Static(ref s) => collector.collect_static_body(&s.source(db).1),
930 }
926 931
927 let (body, source_map) = collector.finish(); 932 let (body, source_map) = collector.finish();
928 (Arc::new(body), Arc::new(source_map)) 933 (Arc::new(body), Arc::new(source_map))
929} 934}
930 935
931pub(crate) fn body_hir_query(db: &impl HirDatabase, func: Function) -> Arc<Body> { 936pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> {
932 db.body_with_source_map(func).0 937 db.body_with_source_map(def).0
933}
934
935#[cfg(test)]
936fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
937 let mut collector = ExprCollector::new(function);
938 collector.collect_fn_body(node);
939 collector.finish()
940} 938}
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index ed005c9f7..48283907b 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, 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};
@@ -40,8 +40,8 @@ pub struct ScopeData {
40 40
41impl ExprScopes { 41impl ExprScopes {
42 // FIXME: This should take something more general than Function 42 // FIXME: This should take something more general than Function
43 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, function: Function) -> Arc<ExprScopes> { 43 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<ExprScopes> {
44 let body = db.body_hir(function); 44 let body = db.body_hir(def);
45 let res = ExprScopes::new(body); 45 let res = ExprScopes::new(body);
46 Arc::new(res) 46 Arc::new(res)
47 } 47 }
@@ -297,8 +297,9 @@ 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::{ExprCollector};
302 303
303 use super::*; 304 use super::*;
304 305
@@ -316,7 +317,7 @@ mod tests {
316 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 317 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
317 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 318 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
318 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) }; 319 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
319 let (body, source_map) = expr::collect_fn_body_syntax(irrelevant_function, fn_def); 320 let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def);
320 let scopes = ExprScopes::new(Arc::new(body)); 321 let scopes = ExprScopes::new(Arc::new(body));
321 let scopes = 322 let scopes =
322 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; 323 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };
@@ -405,6 +406,12 @@ mod tests {
405 ); 406 );
406 } 407 }
407 408
409 fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
410 let mut collector = ExprCollector::new(DefWithBody::Function(function));
411 collector.collect_fn_body(node);
412 collector.finish()
413 }
414
408 fn do_check_local_name(code: &str, expected_offset: u32) { 415 fn do_check_local_name(code: &str, expected_offset: u32) {
409 let (off, code) = extract_offset(code); 416 let (off, code) = extract_offset(code);
410 let file = SourceFile::parse(&code); 417 let file = SourceFile::parse(&code);
@@ -415,7 +422,7 @@ mod tests {
415 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 422 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
416 423
417 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) }; 424 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) };
418 let (body, source_map) = expr::collect_fn_body_syntax(irrelevant_function, fn_def); 425 let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def);
419 let scopes = ExprScopes::new(Arc::new(body)); 426 let scopes = ExprScopes::new(Arc::new(body));
420 let scopes = 427 let scopes =
421 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; 428 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 7c603bbd3..c19450f39 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -56,7 +56,7 @@ pub use self::{
56 name::Name, 56 name::Name,
57 source_id::{AstIdMap, ErasedFileAstId}, 57 source_id::{AstIdMap, ErasedFileAstId},
58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner}, 58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
59 nameres::{PerNs, Namespace}, 59 nameres::{PerNs, Namespace, ImportId, ImportSource},
60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, 60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
61 impl_block::{ImplBlock, ImplItem}, 61 impl_block::{ImplBlock, ImplItem},
62 docs::{Docs, Documentation}, 62 docs::{Docs, Documentation},
@@ -67,6 +67,7 @@ pub use self::{
67 67
68pub use self::code_model_api::{ 68pub use self::code_model_api::{
69 Crate, CrateDependency, 69 Crate, CrateDependency,
70 DefWithBody,
70 Module, ModuleDef, ModuleSource, 71 Module, ModuleDef, ModuleSource,
71 Struct, Enum, EnumVariant, 72 Struct, Enum, EnumVariant,
72 Function, FnSignature, 73 Function, FnSignature,
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 8adc6d368..4ae04514a 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -71,9 +71,12 @@ use crate::{
71 AstId, 71 AstId,
72}; 72};
73 73
74pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap}; 74pub(crate) use self::raw::{RawItems, ImportSourceMap};
75 75
76pub use self::per_ns::{PerNs, Namespace}; 76pub use self::{
77 per_ns::{PerNs, Namespace},
78 raw::{ImportId, ImportSource},
79};
77 80
78/// Contans all top-level defs from a macro-expanded crate 81/// Contans all top-level defs from a macro-expanded crate
79#[derive(Debug, PartialEq, Eq)] 82#[derive(Debug, PartialEq, Eq)]
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 0936229ac..b7416ede6 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -31,21 +31,43 @@ pub struct RawItems {
31 31
32#[derive(Debug, Default, PartialEq, Eq)] 32#[derive(Debug, Default, PartialEq, Eq)]
33pub struct ImportSourceMap { 33pub struct ImportSourceMap {
34 map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, 34 map: ArenaMap<ImportId, ImportSourcePtr>,
35}
36
37#[derive(Debug, PartialEq, Eq, Clone, Copy)]
38enum ImportSourcePtr {
39 UseTree(AstPtr<ast::UseTree>),
40 ExternCrate(AstPtr<ast::ExternCrateItem>),
41}
42
43impl ImportSourcePtr {
44 fn to_node(self, file: &SourceFile) -> ImportSource {
45 match self {
46 ImportSourcePtr::UseTree(ptr) => ImportSource::UseTree(ptr.to_node(file).to_owned()),
47 ImportSourcePtr::ExternCrate(ptr) => {
48 ImportSource::ExternCrate(ptr.to_node(file).to_owned())
49 }
50 }
51 }
52}
53
54pub enum ImportSource {
55 UseTree(TreeArc<ast::UseTree>),
56 ExternCrate(TreeArc<ast::ExternCrateItem>),
35} 57}
36 58
37impl ImportSourceMap { 59impl ImportSourceMap {
38 fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { 60 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
39 self.map.insert(import, AstPtr::new(segment)) 61 self.map.insert(import, ptr)
40 } 62 }
41 63
42 pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { 64 pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource {
43 let file = match source { 65 let file = match source {
44 ModuleSource::SourceFile(file) => &*file, 66 ModuleSource::SourceFile(file) => &*file,
45 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), 67 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
46 }; 68 };
47 69
48 self.map[import].to_node(file).to_owned() 70 self.map[import].to_node(file)
49 } 71 }
50} 72}
51 73
@@ -256,18 +278,14 @@ impl RawItemsCollector {
256 fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) { 278 fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) {
257 let is_prelude = use_item.has_atom_attr("prelude_import"); 279 let is_prelude = use_item.has_atom_attr("prelude_import");
258 280
259 Path::expand_use_item(use_item, |path, segment, alias| { 281 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
260 let import = self.raw_items.imports.alloc(ImportData { 282 let import_data =
261 path, 283 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false };
262 alias, 284 self.push_import(
263 is_glob: segment.is_none(), 285 current_module,
264 is_prelude, 286 import_data,
265 is_extern_crate: false, 287 ImportSourcePtr::UseTree(AstPtr::new(use_tree)),
266 }); 288 );
267 if let Some(segment) = segment {
268 self.source_map.insert(import, segment)
269 }
270 self.push_item(current_module, RawItem::Import(import))
271 }) 289 })
272 } 290 }
273 291
@@ -279,14 +297,18 @@ impl RawItemsCollector {
279 if let Some(name_ref) = extern_crate.name_ref() { 297 if let Some(name_ref) = extern_crate.name_ref() {
280 let path = Path::from_name_ref(name_ref); 298 let path = Path::from_name_ref(name_ref);
281 let alias = extern_crate.alias().and_then(|a| a.name()).map(AsName::as_name); 299 let alias = extern_crate.alias().and_then(|a| a.name()).map(AsName::as_name);
282 let import = self.raw_items.imports.alloc(ImportData { 300 let import_data = ImportData {
283 path, 301 path,
284 alias, 302 alias,
285 is_glob: false, 303 is_glob: false,
286 is_prelude: false, 304 is_prelude: false,
287 is_extern_crate: true, 305 is_extern_crate: true,
288 }); 306 };
289 self.push_item(current_module, RawItem::Import(import)) 307 self.push_import(
308 current_module,
309 import_data,
310 ImportSourcePtr::ExternCrate(AstPtr::new(extern_crate)),
311 );
290 } 312 }
291 } 313 }
292 314
@@ -303,6 +325,17 @@ impl RawItemsCollector {
303 self.push_item(current_module, RawItem::Macro(m)); 325 self.push_item(current_module, RawItem::Macro(m));
304 } 326 }
305 327
328 fn push_import(
329 &mut self,
330 current_module: Option<Module>,
331 data: ImportData,
332 source: ImportSourcePtr,
333 ) {
334 let import = self.raw_items.imports.alloc(data);
335 self.source_map.insert(import, source);
336 self.push_item(current_module, RawItem::Import(import))
337 }
338
306 fn push_item(&mut self, current_module: Option<Module>, item: RawItem) { 339 fn push_item(&mut self, current_module: Option<Module>, item: RawItem) {
307 match current_module { 340 match current_module {
308 Some(module) => match &mut self.raw_items.modules[module] { 341 Some(module) => match &mut self.raw_items.modules[module] {
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 6cc8104f4..5449cddfd 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -46,7 +46,7 @@ impl Path {
46 /// Calls `cb` with all paths, represented by this use item. 46 /// Calls `cb` with all paths, represented by this use item.
47 pub fn expand_use_item<'a>( 47 pub fn expand_use_item<'a>(
48 item: &'a ast::UseItem, 48 item: &'a ast::UseItem,
49 mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), 49 mut cb: impl FnMut(Path, &'a ast::UseTree, bool, Option<Name>),
50 ) { 50 ) {
51 if let Some(tree) = item.use_tree() { 51 if let Some(tree) = item.use_tree() {
52 expand_use_tree(None, tree, &mut cb); 52 expand_use_tree(None, tree, &mut cb);
@@ -156,7 +156,7 @@ impl From<Name> for Path {
156fn expand_use_tree<'a>( 156fn expand_use_tree<'a>(
157 prefix: Option<Path>, 157 prefix: Option<Path>,
158 tree: &'a ast::UseTree, 158 tree: &'a ast::UseTree,
159 cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), 159 cb: &mut impl FnMut(Path, &'a ast::UseTree, bool, Option<Name>),
160) { 160) {
161 if let Some(use_tree_list) = tree.use_tree_list() { 161 if let Some(use_tree_list) = tree.use_tree_list() {
162 let prefix = match tree.path() { 162 let prefix = match tree.path() {
@@ -181,18 +181,15 @@ fn expand_use_tree<'a>(
181 if let Some(segment) = ast_path.segment() { 181 if let Some(segment) = ast_path.segment() {
182 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { 182 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
183 if let Some(prefix) = prefix { 183 if let Some(prefix) = prefix {
184 cb(prefix, Some(segment), alias); 184 cb(prefix, tree, false, alias);
185 return; 185 return;
186 } 186 }
187 } 187 }
188 } 188 }
189 } 189 }
190 if let Some(path) = convert_path(prefix, ast_path) { 190 if let Some(path) = convert_path(prefix, ast_path) {
191 if tree.has_star() { 191 let is_glob = tree.has_star();
192 cb(path, None, alias) 192 cb(path, tree, is_glob, alias)
193 } else if let Some(segment) = ast_path.segment() {
194 cb(path, Some(segment), alias)
195 };
196 } 193 }
197 // FIXME: report errors somewhere 194 // FIXME: report errors somewhere
198 // We get here if we do 195 // We get here if we do
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 9dae4c3d1..182ed4c91 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -9,11 +9,11 @@ use ra_db::{FileId, FilePosition};
9use ra_syntax::{ 9use ra_syntax::{
10 SyntaxNode, 10 SyntaxNode,
11 ast::{self, AstNode, NameOwner}, 11 ast::{self, AstNode, NameOwner},
12 algo::{find_node_at_offset, find_leaf_at_offset}, 12 algo::{find_node_at_offset, find_token_at_offset},
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();
@@ -155,9 +197,9 @@ pub fn trait_from_module(
155pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { 197pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver {
156 let file_id = position.file_id; 198 let file_id = position.file_id;
157 let file = db.parse(file_id); 199 let file = db.parse(file_id);
158 find_leaf_at_offset(file.syntax(), position.offset) 200 find_token_at_offset(file.syntax(), position.offset)
159 .find_map(|node| { 201 .find_map(|token| {
160 node.ancestors().find_map(|node| { 202 token.parent().ancestors().find_map(|node| {
161 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { 203 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
162 if let Some(func) = function_from_child_node(db, file_id, node) { 204 if let Some(func) = function_from_child_node(db, file_id, node) {
163 let scopes = func.scopes(db); 205 let scopes = func.scopes(db);
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..0b7c841df 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,
@@ -2251,16 +2282,36 @@ fn infer(content: &str) -> String {
2251 types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end())); 2282 types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end()));
2252 for (syntax_ptr, ty) in &types { 2283 for (syntax_ptr, ty) in &types {
2253 let node = syntax_ptr.to_node(&source_file); 2284 let node = syntax_ptr.to_node(&source_file);
2254 write!( 2285 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node) {
2255 acc, 2286 (self_param.self_kw_token().range(), "self".to_string())
2256 "{} '{}': {}\n", 2287 } else {
2257 syntax_ptr.range(), 2288 (syntax_ptr.range(), node.text().to_string().replace("\n", " "))
2258 ellipsize(node.text().to_string().replace("\n", " "), 15), 2289 };
2259 ty.display(&db) 2290 write!(acc, "{} '{}': {}\n", range, ellipsize(text, 15), ty.display(&db)).unwrap();
2260 )
2261 .unwrap();
2262 } 2291 }
2292 };
2293
2294 for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) {
2295 let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap();
2296 let inference_result = konst.infer(&db);
2297 let body_source_map = konst.body_source_map(&db);
2298 infer_def(inference_result, body_source_map)
2263 } 2299 }
2300
2301 for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) {
2302 let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap();
2303 let inference_result = static_.infer(&db);
2304 let body_source_map = static_.body_source_map(&db);
2305 infer_def(inference_result, body_source_map)
2306 }
2307
2308 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) {
2309 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
2310 let inference_result = func.infer(&db);
2311 let body_source_map = func.body_source_map(&db);
2312 infer_def(inference_result, body_source_map)
2313 }
2314
2264 acc.truncate(acc.trim_end().len()); 2315 acc.truncate(acc.trim_end().len());
2265 acc 2316 acc
2266} 2317}