aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model_api.rs140
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs14
-rw-r--r--crates/ra_hir/src/db.rs33
-rw-r--r--crates/ra_hir/src/either.rs28
-rw-r--r--crates/ra_hir/src/expr.rs54
-rw-r--r--crates/ra_hir/src/expr/scope.rs233
-rw-r--r--crates/ra_hir/src/generics.rs37
-rw-r--r--crates/ra_hir/src/ids.rs145
-rw-r--r--crates/ra_hir/src/impl_block.rs30
-rw-r--r--crates/ra_hir/src/lib.rs18
-rw-r--r--crates/ra_hir/src/mock.rs11
-rw-r--r--crates/ra_hir/src/nameres.rs2
-rw-r--r--crates/ra_hir/src/nameres/raw.rs33
-rw-r--r--crates/ra_hir/src/resolve.rs18
-rw-r--r--crates/ra_hir/src/source_binder.rs406
-rw-r--r--crates/ra_hir/src/traits.rs33
-rw-r--r--crates/ra_hir/src/ty.rs47
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs4
-rw-r--r--crates/ra_hir/src/ty/infer.rs243
-rw-r--r--crates/ra_hir/src/ty/lower.rs109
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs60
-rw-r--r--crates/ra_hir/src/ty/tests.rs115
-rw-r--r--crates/ra_hir/src/ty/traits.rs112
23 files changed, 1155 insertions, 770 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 9e6170440..8f1ed1086 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -4,14 +4,14 @@ 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, ImportSource, 7 Name, Ty, HirFileId, Either,
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},
11 expr::{Body, BodySourceMap}, 11 expr::{Body, BodySourceMap},
12 ty::InferenceResult, 12 ty::InferenceResult,
13 adt::{EnumVariantId, StructFieldId, VariantDef}, 13 adt::{EnumVariantId, StructFieldId, VariantDef},
14 generics::GenericParams, 14 generics::HasGenericParams,
15 docs::{Documentation, Docs, docs_from_ast}, 15 docs::{Documentation, Docs, docs_from_ast},
16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId}, 16 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId},
17 impl_block::ImplBlock, 17 impl_block::ImplBlock,
@@ -117,8 +117,14 @@ 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(&self, db: &impl HirDatabase, import: ImportId) -> ImportSource { 120 pub fn import_source(
121 self.import_source_impl(db, import) 121 &self,
122 db: &impl HirDatabase,
123 import: ImportId,
124 ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> {
125 let (file_id, source) = self.definition_source(db);
126 let (_, source_map) = db.raw_items_with_source_map(file_id);
127 source_map.get(&source, import)
122 } 128 }
123 129
124 /// Returns the crate this module is part of. 130 /// Returns the crate this module is part of.
@@ -183,12 +189,12 @@ impl Module {
183 } 189 }
184 } 190 }
185 191
186 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 192 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
187 let def_map = db.crate_def_map(self.krate); 193 let def_map = db.crate_def_map(self.krate);
188 Resolver::default().push_module_scope(def_map, self.module_id) 194 Resolver::default().push_module_scope(def_map, self.module_id)
189 } 195 }
190 196
191 pub fn declarations(self, db: &impl HirDatabase) -> Vec<ModuleDef> { 197 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
192 let def_map = db.crate_def_map(self.krate); 198 let def_map = db.crate_def_map(self.krate);
193 def_map[self.module_id] 199 def_map[self.module_id]
194 .scope 200 .scope
@@ -293,10 +299,6 @@ impl Struct {
293 .map(|(id, _)| StructField { parent: (*self).into(), id }) 299 .map(|(id, _)| StructField { parent: (*self).into(), id })
294 } 300 }
295 301
296 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
297 db.generic_params((*self).into())
298 }
299
300 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 302 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
301 db.type_for_def((*self).into(), Namespace::Types) 303 db.type_for_def((*self).into(), Namespace::Types)
302 } 304 }
@@ -307,7 +309,7 @@ impl Struct {
307 309
308 // FIXME move to a more general type 310 // FIXME move to a more general type
309 /// Builds a resolver for type references inside this struct. 311 /// Builds a resolver for type references inside this struct.
310 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 312 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
311 // take the outer scope... 313 // take the outer scope...
312 let r = self.module(db).resolver(db); 314 let r = self.module(db).resolver(db);
313 // ...and add generic params, if present 315 // ...and add generic params, if present
@@ -357,17 +359,13 @@ impl Enum {
357 .map(|(id, _)| EnumVariant { parent: *self, id }) 359 .map(|(id, _)| EnumVariant { parent: *self, id })
358 } 360 }
359 361
360 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
361 db.generic_params((*self).into())
362 }
363
364 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 362 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
365 db.type_for_def((*self).into(), Namespace::Types) 363 db.type_for_def((*self).into(), Namespace::Types)
366 } 364 }
367 365
368 // FIXME: move to a more general type 366 // FIXME: move to a more general type
369 /// Builds a resolver for type references inside this struct. 367 /// Builds a resolver for type references inside this struct.
370 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 368 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
371 // take the outer scope... 369 // take the outer scope...
372 let r = self.module(db).resolver(db); 370 let r = self.module(db).resolver(db);
373 // ...and add generic params, if present 371 // ...and add generic params, if present
@@ -444,28 +442,22 @@ impl DefWithBody {
444 db.infer(*self) 442 db.infer(*self)
445 } 443 }
446 444
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> { 445 pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
452 db.body_hir(*self) 446 db.body_hir(*self)
453 } 447 }
454 448
449 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
450 db.body_with_source_map(*self).1
451 }
452
455 /// Builds a resolver for code inside this item. 453 /// Builds a resolver for code inside this item.
456 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 454 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
457 match *self { 455 match *self {
458 DefWithBody::Const(ref c) => c.resolver(db), 456 DefWithBody::Const(ref c) => c.resolver(db),
459 DefWithBody::Function(ref f) => f.resolver(db), 457 DefWithBody::Function(ref f) => f.resolver(db),
460 DefWithBody::Static(ref s) => s.resolver(db), 458 DefWithBody::Static(ref s) => s.resolver(db),
461 } 459 }
462 } 460 }
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} 461}
470 462
471#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 463#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -517,7 +509,7 @@ impl Function {
517 self.signature(db).name.clone() 509 self.signature(db).name.clone()
518 } 510 }
519 511
520 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 512 pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
521 db.body_with_source_map((*self).into()).1 513 db.body_with_source_map((*self).into()).1
522 } 514 }
523 515
@@ -529,12 +521,6 @@ impl Function {
529 db.type_for_def((*self).into(), Namespace::Values) 521 db.type_for_def((*self).into(), Namespace::Values)
530 } 522 }
531 523
532 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap {
533 let scopes = db.expr_scopes((*self).into());
534 let source_map = db.body_with_source_map((*self).into()).1;
535 ScopesWithSourceMap { scopes, source_map }
536 }
537
538 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { 524 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
539 db.fn_signature(*self) 525 db.fn_signature(*self)
540 } 526 }
@@ -543,24 +529,32 @@ impl Function {
543 db.infer((*self).into()) 529 db.infer((*self).into())
544 } 530 }
545 531
546 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
547 db.generic_params((*self).into())
548 }
549
550 /// The containing impl block, if this is a method. 532 /// The containing impl block, if this is a method.
551 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 533 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
552 let module_impls = db.impls_in_module(self.module(db)); 534 let module_impls = db.impls_in_module(self.module(db));
553 ImplBlock::containing(module_impls, (*self).into()) 535 ImplBlock::containing(module_impls, (*self).into())
554 } 536 }
555 537
538 /// The containing trait, if this is a trait method definition.
539 pub fn parent_trait(&self, db: &impl DefDatabase) -> Option<Trait> {
540 db.trait_items_index(self.module(db)).get_parent_trait((*self).into())
541 }
542
543 pub fn container(&self, db: &impl DefDatabase) -> Option<Container> {
544 if let Some(impl_block) = self.impl_block(db) {
545 Some(impl_block.into())
546 } else if let Some(trait_) = self.parent_trait(db) {
547 Some(trait_.into())
548 } else {
549 None
550 }
551 }
552
556 // FIXME: move to a more general type for 'body-having' items 553 // FIXME: move to a more general type for 'body-having' items
557 /// Builds a resolver for code inside this item. 554 /// Builds a resolver for code inside this item.
558 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 555 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
559 // take the outer scope... 556 // take the outer scope...
560 let r = self 557 let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db));
561 .impl_block(db)
562 .map(|ib| ib.resolver(db))
563 .unwrap_or_else(|| self.module(db).resolver(db));
564 // ...and add generic params, if present 558 // ...and add generic params, if present
565 let p = self.generic_params(db); 559 let p = self.generic_params(db);
566 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; 560 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
@@ -600,10 +594,6 @@ impl Const {
600 db.infer((*self).into()) 594 db.infer((*self).into())
601 } 595 }
602 596
603 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
604 db.body_with_source_map((*self).into()).1
605 }
606
607 /// The containing impl block, if this is a method. 597 /// The containing impl block, if this is a method.
608 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 598 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
609 let module_impls = db.impls_in_module(self.module(db)); 599 let module_impls = db.impls_in_module(self.module(db));
@@ -612,7 +602,7 @@ impl Const {
612 602
613 // FIXME: move to a more general type for 'body-having' items 603 // FIXME: move to a more general type for 'body-having' items
614 /// Builds a resolver for code inside this item. 604 /// Builds a resolver for code inside this item.
615 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 605 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
616 // take the outer scope... 606 // take the outer scope...
617 let r = self 607 let r = self
618 .impl_block(db) 608 .impl_block(db)
@@ -664,7 +654,7 @@ impl Static {
664 } 654 }
665 655
666 /// Builds a resolver for code inside this item. 656 /// Builds a resolver for code inside this item.
667 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 657 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
668 // take the outer scope... 658 // take the outer scope...
669 self.module(db).resolver(db) 659 self.module(db).resolver(db)
670 } 660 }
@@ -672,10 +662,6 @@ impl Static {
672 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 662 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
673 db.infer((*self).into()) 663 db.infer((*self).into())
674 } 664 }
675
676 pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
677 db.body_with_source_map((*self).into()).1
678 }
679} 665}
680 666
681impl Docs for Static { 667impl Docs for Static {
@@ -698,10 +684,6 @@ impl Trait {
698 self.id.module(db) 684 self.id.module(db)
699 } 685 }
700 686
701 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
702 db.generic_params((*self).into())
703 }
704
705 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 687 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
706 self.trait_data(db).name().clone() 688 self.trait_data(db).name().clone()
707 } 689 }
@@ -713,6 +695,14 @@ impl Trait {
713 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 695 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
714 db.trait_data(self) 696 db.trait_data(self)
715 } 697 }
698
699 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
700 let r = self.module(db).resolver(db);
701 // add generic params, if present
702 let p = self.generic_params(db);
703 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
704 r
705 }
716} 706}
717 707
718impl Docs for Trait { 708impl Docs for Trait {
@@ -731,10 +721,6 @@ impl TypeAlias {
731 self.id.source(db) 721 self.id.source(db)
732 } 722 }
733 723
734 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
735 db.generic_params((*self).into())
736 }
737
738 pub fn module(&self, db: &impl DefDatabase) -> Module { 724 pub fn module(&self, db: &impl DefDatabase) -> Module {
739 self.id.module(db) 725 self.id.module(db)
740 } 726 }
@@ -745,12 +731,27 @@ impl TypeAlias {
745 ImplBlock::containing(module_impls, (*self).into()) 731 ImplBlock::containing(module_impls, (*self).into())
746 } 732 }
747 733
734 /// The containing trait, if this is a trait method definition.
735 pub fn parent_trait(&self, db: &impl DefDatabase) -> Option<Trait> {
736 db.trait_items_index(self.module(db)).get_parent_trait((*self).into())
737 }
738
739 pub fn container(&self, db: &impl DefDatabase) -> Option<Container> {
740 if let Some(impl_block) = self.impl_block(db) {
741 Some(impl_block.into())
742 } else if let Some(trait_) = self.parent_trait(db) {
743 Some(trait_.into())
744 } else {
745 None
746 }
747 }
748
748 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> { 749 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> {
749 db.type_alias_ref(self) 750 db.type_alias_ref(self)
750 } 751 }
751 752
752 /// Builds a resolver for the type references in this type alias. 753 /// Builds a resolver for the type references in this type alias.
753 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 754 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
754 // take the outer scope... 755 // take the outer scope...
755 let r = self 756 let r = self
756 .impl_block(db) 757 .impl_block(db)
@@ -768,3 +769,18 @@ impl Docs for TypeAlias {
768 docs_from_ast(&*self.source(db).1) 769 docs_from_ast(&*self.source(db).1)
769 } 770 }
770} 771}
772
773pub enum Container {
774 Trait(Trait),
775 ImplBlock(ImplBlock),
776}
777impl_froms!(Container: Trait, ImplBlock);
778
779impl Container {
780 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
781 match self {
782 Container::Trait(trait_) => trait_.resolver(db),
783 Container::ImplBlock(impl_block) => impl_block.resolver(db),
784 }
785 }
786}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 88dee3a69..5c2ea73ce 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -3,9 +3,9 @@ use ra_syntax::{ast, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Name, AstId, 5 Module, ModuleSource, Name, AstId,
6 nameres::{CrateModuleId, ImportId}, 6 nameres::CrateModuleId,
7 HirDatabase, DefDatabase, 7 HirDatabase, DefDatabase,
8 HirFileId, ImportSource, 8 HirFileId,
9}; 9};
10 10
11impl ModuleSource { 11impl ModuleSource {
@@ -68,16 +68,6 @@ impl Module {
68 Some((decl.file_id(), ast)) 68 Some((decl.file_id(), ast))
69 } 69 }
70 70
71 pub(crate) fn import_source_impl(
72 &self,
73 db: &impl HirDatabase,
74 import: ImportId,
75 ) -> ImportSource {
76 let (file_id, source) = self.definition_source(db);
77 let (_, source_map) = db.raw_items_with_source_map(file_id);
78 source_map.get(&source, import)
79 }
80
81 pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module { 71 pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module {
82 let def_map = db.crate_def_map(self.krate); 72 let def_map = db.crate_def_map(self.krate);
83 self.with_module_id(def_map.root()) 73 self.with_module_id(def_map.root())
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index be8a8c98b..18627bbc2 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,10 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile, ast};
4use ra_db::{SourceDatabase, salsa}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
7 HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, HirInterner, 7 HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, MacroCallLoc,
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,
@@ -15,11 +15,29 @@ use crate::{
15 impl_block::{ModuleImplBlocks, ImplSourceMap}, 15 impl_block::{ModuleImplBlocks, ImplSourceMap},
16 generics::{GenericParams, GenericDef}, 16 generics::{GenericParams, GenericDef},
17 type_ref::TypeRef, 17 type_ref::TypeRef,
18 traits::TraitData, Trait, ty::TraitRef 18 traits::TraitData, Trait, ty::TraitRef,
19 ids
19}; 20};
20 21
21#[salsa::query_group(DefDatabaseStorage)] 22#[salsa::query_group(DefDatabaseStorage)]
22pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> { 23pub trait DefDatabase: SourceDatabase {
24 #[salsa::interned]
25 fn intern_macro(&self, macro_call: MacroCallLoc) -> ids::MacroCallId;
26 #[salsa::interned]
27 fn intern_function(&self, loc: ids::ItemLoc<ast::FnDef>) -> ids::FunctionId;
28 #[salsa::interned]
29 fn intern_struct(&self, loc: ids::ItemLoc<ast::StructDef>) -> ids::StructId;
30 #[salsa::interned]
31 fn intern_enum(&self, loc: ids::ItemLoc<ast::EnumDef>) -> ids::EnumId;
32 #[salsa::interned]
33 fn intern_const(&self, loc: ids::ItemLoc<ast::ConstDef>) -> ids::ConstId;
34 #[salsa::interned]
35 fn intern_static(&self, loc: ids::ItemLoc<ast::StaticDef>) -> ids::StaticId;
36 #[salsa::interned]
37 fn intern_trait(&self, loc: ids::ItemLoc<ast::TraitDef>) -> ids::TraitId;
38 #[salsa::interned]
39 fn intern_type_alias(&self, loc: ids::ItemLoc<ast::TypeAliasDef>) -> ids::TypeAliasId;
40
23 #[salsa::invoke(crate::ids::macro_def_query)] 41 #[salsa::invoke(crate::ids::macro_def_query)]
24 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; 42 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
25 43
@@ -35,6 +53,9 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
35 #[salsa::invoke(crate::traits::TraitData::trait_data_query)] 53 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
36 fn trait_data(&self, t: Trait) -> Arc<TraitData>; 54 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
37 55
56 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
57 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
58
38 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] 59 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
39 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; 60 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
40 61
@@ -110,8 +131,8 @@ pub trait HirDatabase: DefDatabase {
110 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 131 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
111 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 132 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
112 133
113 #[salsa::invoke(crate::ty::method_resolution::implements)] 134 #[salsa::invoke(crate::ty::traits::implements)]
114 fn implements(&self, trait_ref: TraitRef) -> bool; 135 fn implements(&self, trait_ref: TraitRef) -> Option<crate::ty::traits::Solution>;
115} 136}
116 137
117#[test] 138#[test]
diff --git a/crates/ra_hir/src/either.rs b/crates/ra_hir/src/either.rs
new file mode 100644
index 000000000..4073cc82e
--- /dev/null
+++ b/crates/ra_hir/src/either.rs
@@ -0,0 +1,28 @@
1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub enum Either<A, B> {
3 A(A),
4 B(B),
5}
6
7impl<A, B> Either<A, B> {
8 pub fn either<R, F1, F2>(self, f1: F1, f2: F2) -> R
9 where
10 F1: FnOnce(A) -> R,
11 F2: FnOnce(B) -> R,
12 {
13 match self {
14 Either::A(a) => f1(a),
15 Either::B(b) => f2(b),
16 }
17 }
18 pub fn map<U, V, F1, F2>(self, f1: F1, f2: F2) -> Either<U, V>
19 where
20 F1: FnOnce(A) -> U,
21 F2: FnOnce(B) -> V,
22 {
23 match self {
24 Either::A(a) => Either::A(f1(a)),
25 Either::B(b) => Either::B(f2(b)),
26 }
27 }
28}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 589a9b2db..817e660f9 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -10,13 +10,13 @@ use ra_syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either,
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
17use crate::{ path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; 17use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}; 19pub use self::scope::ExprScopes;
20 20
21pub(crate) mod scope; 21pub(crate) mod scope;
22 22
@@ -51,11 +51,13 @@ pub struct Body {
51pub struct BodySourceMap { 51pub struct BodySourceMap {
52 expr_map: FxHashMap<SyntaxNodePtr, ExprId>, 52 expr_map: FxHashMap<SyntaxNodePtr, ExprId>,
53 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 53 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
54 pat_map: FxHashMap<SyntaxNodePtr, PatId>, 54 pat_map: FxHashMap<PatPtr, PatId>,
55 pat_map_back: ArenaMap<PatId, SyntaxNodePtr>, 55 pat_map_back: ArenaMap<PatId, PatPtr>,
56 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>, 56 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>,
57} 57}
58 58
59type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
60
59impl Body { 61impl Body {
60 pub fn params(&self) -> &[PatId] { 62 pub fn params(&self) -> &[PatId] {
61 &self.params 63 &self.params
@@ -79,19 +81,23 @@ impl Body {
79} 81}
80 82
81// needs arbitrary_self_types to be a method... or maybe move to the def? 83// needs arbitrary_self_types to be a method... or maybe move to the def?
82pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { 84pub(crate) fn resolver_for_expr(
85 body: Arc<Body>,
86 db: &impl HirDatabase,
87 expr_id: ExprId,
88) -> Resolver {
83 let scopes = db.expr_scopes(body.owner); 89 let scopes = db.expr_scopes(body.owner);
84 resolver_for_scope(body, db, scopes.scope_for(expr_id)) 90 resolver_for_scope(body, db, scopes.scope_for(expr_id))
85} 91}
86 92
87pub fn resolver_for_scope( 93pub(crate) fn resolver_for_scope(
88 body: Arc<Body>, 94 body: Arc<Body>,
89 db: &impl HirDatabase, 95 db: &impl HirDatabase,
90 scope_id: Option<scope::ScopeId>, 96 scope_id: Option<scope::ScopeId>,
91) -> Resolver { 97) -> Resolver {
92 let mut r = body.owner.resolver(db); 98 let mut r = body.owner.resolver(db);
93 let scopes = db.expr_scopes(body.owner); 99 let scopes = db.expr_scopes(body.owner);
94 let scope_chain = scopes.scope_chain_for(scope_id).collect::<Vec<_>>(); 100 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
95 for scope in scope_chain.into_iter().rev() { 101 for scope in scope_chain.into_iter().rev() {
96 r = r.push_expr_scope(Arc::clone(&scopes), scope); 102 r = r.push_expr_scope(Arc::clone(&scopes), scope);
97 } 103 }
@@ -115,31 +121,27 @@ impl Index<PatId> for Body {
115} 121}
116 122
117impl BodySourceMap { 123impl BodySourceMap {
118 pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { 124 pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> {
119 self.expr_map_back.get(expr).cloned() 125 self.expr_map_back.get(expr).cloned()
120 } 126 }
121 127
122 pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> { 128 pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
123 self.expr_map.get(&ptr).cloned() 129 self.expr_map.get(&ptr).cloned()
124 } 130 }
125 131
126 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 132 pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
127 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 133 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
128 } 134 }
129 135
130 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> { 136 pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> {
131 self.pat_map_back.get(pat).cloned() 137 self.pat_map_back.get(pat).cloned()
132 } 138 }
133 139
134 pub fn syntax_pat(&self, ptr: SyntaxNodePtr) -> Option<PatId> { 140 pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
135 self.pat_map.get(&ptr).cloned() 141 self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
136 }
137
138 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
139 self.pat_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
140 } 142 }
141 143
142 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> { 144 pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> {
143 self.field_map[&(expr, field)].clone() 145 self.field_map[&(expr, field)].clone()
144 } 146 }
145} 147}
@@ -504,10 +506,10 @@ impl ExprCollector {
504 id 506 id
505 } 507 }
506 508
507 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: SyntaxNodePtr) -> PatId { 509 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
508 let id = self.pats.alloc(pat); 510 let id = self.pats.alloc(pat);
509 self.source_map.pat_map.insert(syntax_ptr, id); 511 self.source_map.pat_map.insert(ptr, id);
510 self.source_map.pat_map_back.insert(id, syntax_ptr); 512 self.source_map.pat_map_back.insert(id, ptr);
511 id 513 id
512 } 514 }
513 515
@@ -886,8 +888,8 @@ impl ExprCollector {
886 ast::PatKind::LiteralPat(_) => Pat::Missing, 888 ast::PatKind::LiteralPat(_) => Pat::Missing,
887 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing, 889 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
888 }; 890 };
889 let syntax_ptr = SyntaxNodePtr::new(pat.syntax()); 891 let ptr = AstPtr::new(pat);
890 self.alloc_pat(pattern, syntax_ptr) 892 self.alloc_pat(pattern, Either::A(ptr))
891 } 893 }
892 894
893 fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId { 895 fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId {
@@ -911,14 +913,14 @@ impl ExprCollector {
911 fn collect_fn_body(&mut self, node: &ast::FnDef) { 913 fn collect_fn_body(&mut self, node: &ast::FnDef) {
912 if let Some(param_list) = node.param_list() { 914 if let Some(param_list) = node.param_list() {
913 if let Some(self_param) = param_list.self_param() { 915 if let Some(self_param) = param_list.self_param() {
914 let self_param = SyntaxNodePtr::new(self_param.syntax()); 916 let ptr = AstPtr::new(self_param);
915 let param_pat = self.alloc_pat( 917 let param_pat = self.alloc_pat(
916 Pat::Bind { 918 Pat::Bind {
917 name: Name::self_param(), 919 name: Name::self_param(),
918 mode: BindingAnnotation::Unannotated, 920 mode: BindingAnnotation::Unannotated,
919 subpat: None, 921 subpat: None,
920 }, 922 },
921 self_param, 923 Either::B(ptr),
922 ); 924 );
923 self.params.push(param_pat); 925 self.params.push(param_pat);
924 } 926 }
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 48283907b..58f365128 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -1,17 +1,11 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::FxHashMap;
4
5use ra_syntax::{
6 AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr,
7 algo::generate,
8 ast,
9};
10use ra_arena::{Arena, RawId, impl_arena_id}; 4use ra_arena::{Arena, RawId, impl_arena_id};
11 5
12use crate::{ 6use crate::{
13 Name, AsName,DefWithBody, 7 Name, DefWithBody,
14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap}, 8 expr::{PatId, ExprId, Pat, Expr, Body, Statement},
15 HirDatabase, 9 HirDatabase,
16}; 10};
17 11
@@ -23,23 +17,32 @@ impl_arena_id!(ScopeId);
23pub struct ExprScopes { 17pub struct ExprScopes {
24 body: Arc<Body>, 18 body: Arc<Body>,
25 scopes: Arena<ScopeId, ScopeData>, 19 scopes: Arena<ScopeId, ScopeData>,
26 scope_for: FxHashMap<ExprId, ScopeId>, 20 scope_by_expr: FxHashMap<ExprId, ScopeId>,
27} 21}
28 22
29#[derive(Debug, PartialEq, Eq)] 23#[derive(Debug, PartialEq, Eq)]
30pub struct ScopeEntry { 24pub(crate) struct ScopeEntry {
31 name: Name, 25 name: Name,
32 pat: PatId, 26 pat: PatId,
33} 27}
34 28
29impl ScopeEntry {
30 pub(crate) fn name(&self) -> &Name {
31 &self.name
32 }
33
34 pub(crate) fn pat(&self) -> PatId {
35 self.pat
36 }
37}
38
35#[derive(Debug, PartialEq, Eq)] 39#[derive(Debug, PartialEq, Eq)]
36pub struct ScopeData { 40pub(crate) struct ScopeData {
37 parent: Option<ScopeId>, 41 parent: Option<ScopeId>,
38 entries: Vec<ScopeEntry>, 42 entries: Vec<ScopeEntry>,
39} 43}
40 44
41impl ExprScopes { 45impl ExprScopes {
42 // FIXME: This should take something more general than Function
43 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<ExprScopes> { 46 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<ExprScopes> {
44 let body = db.body_hir(def); 47 let body = db.body_hir(def);
45 let res = ExprScopes::new(body); 48 let res = ExprScopes::new(body);
@@ -50,7 +53,7 @@ impl ExprScopes {
50 let mut scopes = ExprScopes { 53 let mut scopes = ExprScopes {
51 body: body.clone(), 54 body: body.clone(),
52 scopes: Arena::default(), 55 scopes: Arena::default(),
53 scope_for: FxHashMap::default(), 56 scope_by_expr: FxHashMap::default(),
54 }; 57 };
55 let root = scopes.root_scope(); 58 let root = scopes.root_scope();
56 scopes.add_params_bindings(root, body.params()); 59 scopes.add_params_bindings(root, body.params());
@@ -58,19 +61,23 @@ impl ExprScopes {
58 scopes 61 scopes
59 } 62 }
60 63
61 pub fn body(&self) -> Arc<Body> { 64 pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
62 self.body.clone()
63 }
64
65 pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
66 &self.scopes[scope].entries 65 &self.scopes[scope].entries
67 } 66 }
68 67
69 pub fn scope_chain_for<'a>( 68 pub(crate) fn scope_chain<'a>(
70 &'a self, 69 &'a self,
71 scope: Option<ScopeId>, 70 scope: Option<ScopeId>,
72 ) -> impl Iterator<Item = ScopeId> + 'a { 71 ) -> impl Iterator<Item = ScopeId> + 'a {
73 generate(scope, move |&scope| self.scopes[scope].parent) 72 std::iter::successors(scope, move |&scope| self.scopes[scope].parent)
73 }
74
75 pub(crate) fn scope_for(&self, expr: ExprId) -> Option<ScopeId> {
76 self.scope_by_expr.get(&expr).map(|&scope| scope)
77 }
78
79 pub(crate) fn scope_by_expr(&self) -> &FxHashMap<ExprId, ScopeId> {
80 &self.scope_by_expr
74 } 81 }
75 82
76 fn root_scope(&mut self) -> ScopeId { 83 fn root_scope(&mut self) -> ScopeId {
@@ -99,130 +106,7 @@ impl ExprScopes {
99 } 106 }
100 107
101 fn set_scope(&mut self, node: ExprId, scope: ScopeId) { 108 fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
102 self.scope_for.insert(node, scope); 109 self.scope_by_expr.insert(node, scope);
103 }
104
105 pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> {
106 self.scope_for.get(&expr).map(|&scope| scope)
107 }
108}
109
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct ScopesWithSourceMap {
112 pub source_map: Arc<BodySourceMap>,
113 pub scopes: Arc<ExprScopes>,
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct ScopeEntryWithSyntax {
118 name: Name,
119 ptr: SyntaxNodePtr,
120}
121
122impl ScopeEntryWithSyntax {
123 pub fn name(&self) -> &Name {
124 &self.name
125 }
126
127 pub fn ptr(&self) -> SyntaxNodePtr {
128 self.ptr
129 }
130}
131
132impl ScopesWithSourceMap {
133 fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a {
134 generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent)
135 }
136
137 pub fn scope_for_offset(&self, offset: TextUnit) -> Option<ScopeId> {
138 self.scopes
139 .scope_for
140 .iter()
141 .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope)))
142 // find containing scope
143 .min_by_key(|(ptr, _scope)| {
144 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len())
145 })
146 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset))
147 }
148
149 // XXX: during completion, cursor might be outside of any particular
150 // expression. Try to figure out the correct scope...
151 // FIXME: move this to source binder?
152 fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId {
153 let r = ptr.range();
154 let child_scopes = self
155 .scopes
156 .scope_for
157 .iter()
158 .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope)))
159 .map(|(ptr, scope)| (ptr.range(), scope))
160 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
161
162 child_scopes
163 .max_by(|(r1, _), (r2, _)| {
164 if r2.is_subrange(&r1) {
165 std::cmp::Ordering::Greater
166 } else if r1.is_subrange(&r2) {
167 std::cmp::Ordering::Less
168 } else {
169 r1.start().cmp(&r2.start())
170 }
171 })
172 .map(|(_ptr, scope)| *scope)
173 .unwrap_or(original_scope)
174 }
175
176 pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> {
177 let mut shadowed = FxHashSet::default();
178 let name = name_ref.as_name();
179 let ret = self
180 .scope_chain(name_ref.syntax())
181 .flat_map(|scope| self.scopes.entries(scope).iter())
182 .filter(|entry| shadowed.insert(entry.name()))
183 .filter(|entry| entry.name() == &name)
184 .nth(0);
185 ret.and_then(|entry| {
186 Some(ScopeEntryWithSyntax {
187 name: entry.name().clone(),
188 ptr: self.source_map.pat_syntax(entry.pat())?,
189 })
190 })
191 }
192
193 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
194 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
195 let name_ptr = SyntaxNodePtr::new(pat.syntax());
196 fn_def
197 .syntax()
198 .descendants()
199 .filter_map(ast::NameRef::cast)
200 .filter(|name_ref| match self.resolve_local_name(*name_ref) {
201 None => false,
202 Some(entry) => entry.ptr() == name_ptr,
203 })
204 .map(|name_ref| ReferenceDescriptor {
205 name: name_ref.syntax().text().to_string(),
206 range: name_ref.syntax().range(),
207 })
208 .collect()
209 }
210
211 pub fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> {
212 node.ancestors()
213 .map(SyntaxNodePtr::new)
214 .filter_map(|ptr| self.source_map.syntax_expr(ptr))
215 .find_map(|it| self.scopes.scope_for(it))
216 }
217}
218
219impl ScopeEntry {
220 pub fn name(&self) -> &Name {
221 &self.name
222 }
223
224 pub fn pat(&self) -> PatId {
225 self.pat
226 } 110 }
227} 111}
228 112
@@ -286,22 +170,13 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
286 }; 170 };
287} 171}
288 172
289#[derive(Debug)]
290pub struct ReferenceDescriptor {
291 pub range: TextRange,
292 pub name: String,
293}
294
295#[cfg(test)] 173#[cfg(test)]
296mod tests { 174mod tests {
297 use ra_syntax::{SourceFile, algo::find_node_at_offset}; 175 use ra_db::SourceDatabase;
176 use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr, ast};
298 use test_utils::{extract_offset, assert_eq_text}; 177 use test_utils::{extract_offset, assert_eq_text};
299 use ra_arena::ArenaId;
300 use crate::Function;
301
302 use crate::expr::{ExprCollector};
303 178
304 use super::*; 179 use crate::{source_binder::SourceAnalyzer, mock::MockDatabase};
305 180
306 fn do_check(code: &str, expected: &[&str]) { 181 fn do_check(code: &str, expected: &[&str]) {
307 let (off, code) = extract_offset(code); 182 let (off, code) = extract_offset(code);
@@ -313,17 +188,20 @@ mod tests {
313 buf.push_str(&code[off..]); 188 buf.push_str(&code[off..]);
314 buf 189 buf
315 }; 190 };
316 let file = SourceFile::parse(&code); 191
192 let (db, _source_root, file_id) = MockDatabase::with_single_file(&code);
193 let file = db.parse(file_id);
317 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 194 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
318 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 195 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None);
319 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) }; 196
320 let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); 197 let scopes = analyzer.scopes();
321 let scopes = ExprScopes::new(Arc::new(body)); 198 let expr_id =
322 let scopes = 199 analyzer.body_source_map().syntax_expr(SyntaxNodePtr::new(marker.syntax())).unwrap();
323 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; 200 let scope = scopes.scope_for(expr_id);
201
324 let actual = scopes 202 let actual = scopes
325 .scope_chain(marker.syntax()) 203 .scope_chain(scope)
326 .flat_map(|scope| scopes.scopes.entries(scope)) 204 .flat_map(|scope| scopes.entries(scope))
327 .map(|it| it.name().to_string()) 205 .map(|it| it.name().to_string())
328 .collect::<Vec<_>>() 206 .collect::<Vec<_>>()
329 .join("\n"); 207 .join("\n");
@@ -406,28 +284,19 @@ mod tests {
406 ); 284 );
407 } 285 }
408 286
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
415 fn do_check_local_name(code: &str, expected_offset: u32) { 287 fn do_check_local_name(code: &str, expected_offset: u32) {
416 let (off, code) = extract_offset(code); 288 let (off, code) = extract_offset(code);
417 let file = SourceFile::parse(&code); 289
290 let (db, _source_root, file_id) = MockDatabase::with_single_file(&code);
291 let file = db.parse(file_id);
418 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) 292 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into())
419 .expect("failed to find a name at the target offset"); 293 .expect("failed to find a name at the target offset");
420
421 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
422 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 294 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
295 let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None);
423 296
424 let irrelevant_function = Function { id: crate::ids::FunctionId::from_raw(0.into()) }; 297 let local_name_entry = analyzer.resolve_local_name(name_ref).unwrap();
425 let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); 298 let local_name =
426 let scopes = ExprScopes::new(Arc::new(body)); 299 local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
427 let scopes =
428 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };
429 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
430 let local_name = local_name_entry.ptr();
431 assert_eq!(local_name.range(), expected_name.syntax().range()); 300 assert_eq!(local_name.range(), expected_name.syntax().range());
432 } 301 }
433 302
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 84fe94289..5625c2459 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner};
9 9
10use crate::{ 10use crate::{
11 db::DefDatabase, 11 db::DefDatabase,
12 Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock 12 Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container
13}; 13};
14 14
15/// Data about a generic parameter (to a function, struct, impl, ...). 15/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -27,6 +27,7 @@ pub struct GenericParams {
27 pub(crate) params: Vec<GenericParam>, 27 pub(crate) params: Vec<GenericParam>,
28} 28}
29 29
30// FIXME: consts can have type parameters from their parents (i.e. associated consts of traits)
30#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 31#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
31pub enum GenericDef { 32pub enum GenericDef {
32 Function(Function), 33 Function(Function),
@@ -45,18 +46,22 @@ impl GenericParams {
45 ) -> Arc<GenericParams> { 46 ) -> Arc<GenericParams> {
46 let mut generics = GenericParams::default(); 47 let mut generics = GenericParams::default();
47 let parent = match def { 48 let parent = match def {
48 GenericDef::Function(it) => it.impl_block(db), 49 GenericDef::Function(it) => it.container(db).map(GenericDef::from),
49 GenericDef::TypeAlias(it) => it.impl_block(db), 50 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
50 GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, 51 GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None,
51 GenericDef::ImplBlock(_) => None, 52 GenericDef::ImplBlock(_) => None,
52 }; 53 };
53 generics.parent_params = parent.map(|p| p.generic_params(db)); 54 generics.parent_params = parent.map(|p| db.generic_params(p));
54 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; 55 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
55 match def { 56 match def {
56 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), 57 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start),
57 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), 58 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start),
58 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), 59 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
59 GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start), 60 GenericDef::Trait(it) => {
61 // traits get the Self type as an implicit first type parameter
62 generics.params.push(GenericParam { idx: start, name: Name::self_type() });
63 generics.fill(&*it.source(db).1, start + 1);
64 }
60 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), 65 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start),
61 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), 66 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start),
62 } 67 }
@@ -104,3 +109,25 @@ impl GenericParams {
104 vec 109 vec
105 } 110 }
106} 111}
112
113impl From<Container> for GenericDef {
114 fn from(c: Container) -> Self {
115 match c {
116 Container::Trait(trait_) => trait_.into(),
117 Container::ImplBlock(impl_block) => impl_block.into(),
118 }
119 }
120}
121
122pub trait HasGenericParams {
123 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams>;
124}
125
126impl<T> HasGenericParams for T
127where
128 T: Into<GenericDef>,
129{
130 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> {
131 db.generic_params(self.into())
132 }
133}
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index eb9939df7..141c9072f 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -3,40 +3,14 @@ use std::{
3 sync::Arc, 3 sync::Arc,
4}; 4};
5 5
6use ra_db::{LocationInterner, FileId}; 6use ra_db::{FileId, salsa};
7use ra_syntax::{TreeArc, SourceFile, AstNode, ast}; 7use ra_syntax::{TreeArc, SourceFile, AstNode, ast};
8use ra_arena::{RawId, ArenaId, impl_arena_id};
9use mbe::MacroRules; 8use mbe::MacroRules;
10 9
11use crate::{ 10use crate::{
12 Module, DefDatabase, AstId, FileAstId, 11 Module, DefDatabase, AstId, FileAstId,
13}; 12};
14 13
15#[derive(Debug, Default)]
16pub struct HirInterner {
17 macros: LocationInterner<MacroCallLoc, MacroCallId>,
18 fns: LocationInterner<ItemLoc<ast::FnDef>, FunctionId>,
19 structs: LocationInterner<ItemLoc<ast::StructDef>, StructId>,
20 enums: LocationInterner<ItemLoc<ast::EnumDef>, EnumId>,
21 consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>,
22 statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>,
23 traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>,
24 types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeAliasId>,
25}
26
27impl HirInterner {
28 pub fn len(&self) -> usize {
29 self.macros.len()
30 + self.fns.len()
31 + self.structs.len()
32 + self.enums.len()
33 + self.consts.len()
34 + self.statics.len()
35 + self.traits.len()
36 + self.types.len()
37 }
38}
39
40/// hir makes heavy use of ids: integer (u32) handlers to various things. You 14/// hir makes heavy use of ids: integer (u32) handlers to various things. You
41/// can think of id as a pointer (but without a lifetime) or a file descriptor 15/// can think of id as a pointer (but without a lifetime) or a file descriptor
42/// (but for hir objects). 16/// (but for hir objects).
@@ -135,11 +109,24 @@ pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<A
135 Some(Arc::new(rules)) 109 Some(Arc::new(rules))
136} 110}
137 111
112macro_rules! impl_intern_key {
113 ($name:ident) => {
114 impl salsa::InternKey for $name {
115 fn from_intern_id(v: salsa::InternId) -> Self {
116 $name(v)
117 }
118 fn as_intern_id(&self) -> salsa::InternId {
119 self.0
120 }
121 }
122 };
123}
124
138/// `MacroCallId` identifies a particular macro invocation, like 125/// `MacroCallId` identifies a particular macro invocation, like
139/// `println!("Hello, {}", world)`. 126/// `println!("Hello, {}", world)`.
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
141pub struct MacroCallId(RawId); 128pub struct MacroCallId(salsa::InternId);
142impl_arena_id!(MacroCallId); 129impl_intern_key!(MacroCallId);
143 130
144#[derive(Debug, Clone, PartialEq, Eq, Hash)] 131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
145pub struct MacroCallLoc { 132pub struct MacroCallLoc {
@@ -148,14 +135,14 @@ pub struct MacroCallLoc {
148} 135}
149 136
150impl MacroCallId { 137impl MacroCallId {
151 pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> MacroCallLoc { 138 pub(crate) fn loc(self, db: &impl DefDatabase) -> MacroCallLoc {
152 db.as_ref().macros.id2loc(self) 139 db.lookup_intern_macro(self)
153 } 140 }
154} 141}
155 142
156impl MacroCallLoc { 143impl MacroCallLoc {
157 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId { 144 pub(crate) fn id(self, db: &impl DefDatabase) -> MacroCallId {
158 db.as_ref().macros.loc2id(&self) 145 db.intern_macro(self)
159 } 146 }
160} 147}
161 148
@@ -204,8 +191,10 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
204 } 191 }
205} 192}
206 193
207pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { 194pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
208 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>; 195 fn intern(db: &impl DefDatabase, loc: ItemLoc<N>) -> Self;
196 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<N>;
197
209 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { 198 fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self {
210 let items = ctx.db.ast_id_map(ctx.file_id); 199 let items = ctx.db.ast_id_map(ctx.file_id);
211 let item_id = items.ast_id(ast); 200 let item_id = items.ast_id(ast);
@@ -213,80 +202,100 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
213 } 202 }
214 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self { 203 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
215 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) }; 204 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
216 Self::interner(ctx.db.as_ref()).loc2id(&loc) 205 Self::intern(ctx.db, loc)
217 } 206 }
218 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) { 207 fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) {
219 let int = Self::interner(db.as_ref()); 208 let loc = self.lookup_intern(db);
220 let loc = int.id2loc(self);
221 let ast = loc.ast_id.to_node(db); 209 let ast = loc.ast_id.to_node(db);
222 (loc.ast_id.file_id(), ast) 210 (loc.ast_id.file_id(), ast)
223 } 211 }
224 fn module(self, db: &impl DefDatabase) -> Module { 212 fn module(self, db: &impl DefDatabase) -> Module {
225 let int = Self::interner(db.as_ref()); 213 let loc = self.lookup_intern(db);
226 let loc = int.id2loc(self);
227 loc.module 214 loc.module
228 } 215 }
229} 216}
230 217
231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 218#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
232pub(crate) struct FunctionId(RawId); 219pub struct FunctionId(salsa::InternId);
233impl_arena_id!(FunctionId); 220impl_intern_key!(FunctionId);
221
234impl AstItemDef<ast::FnDef> for FunctionId { 222impl AstItemDef<ast::FnDef> for FunctionId {
235 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> { 223 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::FnDef>) -> Self {
236 &interner.fns 224 db.intern_function(loc)
225 }
226 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::FnDef> {
227 db.lookup_intern_function(self)
237 } 228 }
238} 229}
239 230
240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
241pub(crate) struct StructId(RawId); 232pub struct StructId(salsa::InternId);
242impl_arena_id!(StructId); 233impl_intern_key!(StructId);
243impl AstItemDef<ast::StructDef> for StructId { 234impl AstItemDef<ast::StructDef> for StructId {
244 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> { 235 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
245 &interner.structs 236 db.intern_struct(loc)
237 }
238 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StructDef> {
239 db.lookup_intern_struct(self)
246 } 240 }
247} 241}
248 242
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 243#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
250pub(crate) struct EnumId(RawId); 244pub struct EnumId(salsa::InternId);
251impl_arena_id!(EnumId); 245impl_intern_key!(EnumId);
252impl AstItemDef<ast::EnumDef> for EnumId { 246impl AstItemDef<ast::EnumDef> for EnumId {
253 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> { 247 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::EnumDef>) -> Self {
254 &interner.enums 248 db.intern_enum(loc)
249 }
250 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::EnumDef> {
251 db.lookup_intern_enum(self)
255 } 252 }
256} 253}
257 254
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 255#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
259pub(crate) struct ConstId(RawId); 256pub struct ConstId(salsa::InternId);
260impl_arena_id!(ConstId); 257impl_intern_key!(ConstId);
261impl AstItemDef<ast::ConstDef> for ConstId { 258impl AstItemDef<ast::ConstDef> for ConstId {
262 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> { 259 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::ConstDef>) -> Self {
263 &interner.consts 260 db.intern_const(loc)
261 }
262 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::ConstDef> {
263 db.lookup_intern_const(self)
264 } 264 }
265} 265}
266 266
267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 267#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
268pub(crate) struct StaticId(RawId); 268pub struct StaticId(salsa::InternId);
269impl_arena_id!(StaticId); 269impl_intern_key!(StaticId);
270impl AstItemDef<ast::StaticDef> for StaticId { 270impl AstItemDef<ast::StaticDef> for StaticId {
271 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> { 271 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StaticDef>) -> Self {
272 &interner.statics 272 db.intern_static(loc)
273 }
274 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StaticDef> {
275 db.lookup_intern_static(self)
273 } 276 }
274} 277}
275 278
276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 279#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
277pub(crate) struct TraitId(RawId); 280pub struct TraitId(salsa::InternId);
278impl_arena_id!(TraitId); 281impl_intern_key!(TraitId);
279impl AstItemDef<ast::TraitDef> for TraitId { 282impl AstItemDef<ast::TraitDef> for TraitId {
280 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> { 283 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TraitDef>) -> Self {
281 &interner.traits 284 db.intern_trait(loc)
285 }
286 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TraitDef> {
287 db.lookup_intern_trait(self)
282 } 288 }
283} 289}
284 290
285#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 291#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
286pub(crate) struct TypeAliasId(RawId); 292pub struct TypeAliasId(salsa::InternId);
287impl_arena_id!(TypeAliasId); 293impl_intern_key!(TypeAliasId);
288impl AstItemDef<ast::TypeAliasDef> for TypeAliasId { 294impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
289 fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> { 295 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self {
290 &interner.types 296 db.intern_type_alias(loc)
297 }
298 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TypeAliasDef> {
299 db.lookup_intern_type_alias(self)
291 } 300 }
292} 301}
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 40d368cd9..a8a466e43 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -9,16 +9,15 @@ use ra_syntax::{
9 9
10use crate::{ 10use crate::{
11 Const, TypeAlias, Function, HirFileId, 11 Const, TypeAlias, Function, HirFileId,
12 HirDatabase, DefDatabase, 12 HirDatabase, DefDatabase, TraitRef,
13 ModuleDef, Trait, Resolution,
14 type_ref::TypeRef, 13 type_ref::TypeRef,
15 ids::LocationCtx, 14 ids::LocationCtx,
16 resolve::Resolver, 15 resolve::Resolver,
17 ty::Ty, generics::GenericParams, 16 ty::Ty,
17 generics::HasGenericParams,
18 code_model_api::{Module, ModuleSource}
18}; 19};
19 20
20use crate::code_model_api::{Module, ModuleSource};
21
22#[derive(Debug, Default, PartialEq, Eq)] 21#[derive(Debug, Default, PartialEq, Eq)]
23pub struct ImplSourceMap { 22pub struct ImplSourceMap {
24 map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>, 23 map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
@@ -73,7 +72,7 @@ impl ImplBlock {
73 self.module 72 self.module
74 } 73 }
75 74
76 pub fn target_trait_ref(&self, db: &impl DefDatabase) -> Option<TypeRef> { 75 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
77 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() 76 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
78 } 77 }
79 78
@@ -85,27 +84,16 @@ impl ImplBlock {
85 Ty::from_hir(db, &self.resolver(db), &self.target_type(db)) 84 Ty::from_hir(db, &self.resolver(db), &self.target_type(db))
86 } 85 }
87 86
88 pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> { 87 pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
89 if let Some(TypeRef::Path(path)) = self.target_trait_ref(db) { 88 let target_ty = self.target_ty(db);
90 let resolver = self.resolver(db); 89 TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty))
91 if let Some(Resolution::Def(ModuleDef::Trait(tr))) =
92 resolver.resolve_path(db, &path).take_types()
93 {
94 return Some(tr);
95 }
96 }
97 None
98 } 90 }
99 91
100 pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> { 92 pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> {
101 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() 93 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
102 } 94 }
103 95
104 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { 96 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
105 db.generic_params((*self).into())
106 }
107
108 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
109 let r = self.module().resolver(db); 97 let r = self.module().resolver(db);
110 // add generic params, if present 98 // add generic params, if present
111 let p = self.generic_params(db); 99 let p = self.generic_params(db);
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index c19450f39..9292de1b5 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -17,6 +17,8 @@ macro_rules! impl_froms {
17 } 17 }
18} 18}
19 19
20mod either;
21
20pub mod db; 22pub mod db;
21#[macro_use] 23#[macro_use]
22pub mod mock; 24pub mod mock;
@@ -49,20 +51,24 @@ use crate::{
49 db::{HirDatabase, DefDatabase}, 51 db::{HirDatabase, DefDatabase},
50 name::{AsName, KnownName}, 52 name::{AsName, KnownName},
51 source_id::{FileAstId, AstId}, 53 source_id::{FileAstId, AstId},
54 resolve::Resolver,
52}; 55};
53 56
54pub use self::{ 57pub use self::{
58 either::Either,
55 path::{Path, PathKind}, 59 path::{Path, PathKind},
56 name::Name, 60 name::Name,
57 source_id::{AstIdMap, ErasedFileAstId}, 61 source_id::{AstIdMap, ErasedFileAstId},
58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner}, 62 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc},
59 nameres::{PerNs, Namespace, ImportId, ImportSource}, 63 nameres::{PerNs, Namespace, ImportId},
60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, 64 ty::{Ty, ApplicationTy, TypeCtor, TraitRef, Substs, display::HirDisplay, CallableDef},
61 impl_block::{ImplBlock, ImplItem}, 65 impl_block::{ImplBlock, ImplItem},
62 docs::{Docs, Documentation}, 66 docs::{Docs, Documentation},
63 adt::AdtDef, 67 adt::AdtDef,
64 expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, 68 expr::ExprScopes,
65 resolve::{Resolver, Resolution}, 69 resolve::Resolution,
70 generics::{GenericParams, GenericParam, HasGenericParams},
71 source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax},
66}; 72};
67 73
68pub use self::code_model_api::{ 74pub use self::code_model_api::{
@@ -73,5 +79,5 @@ pub use self::code_model_api::{
73 Function, FnSignature, 79 Function, FnSignature,
74 StructField, FieldSource, 80 StructField, FieldSource,
75 Static, Const, ConstSignature, 81 Static, Const, ConstSignature,
76 Trait, TypeAlias, 82 Trait, TypeAlias, Container,
77}; 83};
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index aeab6b180..fa5882dea 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -9,7 +9,7 @@ use relative_path::RelativePathBuf;
9use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; 9use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
10use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
11 11
12use crate::{db, HirInterner, diagnostics::DiagnosticSink}; 12use crate::{db, diagnostics::DiagnosticSink};
13 13
14pub const WORKSPACE: SourceRootId = SourceRootId(0); 14pub const WORKSPACE: SourceRootId = SourceRootId(0);
15 15
@@ -18,7 +18,6 @@ pub const WORKSPACE: SourceRootId = SourceRootId(0);
18pub struct MockDatabase { 18pub struct MockDatabase {
19 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, 19 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
20 runtime: salsa::Runtime<MockDatabase>, 20 runtime: salsa::Runtime<MockDatabase>,
21 interner: Arc<HirInterner>,
22 files: FxHashMap<String, FileId>, 21 files: FxHashMap<String, FileId>,
23} 22}
24 23
@@ -195,7 +194,6 @@ impl Default for MockDatabase {
195 let mut db = MockDatabase { 194 let mut db = MockDatabase {
196 events: Default::default(), 195 events: Default::default(),
197 runtime: salsa::Runtime::default(), 196 runtime: salsa::Runtime::default(),
198 interner: Default::default(),
199 files: FxHashMap::default(), 197 files: FxHashMap::default(),
200 }; 198 };
201 db.set_crate_graph(Default::default()); 199 db.set_crate_graph(Default::default());
@@ -208,19 +206,12 @@ impl salsa::ParallelDatabase for MockDatabase {
208 salsa::Snapshot::new(MockDatabase { 206 salsa::Snapshot::new(MockDatabase {
209 events: Default::default(), 207 events: Default::default(),
210 runtime: self.runtime.snapshot(self), 208 runtime: self.runtime.snapshot(self),
211 interner: Arc::clone(&self.interner),
212 // only the root database can be used to get file_id by path. 209 // only the root database can be used to get file_id by path.
213 files: FxHashMap::default(), 210 files: FxHashMap::default(),
214 }) 211 })
215 } 212 }
216} 213}
217 214
218impl AsRef<HirInterner> for MockDatabase {
219 fn as_ref(&self) -> &HirInterner {
220 &self.interner
221 }
222}
223
224impl MockDatabase { 215impl MockDatabase {
225 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { 216 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
226 *self.events.lock() = Some(Vec::new()); 217 *self.events.lock() = Some(Vec::new());
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 4ae04514a..0eddfab12 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -75,7 +75,7 @@ pub(crate) use self::raw::{RawItems, ImportSourceMap};
75 75
76pub use self::{ 76pub use self::{
77 per_ns::{PerNs, Namespace}, 77 per_ns::{PerNs, Namespace},
78 raw::{ImportId, ImportSource}, 78 raw::ImportId,
79}; 79};
80 80
81/// Contans all top-level defs from a macro-expanded crate 81/// Contans all top-level defs from a macro-expanded crate
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index b7416ede6..43c97a0bf 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -12,7 +12,7 @@ use ra_syntax::{
12 12
13use crate::{ 13use crate::{
14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, 14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
15 AstIdMap, FileAstId, 15 AstIdMap, FileAstId, Either,
16}; 16};
17 17
18/// `RawItems` is a set of top-level items in a file (except for impls). 18/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -34,28 +34,15 @@ pub struct ImportSourceMap {
34 map: ArenaMap<ImportId, ImportSourcePtr>, 34 map: ArenaMap<ImportId, ImportSourcePtr>,
35} 35}
36 36
37#[derive(Debug, PartialEq, Eq, Clone, Copy)] 37type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
38enum ImportSourcePtr { 38type ImportSource = Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>>;
39 UseTree(AstPtr<ast::UseTree>),
40 ExternCrate(AstPtr<ast::ExternCrateItem>),
41}
42 39
43impl ImportSourcePtr { 40impl ImportSourcePtr {
44 fn to_node(self, file: &SourceFile) -> ImportSource { 41 fn to_node(self, file: &SourceFile) -> ImportSource {
45 match self { 42 self.map(|ptr| ptr.to_node(file).to_owned(), |ptr| ptr.to_node(file).to_owned())
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 } 43 }
52} 44}
53 45
54pub enum ImportSource {
55 UseTree(TreeArc<ast::UseTree>),
56 ExternCrate(TreeArc<ast::ExternCrateItem>),
57}
58
59impl ImportSourceMap { 46impl ImportSourceMap {
60 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 47 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
61 self.map.insert(import, ptr) 48 self.map.insert(import, ptr)
@@ -281,11 +268,7 @@ impl RawItemsCollector {
281 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| { 268 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
282 let import_data = 269 let import_data =
283 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false }; 270 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false };
284 self.push_import( 271 self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree)));
285 current_module,
286 import_data,
287 ImportSourcePtr::UseTree(AstPtr::new(use_tree)),
288 );
289 }) 272 })
290 } 273 }
291 274
@@ -304,11 +287,7 @@ impl RawItemsCollector {
304 is_prelude: false, 287 is_prelude: false,
305 is_extern_crate: true, 288 is_extern_crate: true,
306 }; 289 };
307 self.push_import( 290 self.push_import(current_module, import_data, Either::B(AstPtr::new(extern_crate)));
308 current_module,
309 import_data,
310 ImportSourcePtr::ExternCrate(AstPtr::new(extern_crate)),
311 );
312 } 291 }
313 } 292 }
314 293
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 2609585b1..685f4b8b1 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -9,13 +9,13 @@ use crate::{
9 name::{Name, KnownName}, 9 name::{Name, KnownName},
10 nameres::{PerNs, CrateDefMap, CrateModuleId}, 10 nameres::{PerNs, CrateDefMap, CrateModuleId},
11 generics::GenericParams, 11 generics::GenericParams,
12 expr::{scope::{ExprScopes, ScopeId}, PatId, Body}, 12 expr::{scope::{ExprScopes, ScopeId}, PatId},
13 impl_block::ImplBlock, 13 impl_block::ImplBlock,
14 path::Path, Trait 14 path::Path, Trait
15}; 15};
16 16
17#[derive(Debug, Clone, Default)] 17#[derive(Debug, Clone, Default)]
18pub struct Resolver { 18pub(crate) struct Resolver {
19 scopes: Vec<Scope>, 19 scopes: Vec<Scope>,
20} 20}
21 21
@@ -117,7 +117,7 @@ pub enum Resolution {
117} 117}
118 118
119impl Resolver { 119impl Resolver {
120 pub fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> { 120 pub(crate) fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> {
121 let mut resolution = PerNs::none(); 121 let mut resolution = PerNs::none();
122 for scope in self.scopes.iter().rev() { 122 for scope in self.scopes.iter().rev() {
123 resolution = resolution.or(scope.resolve_name(db, name)); 123 resolution = resolution.or(scope.resolve_name(db, name));
@@ -154,12 +154,12 @@ impl Resolver {
154 154
155 /// Returns the fully resolved path if we were able to resolve it. 155 /// Returns the fully resolved path if we were able to resolve it.
156 /// otherwise returns `PerNs::none` 156 /// otherwise returns `PerNs::none`
157 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> { 157 pub(crate) fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> {
158 // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise 158 // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise
159 self.resolve_path_segments(db, path).into_fully_resolved() 159 self.resolve_path_segments(db, path).into_fully_resolved()
160 } 160 }
161 161
162 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> { 162 pub(crate) fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> {
163 let mut names = FxHashMap::default(); 163 let mut names = FxHashMap::default();
164 for scope in self.scopes.iter().rev() { 164 for scope in self.scopes.iter().rev() {
165 scope.collect_names(db, &mut |name, res| { 165 scope.collect_names(db, &mut |name, res| {
@@ -197,14 +197,6 @@ impl Resolver {
197 _ => None, 197 _ => None,
198 }) 198 })
199 } 199 }
200
201 /// The body from which any `LocalBinding` resolutions in this resolver come.
202 pub fn body(&self) -> Option<Arc<Body>> {
203 self.scopes.iter().rev().find_map(|scope| match scope {
204 Scope::ExprScope(expr_scope) => Some(expr_scope.expr_scopes.body()),
205 _ => None,
206 })
207 }
208} 200}
209 201
210impl Resolver { 202impl Resolver {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 182ed4c91..bd035ced9 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -5,16 +5,21 @@
5/// 5///
6/// So, this modules should not be used during hir construction, it exists 6/// So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs". 7/// purely for "IDE needs".
8use std::sync::Arc;
9
10use rustc_hash::{FxHashSet, FxHashMap};
8use ra_db::{FileId, FilePosition}; 11use ra_db::{FileId, FilePosition};
9use ra_syntax::{ 12use ra_syntax::{
10 SyntaxNode, 13 SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange,
11 ast::{self, AstNode, NameOwner}, 14 ast::{self, AstNode, NameOwner},
12 algo::{find_node_at_offset, find_token_at_offset}, 15 algo::find_node_at_offset,
16 SyntaxKind::*,
13}; 17};
14 18
15use crate::{ 19use crate::{
16 HirDatabase, Function, Struct, Enum,Const,Static, 20 HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name,
17 AsName, Module, HirFileId, Crate, Trait, Resolver, 21 AsName, Module, HirFileId, Crate, Trait, Resolver,
22 expr::{BodySourceMap, scope::{ScopeId, ExprScopes}},
18 ids::LocationCtx, 23 ids::LocationCtx,
19 expr, AstId 24 expr, AstId
20}; 25};
@@ -87,63 +92,6 @@ fn module_from_source(
87 ) 92 )
88} 93}
89 94
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
111pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
112 let file = db.parse(position.file_id);
113 let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
114 function_from_source(db, position.file_id, fn_def)
115}
116
117pub fn function_from_source(
118 db: &impl HirDatabase,
119 file_id: FileId,
120 fn_def: &ast::FnDef,
121) -> Option<Function> {
122 let module = module_from_child_node(db, file_id, fn_def.syntax())?;
123 let res = function_from_module(db, module, fn_def);
124 Some(res)
125}
126
127pub fn function_from_module(
128 db: &impl HirDatabase,
129 module: Module,
130 fn_def: &ast::FnDef,
131) -> Function {
132 let (file_id, _) = module.definition_source(db);
133 let file_id = file_id.into();
134 let ctx = LocationCtx::new(db, module, file_id);
135 Function { id: ctx.to_def(fn_def) }
136}
137
138pub fn function_from_child_node(
139 db: &impl HirDatabase,
140 file_id: FileId,
141 node: &SyntaxNode,
142) -> Option<Function> {
143 let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
144 function_from_source(db, file_id, fn_def)
145}
146
147pub fn struct_from_module( 95pub fn struct_from_module(
148 db: &impl HirDatabase, 96 db: &impl HirDatabase,
149 module: Module, 97 module: Module,
@@ -155,27 +103,6 @@ pub fn struct_from_module(
155 Struct { id: ctx.to_def(struct_def) } 103 Struct { id: ctx.to_def(struct_def) }
156} 104}
157 105
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
179pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { 106pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
180 let (file_id, _) = module.definition_source(db); 107 let (file_id, _) = module.definition_source(db);
181 let file_id = file_id.into(); 108 let file_id = file_id.into();
@@ -194,48 +121,6 @@ pub fn trait_from_module(
194 Trait { id: ctx.to_def(trait_def) } 121 Trait { id: ctx.to_def(trait_def) }
195} 122}
196 123
197pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver {
198 let file_id = position.file_id;
199 let file = db.parse(file_id);
200 find_token_at_offset(file.syntax(), position.offset)
201 .find_map(|token| {
202 token.parent().ancestors().find_map(|node| {
203 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
204 if let Some(func) = function_from_child_node(db, file_id, node) {
205 let scopes = func.scopes(db);
206 let scope = scopes.scope_for_offset(position.offset);
207 Some(expr::resolver_for_scope(func.body(db), db, scope))
208 } else {
209 // FIXME const/static/array length
210 None
211 }
212 } else {
213 try_get_resolver_for_node(db, file_id, node)
214 }
215 })
216 })
217 .unwrap_or_default()
218}
219
220pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver {
221 node.ancestors()
222 .find_map(|node| {
223 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
224 if let Some(func) = function_from_child_node(db, file_id, node) {
225 let scopes = func.scopes(db);
226 let scope = scopes.scope_for(&node);
227 Some(expr::resolver_for_scope(func.body(db), db, scope))
228 } else {
229 // FIXME const/static/array length
230 None
231 }
232 } else {
233 try_get_resolver_for_node(db, file_id, node)
234 }
235 })
236 .unwrap_or_default()
237}
238
239fn try_get_resolver_for_node( 124fn try_get_resolver_for_node(
240 db: &impl HirDatabase, 125 db: &impl HirDatabase,
241 file_id: FileId, 126 file_id: FileId,
@@ -251,10 +136,281 @@ fn try_get_resolver_for_node(
251 } else if let Some(e) = ast::EnumDef::cast(node) { 136 } else if let Some(e) = ast::EnumDef::cast(node) {
252 let module = module_from_child_node(db, file_id, e.syntax())?; 137 let module = module_from_child_node(db, file_id, e.syntax())?;
253 Some(enum_from_module(db, module, e).resolver(db)) 138 Some(enum_from_module(db, module, e).resolver(db))
254 } else if let Some(f) = ast::FnDef::cast(node) { 139 } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
255 function_from_source(db, file_id, f).map(|f| f.resolver(db)) 140 Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db))
256 } else { 141 } else {
257 // FIXME add missing cases 142 // FIXME add missing cases
258 None 143 None
259 } 144 }
260} 145}
146
147fn def_with_body_from_child_node(
148 db: &impl HirDatabase,
149 file_id: FileId,
150 node: &SyntaxNode,
151) -> Option<DefWithBody> {
152 let module = module_from_child_node(db, file_id, node)?;
153 let ctx = LocationCtx::new(db, module, file_id.into());
154 node.ancestors().find_map(|node| {
155 if let Some(def) = ast::FnDef::cast(node) {
156 return Some(Function { id: ctx.to_def(def) }.into());
157 }
158 if let Some(def) = ast::ConstDef::cast(node) {
159 return Some(Const { id: ctx.to_def(def) }.into());
160 }
161 if let Some(def) = ast::StaticDef::cast(node) {
162 return Some(Static { id: ctx.to_def(def) }.into());
163 }
164 None
165 })
166}
167
168/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
169/// original source files. It should not be used inside the HIR itself.
170#[derive(Debug)]
171pub struct SourceAnalyzer {
172 resolver: Resolver,
173 body_source_map: Option<Arc<BodySourceMap>>,
174 infer: Option<Arc<crate::ty::InferenceResult>>,
175 scopes: Option<Arc<crate::expr::ExprScopes>>,
176}
177
178#[derive(Debug, Clone, PartialEq, Eq)]
179pub enum PathResolution {
180 /// An item
181 Def(crate::ModuleDef),
182 /// A local binding (only value namespace)
183 LocalBinding(Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>),
184 /// A generic parameter
185 GenericParam(u32),
186 SelfType(crate::ImplBlock),
187 AssocItem(crate::ImplItem),
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct ScopeEntryWithSyntax {
192 pub(crate) name: Name,
193 pub(crate) ptr: Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>,
194}
195
196impl ScopeEntryWithSyntax {
197 pub fn name(&self) -> &Name {
198 &self.name
199 }
200
201 pub fn ptr(&self) -> Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>> {
202 self.ptr
203 }
204}
205
206#[derive(Debug)]
207pub struct ReferenceDescriptor {
208 pub range: TextRange,
209 pub name: String,
210}
211
212impl SourceAnalyzer {
213 pub fn new(
214 db: &impl HirDatabase,
215 file_id: FileId,
216 node: &SyntaxNode,
217 offset: Option<TextUnit>,
218 ) -> SourceAnalyzer {
219 let def_with_body = def_with_body_from_child_node(db, file_id, node);
220 if let Some(def) = def_with_body {
221 let source_map = def.body_source_map(db);
222 let scopes = db.expr_scopes(def);
223 let scope = match offset {
224 None => scope_for(&scopes, &source_map, &node),
225 Some(offset) => scope_for_offset(&scopes, &source_map, offset),
226 };
227 let resolver = expr::resolver_for_scope(def.body(db), db, scope);
228 SourceAnalyzer {
229 resolver,
230 body_source_map: Some(source_map),
231 infer: Some(def.infer(db)),
232 scopes: Some(scopes),
233 }
234 } else {
235 SourceAnalyzer {
236 resolver: node
237 .ancestors()
238 .find_map(|node| try_get_resolver_for_node(db, file_id, node))
239 .unwrap_or_default(),
240 body_source_map: None,
241 infer: None,
242 scopes: None,
243 }
244 }
245 }
246
247 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> {
248 let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?;
249 Some(self.infer.as_ref()?[expr_id].clone())
250 }
251
252 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> {
253 let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?;
254 Some(self.infer.as_ref()?[pat_id].clone())
255 }
256
257 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
258 let expr_id = self.body_source_map.as_ref()?.node_expr(call.into())?;
259 self.infer.as_ref()?.method_resolution(expr_id)
260 }
261
262 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
263 let expr_id = self.body_source_map.as_ref()?.node_expr(field.into())?;
264 self.infer.as_ref()?.field_resolution(expr_id)
265 }
266
267 pub fn resolve_hir_path(
268 &self,
269 db: &impl HirDatabase,
270 path: &crate::Path,
271 ) -> PerNs<crate::Resolution> {
272 self.resolver.resolve_path(db, path)
273 }
274
275 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
276 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
277 let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?;
278 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
279 return Some(PathResolution::AssocItem(assoc));
280 }
281 }
282 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
283 let pat_id = self.body_source_map.as_ref()?.node_pat(path_pat.into())?;
284 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
285 return Some(PathResolution::AssocItem(assoc));
286 }
287 }
288 let hir_path = crate::Path::from_ast(path)?;
289 let res = self.resolver.resolve_path(db, &hir_path);
290 let res = res.clone().take_types().or_else(|| res.take_values())?;
291 let res = match res {
292 crate::Resolution::Def(it) => PathResolution::Def(it),
293 crate::Resolution::LocalBinding(it) => {
294 PathResolution::LocalBinding(self.body_source_map.as_ref()?.pat_syntax(it)?)
295 }
296 crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),
297 crate::Resolution::SelfType(it) => PathResolution::SelfType(it),
298 };
299 Some(res)
300 }
301
302 pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> {
303 let mut shadowed = FxHashSet::default();
304 let name = name_ref.as_name();
305 let source_map = self.body_source_map.as_ref()?;
306 let scopes = self.scopes.as_ref()?;
307 let scope = scope_for(scopes, source_map, name_ref.syntax());
308 let ret = scopes
309 .scope_chain(scope)
310 .flat_map(|scope| scopes.entries(scope).iter())
311 .filter(|entry| shadowed.insert(entry.name()))
312 .filter(|entry| entry.name() == &name)
313 .nth(0);
314 ret.and_then(|entry| {
315 Some(ScopeEntryWithSyntax {
316 name: entry.name().clone(),
317 ptr: source_map.pat_syntax(entry.pat())?,
318 })
319 })
320 }
321
322 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<crate::Resolution>> {
323 self.resolver.all_names(db)
324 }
325
326 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
327 // FIXME: at least, this should work with any DefWithBody, but ideally
328 // this should be hir-based altogether
329 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
330 let ptr = Either::A(AstPtr::new(pat.into()));
331 fn_def
332 .syntax()
333 .descendants()
334 .filter_map(ast::NameRef::cast)
335 .filter(|name_ref| match self.resolve_local_name(*name_ref) {
336 None => false,
337 Some(entry) => entry.ptr() == ptr,
338 })
339 .map(|name_ref| ReferenceDescriptor {
340 name: name_ref.text().to_string(),
341 range: name_ref.syntax().range(),
342 })
343 .collect()
344 }
345
346 #[cfg(test)]
347 pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> {
348 self.body_source_map.clone().unwrap()
349 }
350
351 #[cfg(test)]
352 pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
353 self.infer.clone().unwrap()
354 }
355
356 #[cfg(test)]
357 pub(crate) fn scopes(&self) -> Arc<ExprScopes> {
358 self.scopes.clone().unwrap()
359 }
360}
361
362fn scope_for(
363 scopes: &ExprScopes,
364 source_map: &BodySourceMap,
365 node: &SyntaxNode,
366) -> Option<ScopeId> {
367 node.ancestors()
368 .map(SyntaxNodePtr::new)
369 .filter_map(|ptr| source_map.syntax_expr(ptr))
370 .find_map(|it| scopes.scope_for(it))
371}
372
373fn scope_for_offset(
374 scopes: &ExprScopes,
375 source_map: &BodySourceMap,
376 offset: TextUnit,
377) -> Option<ScopeId> {
378 scopes
379 .scope_by_expr()
380 .iter()
381 .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope)))
382 // find containing scope
383 .min_by_key(|(ptr, _scope)| {
384 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len())
385 })
386 .map(|(ptr, scope)| adjust(scopes, source_map, ptr, offset).unwrap_or(*scope))
387}
388
389// XXX: during completion, cursor might be outside of any particular
390// expression. Try to figure out the correct scope...
391fn adjust(
392 scopes: &ExprScopes,
393 source_map: &BodySourceMap,
394 ptr: SyntaxNodePtr,
395 offset: TextUnit,
396) -> Option<ScopeId> {
397 let r = ptr.range();
398 let child_scopes = scopes
399 .scope_by_expr()
400 .iter()
401 .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope)))
402 .map(|(ptr, scope)| (ptr.range(), scope))
403 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
404
405 child_scopes
406 .max_by(|(r1, _), (r2, _)| {
407 if r2.is_subrange(&r1) {
408 std::cmp::Ordering::Greater
409 } else if r1.is_subrange(&r2) {
410 std::cmp::Ordering::Less
411 } else {
412 r1.start().cmp(&r2.start())
413 }
414 })
415 .map(|(_ptr, scope)| *scope)
416}
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
index 725bdd5cb..15f0977b7 100644
--- a/crates/ra_hir/src/traits.rs
+++ b/crates/ra_hir/src/traits.rs
@@ -1,10 +1,11 @@
1//! HIR for trait definitions. 1//! HIR for trait definitions.
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4use rustc_hash::FxHashMap;
4 5
5use ra_syntax::ast::{self, NameOwner}; 6use ra_syntax::ast::{self, NameOwner};
6 7
7use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName}; 8use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName, Module};
8 9
9#[derive(Debug, Clone, PartialEq, Eq)] 10#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct TraitData { 11pub struct TraitData {
@@ -49,4 +50,34 @@ pub enum TraitItem {
49 TypeAlias(TypeAlias), 50 TypeAlias(TypeAlias),
50 // Existential 51 // Existential
51} 52}
53// FIXME: not every function, ... is actually a trait item. maybe we should make
54// sure that you can only turn actual trait items into TraitItems. This would
55// require not implementing From, and instead having some checked way of
56// casting them.
52impl_froms!(TraitItem: Function, Const, TypeAlias); 57impl_froms!(TraitItem: Function, Const, TypeAlias);
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct TraitItemsIndex {
61 traits_by_def: FxHashMap<TraitItem, Trait>,
62}
63
64impl TraitItemsIndex {
65 pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex {
66 let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
67 for decl in module.declarations(db) {
68 match decl {
69 crate::ModuleDef::Trait(tr) => {
70 for item in tr.trait_data(db).items() {
71 index.traits_by_def.insert(*item, tr);
72 }
73 }
74 _ => {}
75 }
76 }
77 index
78 }
79
80 pub(crate) fn get_parent_trait(&self, item: TraitItem) -> Option<Trait> {
81 self.traits_by_def.get(&item).cloned()
82 }
83}
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 20e55d92d..12e10c751 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -5,6 +5,7 @@ mod autoderef;
5pub(crate) mod primitive; 5pub(crate) mod primitive;
6#[cfg(test)] 6#[cfg(test)]
7mod tests; 7mod tests;
8pub(crate) mod traits;
8pub(crate) mod method_resolution; 9pub(crate) mod method_resolution;
9mod op; 10mod op;
10mod lower; 11mod lower;
@@ -15,10 +16,11 @@ use std::sync::Arc;
15use std::{fmt, mem}; 16use std::{fmt, mem};
16 17
17use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait}; 18use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait};
19use display::{HirDisplay, HirFormatter};
18 20
19pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig}; 21pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig};
20pub(crate) use infer::{infer, InferenceResult, InferTy}; 22pub(crate) use infer::{infer, InferenceResult, InferTy};
21use display::{HirDisplay, HirFormatter}; 23pub use lower::CallableDef;
22 24
23/// A type constructor or type name: this might be something like the primitive 25/// A type constructor or type name: this might be something like the primitive
24/// type `bool`, a struct like `Vec`, or things like function pointers or 26/// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -144,6 +146,10 @@ impl Substs {
144 Substs(Arc::new([ty])) 146 Substs(Arc::new([ty]))
145 } 147 }
146 148
149 pub fn prefix(&self, n: usize) -> Substs {
150 Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into())
151 }
152
147 pub fn iter(&self) -> impl Iterator<Item = &Ty> { 153 pub fn iter(&self) -> impl Iterator<Item = &Ty> {
148 self.0.iter() 154 self.0.iter()
149 } 155 }
@@ -169,6 +175,12 @@ impl Substs {
169 } 175 }
170} 176}
171 177
178impl From<Vec<Ty>> for Substs {
179 fn from(v: Vec<Ty>) -> Self {
180 Substs(v.into())
181 }
182}
183
172/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. 184/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
173/// Name to be bikeshedded: TraitBound? TraitImplements? 185/// Name to be bikeshedded: TraitBound? TraitImplements?
174#[derive(Clone, PartialEq, Eq, Debug, Hash)] 186#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -209,6 +221,14 @@ impl FnSig {
209 &self.params_and_return[self.params_and_return.len() - 1] 221 &self.params_and_return[self.params_and_return.len() - 1]
210 } 222 }
211 223
224 /// Applies the given substitutions to all types in this signature and
225 /// returns the result.
226 pub fn subst(&self, substs: &Substs) -> FnSig {
227 let result: Vec<_> =
228 self.params_and_return.iter().map(|ty| ty.clone().subst(substs)).collect();
229 FnSig { params_and_return: result.into() }
230 }
231
212 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 232 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
213 // Without an Arc::make_mut_slice, we can't avoid the clone here: 233 // Without an Arc::make_mut_slice, we can't avoid the clone here:
214 let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); 234 let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
@@ -288,6 +308,15 @@ impl Ty {
288 } 308 }
289 } 309 }
290 310
311 pub fn as_callable(&self) -> Option<(CallableDef, &Substs)> {
312 match self {
313 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => {
314 Some((*callable_def, parameters))
315 }
316 _ => None,
317 }
318 }
319
291 fn builtin_deref(&self) -> Option<Ty> { 320 fn builtin_deref(&self) -> Option<Ty> {
292 match self { 321 match self {
293 Ty::Apply(a_ty) => match a_ty.ctor { 322 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -299,6 +328,20 @@ impl Ty {
299 } 328 }
300 } 329 }
301 330
331 fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
332 match self {
333 Ty::Apply(a_ty) => match a_ty.ctor {
334 TypeCtor::FnPtr => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
335 TypeCtor::FnDef(def) => {
336 let sig = db.callable_item_signature(def);
337 Some(sig.subst(&a_ty.parameters))
338 }
339 _ => None,
340 },
341 _ => None,
342 }
343 }
344
302 /// If this is a type with type parameters (an ADT or function), replaces 345 /// If this is a type with type parameters (an ADT or function), replaces
303 /// the `Substs` for these type parameters with the given ones. (So e.g. if 346 /// the `Substs` for these type parameters with the given ones. (So e.g. if
304 /// `self` is `Option<_>` and the substs contain `u32`, we'll have 347 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index ab5f008ef..a442a856c 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -3,7 +3,7 @@
3//! reference to a type with the field `bar`. This is an approximation of the 3//! reference to a type with the field `bar`. This is an approximation of the
4//! logic in rustc (which lives in librustc_typeck/check/autoderef.rs). 4//! logic in rustc (which lives in librustc_typeck/check/autoderef.rs).
5 5
6use ra_syntax::algo::generate; 6use std::iter::successors;
7 7
8use crate::HirDatabase; 8use crate::HirDatabase;
9use super::Ty; 9use super::Ty;
@@ -11,7 +11,7 @@ use super::Ty;
11impl Ty { 11impl Ty {
12 /// Iterates over the possible derefs of `ty`. 12 /// Iterates over the possible derefs of `ty`.
13 pub fn autoderef<'a>(self, db: &'a impl HirDatabase) -> impl Iterator<Item = Ty> + 'a { 13 pub fn autoderef<'a>(self, db: &'a impl HirDatabase) -> impl Iterator<Item = Ty> + 'a {
14 generate(Some(self), move |ty| ty.autoderef_step(db)) 14 successors(Some(self), move |ty| ty.autoderef_step(db))
15 } 15 }
16 16
17 fn autoderef_step(&self, _db: &impl HirDatabase) -> Option<Ty> { 17 fn autoderef_step(&self, _db: &impl HirDatabase) -> Option<Ty> {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 28947be51..651a78fe5 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -20,9 +20,9 @@ use std::sync::Arc;
20use std::mem; 20use std::mem;
21 21
22use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; 22use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError};
23use ra_arena::map::ArenaMap;
24use rustc_hash::FxHashMap; 23use rustc_hash::FxHashMap;
25 24
25use ra_arena::map::ArenaMap;
26use test_utils::tested_by; 26use test_utils::tested_by;
27 27
28use crate::{ 28use crate::{
@@ -33,15 +33,18 @@ use crate::{
33 ImplItem, 33 ImplItem,
34 type_ref::{TypeRef, Mutability}, 34 type_ref::{TypeRef, Mutability},
35 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self}, 35 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self},
36 generics::GenericParams, 36 generics::{GenericParams, HasGenericParams},
37 path::{GenericArgs, GenericArg}, 37 path::{GenericArgs, GenericArg},
38 adt::VariantDef, 38 adt::VariantDef,
39 resolve::{Resolver, Resolution}, 39 resolve::{Resolver, Resolution},
40 nameres::Namespace, 40 nameres::Namespace,
41 ty::infer::diagnostics::InferenceDiagnostic,
42 diagnostics::DiagnosticSink, 41 diagnostics::DiagnosticSink,
43}; 42};
44use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; 43use super::{
44 Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef,
45 traits::{ Solution, Obligation, Guidance},
46};
47use self::diagnostics::InferenceDiagnostic;
45 48
46/// The entry point of type inference. 49/// The entry point of type inference.
47pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 50pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
@@ -153,6 +156,7 @@ struct InferenceContext<'a, D: HirDatabase> {
153 body: Arc<Body>, 156 body: Arc<Body>,
154 resolver: Resolver, 157 resolver: Resolver,
155 var_unification_table: InPlaceUnificationTable<TypeVarId>, 158 var_unification_table: InPlaceUnificationTable<TypeVarId>,
159 obligations: Vec<Obligation>,
156 method_resolutions: FxHashMap<ExprId, Function>, 160 method_resolutions: FxHashMap<ExprId, Function>,
157 field_resolutions: FxHashMap<ExprId, StructField>, 161 field_resolutions: FxHashMap<ExprId, StructField>,
158 assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, 162 assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>,
@@ -173,6 +177,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
173 type_of_pat: ArenaMap::default(), 177 type_of_pat: ArenaMap::default(),
174 diagnostics: Vec::default(), 178 diagnostics: Vec::default(),
175 var_unification_table: InPlaceUnificationTable::new(), 179 var_unification_table: InPlaceUnificationTable::new(),
180 obligations: Vec::default(),
176 return_ty: Ty::Unknown, // set in collect_fn_signature 181 return_ty: Ty::Unknown, // set in collect_fn_signature
177 db, 182 db,
178 body, 183 body,
@@ -181,6 +186,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
181 } 186 }
182 187
183 fn resolve_all(mut self) -> InferenceResult { 188 fn resolve_all(mut self) -> InferenceResult {
189 // FIXME resolve obligations as well (use Guidance if necessary)
184 let mut tv_stack = Vec::new(); 190 let mut tv_stack = Vec::new();
185 let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); 191 let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default());
186 for ty in expr_types.values_mut() { 192 for ty in expr_types.values_mut() {
@@ -311,11 +317,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
311 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) 317 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty))
312 } 318 }
313 319
320 fn resolve_obligations_as_possible(&mut self) {
321 let obligations = mem::replace(&mut self.obligations, Vec::new());
322 for obligation in obligations {
323 // FIXME resolve types in the obligation first
324 let (solution, var_mapping) = match &obligation {
325 Obligation::Trait(tr) => {
326 let (tr, var_mapping) = super::traits::canonicalize(tr.clone());
327 (self.db.implements(tr), var_mapping)
328 }
329 };
330 match solution {
331 Some(Solution::Unique(substs)) => {
332 for (i, subst) in substs.0.iter().enumerate() {
333 let uncanonical = var_mapping[i];
334 // FIXME the subst may contain type variables, which would need to be mapped back as well
335 self.unify(&Ty::Infer(InferTy::TypeVar(uncanonical)), subst);
336 }
337 }
338 Some(Solution::Ambig(Guidance::Definite(substs))) => {
339 for (i, subst) in substs.0.iter().enumerate() {
340 let uncanonical = var_mapping[i];
341 // FIXME the subst may contain type variables, which would need to be mapped back as well
342 self.unify(&Ty::Infer(InferTy::TypeVar(uncanonical)), subst);
343 }
344 self.obligations.push(obligation);
345 }
346 Some(_) => {
347 self.obligations.push(obligation);
348 }
349 None => {
350 // FIXME obligation cannot be fulfilled => diagnostic
351 }
352 }
353 }
354 }
355
314 /// Resolves the type as far as currently possible, replacing type variables 356 /// Resolves the type as far as currently possible, replacing type variables
315 /// by their known types. All types returned by the infer_* functions should 357 /// by their known types. All types returned by the infer_* functions should
316 /// be resolved as far as possible, i.e. contain no type variables with 358 /// be resolved as far as possible, i.e. contain no type variables with
317 /// known type. 359 /// known type.
318 fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 360 fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
361 self.resolve_obligations_as_possible();
362
319 ty.fold(&mut |ty| match ty { 363 ty.fold(&mut |ty| match ty {
320 Ty::Infer(tv) => { 364 Ty::Infer(tv) => {
321 let inner = tv.to_inner(); 365 let inner = tv.to_inner();
@@ -420,6 +464,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
420 for segment in &path.segments[remaining_index..] { 464 for segment in &path.segments[remaining_index..] {
421 let ty = match resolved { 465 let ty = match resolved {
422 Resolution::Def(def) => { 466 Resolution::Def(def) => {
467 // FIXME resolve associated items from traits as well
423 let typable: Option<TypableDef> = def.into(); 468 let typable: Option<TypableDef> = def.into();
424 let typable = typable?; 469 let typable = typable?;
425 470
@@ -709,13 +754,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
709 fn substs_for_method_call( 754 fn substs_for_method_call(
710 &mut self, 755 &mut self,
711 def_generics: Option<Arc<GenericParams>>, 756 def_generics: Option<Arc<GenericParams>>,
712 generic_args: &Option<GenericArgs>, 757 generic_args: Option<&GenericArgs>,
758 receiver_ty: &Ty,
713 ) -> Substs { 759 ) -> Substs {
714 let (parent_param_count, param_count) = 760 let (parent_param_count, param_count) =
715 def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); 761 def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len()));
716 let mut substs = Vec::with_capacity(parent_param_count + param_count); 762 let mut substs = Vec::with_capacity(parent_param_count + param_count);
717 for _ in 0..parent_param_count { 763 // Parent arguments are unknown, except for the receiver type
718 substs.push(Ty::Unknown); 764 if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) {
765 for param in &parent_generics.params {
766 if param.name.as_known_name() == Some(crate::KnownName::SelfType) {
767 substs.push(receiver_ty.clone());
768 } else {
769 substs.push(Ty::Unknown);
770 }
771 }
719 } 772 }
720 // handle provided type arguments 773 // handle provided type arguments
721 if let Some(generic_args) = generic_args { 774 if let Some(generic_args) = generic_args {
@@ -737,6 +790,83 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
737 Substs(substs.into()) 790 Substs(substs.into())
738 } 791 }
739 792
793 fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
794 match callable_ty {
795 Ty::Apply(a_ty) => match a_ty.ctor {
796 TypeCtor::FnDef(def) => {
797 // add obligation for trait implementation, if this is a trait method
798 // FIXME also register obligations from where clauses from the trait or impl and method
799 match def {
800 CallableDef::Function(f) => {
801 if let Some(trait_) = f.parent_trait(self.db) {
802 // construct a TraitDef
803 let substs = a_ty.parameters.prefix(
804 trait_.generic_params(self.db).count_params_including_parent(),
805 );
806 self.obligations
807 .push(Obligation::Trait(TraitRef { trait_, substs }));
808 }
809 }
810 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {}
811 }
812 }
813 _ => {}
814 },
815 _ => {}
816 }
817 }
818
819 fn infer_method_call(
820 &mut self,
821 tgt_expr: ExprId,
822 receiver: ExprId,
823 args: &[ExprId],
824 method_name: &Name,
825 generic_args: Option<&GenericArgs>,
826 ) -> Ty {
827 let receiver_ty = self.infer_expr(receiver, &Expectation::none());
828 let resolved = receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver);
829 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
830 Some((ty, func)) => {
831 self.write_method_resolution(tgt_expr, func);
832 (
833 ty,
834 self.db.type_for_def(func.into(), Namespace::Values),
835 Some(func.generic_params(self.db)),
836 )
837 }
838 None => (receiver_ty, Ty::Unknown, None),
839 };
840 let substs =
841 self.substs_for_method_call(def_generics.clone(), generic_args, &derefed_receiver_ty);
842 let method_ty = method_ty.apply_substs(substs);
843 let method_ty = self.insert_type_vars(method_ty);
844 self.register_obligations_for_call(&method_ty);
845 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) {
846 Some(sig) => {
847 if !sig.params().is_empty() {
848 (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
849 } else {
850 (Ty::Unknown, Vec::new(), sig.ret().clone())
851 }
852 }
853 None => (Ty::Unknown, Vec::new(), Ty::Unknown),
854 };
855 // Apply autoref so the below unification works correctly
856 // FIXME: return correct autorefs from lookup_method
857 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
858 Some((_, mutability)) => Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty),
859 _ => derefed_receiver_ty,
860 };
861 self.unify(&expected_receiver_ty, &actual_receiver_ty);
862
863 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
864 for (arg, param) in args.iter().zip(param_iter) {
865 self.infer_expr(*arg, &Expectation::has_type(param));
866 }
867 ret_ty
868 }
869
740 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 870 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
741 let body = Arc::clone(&self.body); // avoid borrow checker problem 871 let body = Arc::clone(&self.body); // avoid borrow checker problem
742 let ty = match &body[tgt_expr] { 872 let ty = match &body[tgt_expr] {
@@ -793,102 +923,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
793 } 923 }
794 Expr::Call { callee, args } => { 924 Expr::Call { callee, args } => {
795 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 925 let callee_ty = self.infer_expr(*callee, &Expectation::none());
796 let (param_tys, ret_ty) = match &callee_ty { 926 let (param_tys, ret_ty) = match callee_ty.callable_sig(self.db) {
797 Ty::Apply(a_ty) => match a_ty.ctor { 927 Some(sig) => (sig.params().to_vec(), sig.ret().clone()),
798 TypeCtor::FnPtr => { 928 None => {
799 let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); 929 // Not callable
800 (sig.params().to_vec(), sig.ret().clone()) 930 // FIXME: report an error
801 }
802 TypeCtor::FnDef(def) => {
803 let sig = self.db.callable_item_signature(def);
804 let ret_ty = sig.ret().clone().subst(&a_ty.parameters);
805 let param_tys = sig
806 .params()
807 .iter()
808 .map(|ty| ty.clone().subst(&a_ty.parameters))
809 .collect();
810 (param_tys, ret_ty)
811 }
812 _ => (Vec::new(), Ty::Unknown),
813 },
814 _ => {
815 // not callable
816 // FIXME report an error?
817 (Vec::new(), Ty::Unknown) 931 (Vec::new(), Ty::Unknown)
818 } 932 }
819 }; 933 };
934 // FIXME register obligations from where clauses from the function
820 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 935 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
821 for (arg, param) in args.iter().zip(param_iter) { 936 for (arg, param) in args.iter().zip(param_iter) {
822 self.infer_expr(*arg, &Expectation::has_type(param)); 937 self.infer_expr(*arg, &Expectation::has_type(param));
823 } 938 }
824 ret_ty 939 ret_ty
825 } 940 }
826 Expr::MethodCall { receiver, args, method_name, generic_args } => { 941 Expr::MethodCall { receiver, args, method_name, generic_args } => self
827 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 942 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()),
828 let resolved =
829 receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver);
830 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
831 Some((ty, func)) => {
832 self.write_method_resolution(tgt_expr, func);
833 (
834 ty,
835 self.db.type_for_def(func.into(), Namespace::Values),
836 Some(func.generic_params(self.db)),
837 )
838 }
839 None => (receiver_ty, Ty::Unknown, None),
840 };
841 let substs = self.substs_for_method_call(def_generics, generic_args);
842 let method_ty = method_ty.apply_substs(substs);
843 let method_ty = self.insert_type_vars(method_ty);
844 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
845 Ty::Apply(a_ty) => match a_ty.ctor {
846 TypeCtor::FnPtr => {
847 let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters);
848 if !sig.params().is_empty() {
849 (
850 sig.params()[0].clone(),
851 sig.params()[1..].to_vec(),
852 sig.ret().clone(),
853 )
854 } else {
855 (Ty::Unknown, Vec::new(), sig.ret().clone())
856 }
857 }
858 TypeCtor::FnDef(def) => {
859 let sig = self.db.callable_item_signature(def);
860 let ret_ty = sig.ret().clone().subst(&a_ty.parameters);
861
862 if !sig.params().is_empty() {
863 let mut params_iter = sig
864 .params()
865 .iter()
866 .map(|ty| ty.clone().subst(&a_ty.parameters));
867 let receiver_ty = params_iter.next().unwrap();
868 (receiver_ty, params_iter.collect(), ret_ty)
869 } else {
870 (Ty::Unknown, Vec::new(), ret_ty)
871 }
872 }
873 _ => (Ty::Unknown, Vec::new(), Ty::Unknown),
874 },
875 _ => (Ty::Unknown, Vec::new(), Ty::Unknown),
876 };
877 // Apply autoref so the below unification works correctly
878 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
879 Some((_, mutability)) => {
880 Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty)
881 }
882 _ => derefed_receiver_ty,
883 };
884 self.unify(&expected_receiver_ty, &actual_receiver_ty);
885
886 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
887 for (arg, param) in args.iter().zip(param_iter) {
888 self.infer_expr(*arg, &Expectation::has_type(param));
889 }
890 ret_ty
891 }
892 Expr::Match { expr, arms } => { 943 Expr::Match { expr, arms } => {
893 let expected = if expected.ty == Ty::Unknown { 944 let expected = if expected.ty == Ty::Unknown {
894 Expectation::has_type(self.new_type_var()) 945 Expectation::has_type(self.new_type_var())
@@ -1180,7 +1231,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1180 1231
1181/// The ID of a type variable. 1232/// The ID of a type variable.
1182#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 1233#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
1183pub struct TypeVarId(u32); 1234pub struct TypeVarId(pub(super) u32);
1184 1235
1185impl UnifyKey for TypeVarId { 1236impl UnifyKey for TypeVarId {
1186 type Value = TypeVarValue; 1237 type Value = TypeVarValue;
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 003a89f0d..7fac084ce 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -5,6 +5,7 @@
5//! - Building the type for an item: This happens through the `type_for_def` query. 5//! - Building the type for an item: This happens through the `type_for_def` query.
6//! 6//!
7//! This usually involves resolving names, collecting generic arguments etc. 7//! This usually involves resolving names, collecting generic arguments etc.
8use std::iter;
8 9
9use crate::{ 10use crate::{
10 Function, Struct, StructField, Enum, EnumVariant, Path, 11 Function, Struct, StructField, Enum, EnumVariant, Path,
@@ -15,11 +16,11 @@ use crate::{
15 name::KnownName, 16 name::KnownName,
16 nameres::Namespace, 17 nameres::Namespace,
17 resolve::{Resolver, Resolution}, 18 resolve::{Resolver, Resolution},
18 path::{ PathSegment, GenericArg}, 19 path::{PathSegment, GenericArg},
19 generics::GenericParams, 20 generics::{GenericParams, HasGenericParams},
20 adt::VariantDef, 21 adt::VariantDef, Trait
21}; 22};
22use super::{Ty, primitive, FnSig, Substs, TypeCtor}; 23use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef};
23 24
24impl Ty { 25impl Ty {
25 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 26 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
@@ -115,7 +116,6 @@ impl Ty {
115 segment: &PathSegment, 116 segment: &PathSegment,
116 resolved: TypableDef, 117 resolved: TypableDef,
117 ) -> Substs { 118 ) -> Substs {
118 let mut substs = Vec::new();
119 let def_generics = match resolved { 119 let def_generics = match resolved {
120 TypableDef::Function(func) => func.generic_params(db), 120 TypableDef::Function(func) => func.generic_params(db),
121 TypableDef::Struct(s) => s.generic_params(db), 121 TypableDef::Struct(s) => s.generic_params(db),
@@ -124,28 +124,7 @@ impl Ty {
124 TypableDef::TypeAlias(t) => t.generic_params(db), 124 TypableDef::TypeAlias(t) => t.generic_params(db),
125 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), 125 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(),
126 }; 126 };
127 let parent_param_count = def_generics.count_parent_params(); 127 substs_from_path_segment(db, resolver, segment, &def_generics, false)
128 substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
129 if let Some(generic_args) = &segment.args_and_bindings {
130 // if args are provided, it should be all of them, but we can't rely on that
131 let param_count = def_generics.params.len();
132 for arg in generic_args.args.iter().take(param_count) {
133 match arg {
134 GenericArg::Type(type_ref) => {
135 let ty = Ty::from_hir(db, resolver, type_ref);
136 substs.push(ty);
137 }
138 }
139 }
140 }
141 // add placeholders for args that were not provided
142 // FIXME: handle defaults
143 let supplied_params = substs.len();
144 for _ in supplied_params..def_generics.count_params_including_parent() {
145 substs.push(Ty::Unknown);
146 }
147 assert_eq!(substs.len(), def_generics.count_params_including_parent());
148 Substs(substs.into())
149 } 128 }
150 129
151 /// Collect generic arguments from a path into a `Substs`. See also 130 /// Collect generic arguments from a path into a `Substs`. See also
@@ -185,6 +164,82 @@ impl Ty {
185 } 164 }
186} 165}
187 166
167pub(super) fn substs_from_path_segment(
168 db: &impl HirDatabase,
169 resolver: &Resolver,
170 segment: &PathSegment,
171 def_generics: &GenericParams,
172 add_self_param: bool,
173) -> Substs {
174 let mut substs = Vec::new();
175 let parent_param_count = def_generics.count_parent_params();
176 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
177 if add_self_param {
178 // FIXME this add_self_param argument is kind of a hack: Traits have the
179 // Self type as an implicit first type parameter, but it can't be
180 // actually provided in the type arguments
181 // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`)
182 substs.push(Ty::Unknown);
183 }
184 if let Some(generic_args) = &segment.args_and_bindings {
185 // if args are provided, it should be all of them, but we can't rely on that
186 let self_param_correction = if add_self_param { 1 } else { 0 };
187 let param_count = def_generics.params.len() - self_param_correction;
188 for arg in generic_args.args.iter().take(param_count) {
189 match arg {
190 GenericArg::Type(type_ref) => {
191 let ty = Ty::from_hir(db, resolver, type_ref);
192 substs.push(ty);
193 }
194 }
195 }
196 }
197 // add placeholders for args that were not provided
198 // FIXME: handle defaults
199 let supplied_params = substs.len();
200 for _ in supplied_params..def_generics.count_params_including_parent() {
201 substs.push(Ty::Unknown);
202 }
203 assert_eq!(substs.len(), def_generics.count_params_including_parent());
204 Substs(substs.into())
205}
206
207impl TraitRef {
208 pub(crate) fn from_hir(
209 db: &impl HirDatabase,
210 resolver: &Resolver,
211 type_ref: &TypeRef,
212 explicit_self_ty: Option<Ty>,
213 ) -> Option<Self> {
214 let path = match type_ref {
215 TypeRef::Path(path) => path,
216 _ => return None,
217 };
218 let resolved = match resolver.resolve_path(db, &path).take_types()? {
219 Resolution::Def(ModuleDef::Trait(tr)) => tr,
220 _ => return None,
221 };
222 let mut substs = Self::substs_from_path(db, resolver, path, resolved);
223 if let Some(self_ty) = explicit_self_ty {
224 // FIXME this could be nicer
225 let mut substs_vec = substs.0.to_vec();
226 substs_vec[0] = self_ty;
227 substs.0 = substs_vec.into();
228 }
229 Some(TraitRef { trait_: resolved, substs })
230 }
231
232 fn substs_from_path(
233 db: &impl HirDatabase,
234 resolver: &Resolver,
235 path: &Path,
236 resolved: Trait,
237 ) -> Substs {
238 let segment = path.segments.last().expect("path should have at least one segment");
239 substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true)
240 }
241}
242
188/// Build the declared type of an item. This depends on the namespace; e.g. for 243/// Build the declared type of an item. This depends on the namespace; e.g. for
189/// `struct Foo(usize)`, we have two types: The type of the struct itself, and 244/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
190/// the constructor function `(usize) -> Foo` which lives in the values 245/// the constructor function `(usize) -> Foo` which lives in the values
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 3ac8dc46b..6b7918187 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -10,10 +10,12 @@ use crate::{
10 HirDatabase, Module, Crate, Name, Function, Trait, 10 HirDatabase, Module, Crate, Name, Function, Trait,
11 impl_block::{ImplId, ImplBlock, ImplItem}, 11 impl_block::{ImplId, ImplBlock, ImplItem},
12 ty::{Ty, TypeCtor}, 12 ty::{Ty, TypeCtor},
13 nameres::CrateModuleId, resolve::Resolver, traits::TraitItem 13 nameres::CrateModuleId,
14 14 resolve::Resolver,
15 traits::TraitItem,
16 generics::HasGenericParams,
15}; 17};
16use super::{ TraitRef, Substs}; 18use super::{TraitRef, Substs};
17 19
18/// This is used as a key for indexing impls. 20/// This is used as a key for indexing impls.
19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 21#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -72,9 +74,9 @@ impl CrateImplBlocks {
72 74
73 let target_ty = impl_block.target_ty(db); 75 let target_ty = impl_block.target_ty(db);
74 76
75 if let Some(tr) = impl_block.target_trait(db) { 77 if let Some(tr) = impl_block.target_trait_ref(db) {
76 self.impls_by_trait 78 self.impls_by_trait
77 .entry(tr) 79 .entry(tr.trait_)
78 .or_insert_with(Vec::new) 80 .or_insert_with(Vec::new)
79 .push((module.module_id, impl_id)); 81 .push((module.module_id, impl_id));
80 } else { 82 } else {
@@ -108,20 +110,6 @@ impl CrateImplBlocks {
108 } 110 }
109} 111}
110 112
111/// Rudimentary check whether an impl exists for a given type and trait; this
112/// will actually be done by chalk.
113pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> bool {
114 // FIXME use all trait impls in the whole crate graph
115 let krate = trait_ref.trait_.module(db).krate(db);
116 let krate = match krate {
117 Some(krate) => krate,
118 None => return false,
119 };
120 let crate_impl_blocks = db.impls_in_crate(krate);
121 let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_);
122 impl_blocks.any(|impl_block| &impl_block.target_ty(db) == trait_ref.self_ty())
123}
124
125fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { 113fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
126 match ty { 114 match ty {
127 Ty::Apply(a_ty) => match a_ty.ctor { 115 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -135,13 +123,14 @@ fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
135impl Ty { 123impl Ty {
136 /// Look up the method with the given name, returning the actual autoderefed 124 /// Look up the method with the given name, returning the actual autoderefed
137 /// receiver type (but without autoref applied yet). 125 /// receiver type (but without autoref applied yet).
138 pub fn lookup_method( 126 pub(crate) fn lookup_method(
139 self, 127 self,
140 db: &impl HirDatabase, 128 db: &impl HirDatabase,
141 name: &Name, 129 name: &Name,
142 resolver: &Resolver, 130 resolver: &Resolver,
143 ) -> Option<(Ty, Function)> { 131 ) -> Option<(Ty, Function)> {
144 // FIXME: trait methods should be used before autoderefs 132 // FIXME: trait methods should be used before autoderefs
133 // (and we need to do autoderefs for trait method calls as well)
145 let inherent_method = self.clone().iterate_methods(db, |ty, f| { 134 let inherent_method = self.clone().iterate_methods(db, |ty, f| {
146 let sig = f.signature(db); 135 let sig = f.signature(db);
147 if sig.name() == name && sig.has_self_param() { 136 if sig.name() == name && sig.has_self_param() {
@@ -174,22 +163,15 @@ impl Ty {
174 } 163 }
175 } 164 }
176 } 165 }
177 // FIXME:
178 // - we might not actually be able to determine fully that the type
179 // implements the trait here; it's enough if we (well, Chalk) determine
180 // that it's possible.
181 // - when the trait method is picked, we need to register an
182 // 'obligation' somewhere so that we later check that it's really
183 // implemented
184 // - both points go for additional requirements from where clauses as
185 // well (in fact, the 'implements' condition could just be considered a
186 // 'where Self: Trait' clause)
187 candidates.retain(|(t, _m)| { 166 candidates.retain(|(t, _m)| {
188 let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) }; 167 let trait_ref =
189 db.implements(trait_ref) 168 TraitRef { trait_: *t, substs: fresh_substs_for_trait(db, *t, self.clone()) };
169 let (trait_ref, _) = super::traits::canonicalize(trait_ref);
170 db.implements(trait_ref).is_some()
190 }); 171 });
191 // FIXME if there's multiple candidates here, that's an ambiguity error 172 // FIXME if there's multiple candidates here, that's an ambiguity error
192 let (_chosen_trait, chosen_method) = candidates.first()?; 173 let (_chosen_trait, chosen_method) = candidates.first()?;
174 // FIXME return correct receiver type
193 Some((self.clone(), *chosen_method)) 175 Some((self.clone(), *chosen_method))
194 } 176 }
195 177
@@ -252,3 +234,17 @@ impl Ty {
252 None 234 None
253 } 235 }
254} 236}
237
238/// This creates Substs for a trait with the given Self type and type variables
239/// for all other parameters. This is kind of a hack since these aren't 'real'
240/// type variables; the resulting trait reference is just used for the
241/// preliminary method candidate check.
242fn fresh_substs_for_trait(db: &impl HirDatabase, tr: Trait, self_ty: Ty) -> Substs {
243 let mut substs = Vec::new();
244 let generics = tr.generic_params(db);
245 substs.push(self_ty);
246 substs.extend(generics.params_including_parent().into_iter().skip(1).enumerate().map(
247 |(i, _p)| Ty::Infer(super::infer::InferTy::TypeVar(super::infer::TypeVarId(i as u32))),
248 ));
249 substs.into()
250}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f6a325033..291bc9ae5 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -4,15 +4,15 @@ use std::fmt::Write;
4use insta::assert_snapshot_matches; 4use insta::assert_snapshot_matches;
5 5
6use ra_db::{SourceDatabase, salsa::Database, FilePosition}; 6use ra_db::{SourceDatabase, salsa::Database, FilePosition};
7use ra_syntax::{algo, ast::{self, AstNode}}; 7use ra_syntax::{algo, ast::{self, AstNode}, SyntaxKind::*};
8use test_utils::covers; 8use test_utils::covers;
9 9
10use crate::{ 10use crate::{
11 source_binder,
12 mock::MockDatabase, 11 mock::MockDatabase,
13 ty::display::HirDisplay, 12 ty::display::HirDisplay,
14 ty::InferenceResult, 13 ty::InferenceResult,
15 expr::BodySourceMap 14 expr::BodySourceMap,
15 SourceAnalyzer,
16}; 16};
17 17
18// 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
@@ -1862,14 +1862,14 @@ fn test() {
1862 @r###" 1862 @r###"
1863[49; 50) '0': u32 1863[49; 50) '0': u32
1864[80; 83) '101': u32 1864[80; 83) '101': u32
1865[126; 128) '99': u32
1866[95; 213) '{ ...NST; }': () 1865[95; 213) '{ ...NST; }': ()
1867[138; 139) 'x': {unknown} 1866[138; 139) 'x': {unknown}
1868[142; 153) 'LOCAL_CONST': {unknown} 1867[142; 153) 'LOCAL_CONST': {unknown}
1869[163; 164) 'z': u32 1868[163; 164) 'z': u32
1870[167; 179) 'GLOBAL_CONST': u32 1869[167; 179) 'GLOBAL_CONST': u32
1871[189; 191) 'id': u32 1870[189; 191) 'id': u32
1872[194; 210) 'Foo::A..._CONST': u32"### 1871[194; 210) 'Foo::A..._CONST': u32
1872[126; 128) '99': u32"###
1873 ); 1873 );
1874} 1874}
1875 1875
@@ -1891,8 +1891,6 @@ fn test() {
1891 @r###" 1891 @r###"
1892[29; 32) '101': u32 1892[29; 32) '101': u32
1893[70; 73) '101': u32 1893[70; 73) '101': u32
1894[118; 120) '99': u32
1895[161; 163) '99': u32
1896[85; 280) '{ ...MUT; }': () 1894[85; 280) '{ ...MUT; }': ()
1897[173; 174) 'x': {unknown} 1895[173; 174) 'x': {unknown}
1898[177; 189) 'LOCAL_STATIC': {unknown} 1896[177; 189) 'LOCAL_STATIC': {unknown}
@@ -1901,7 +1899,9 @@ fn test() {
1901[229; 230) 'z': u32 1899[229; 230) 'z': u32
1902[233; 246) 'GLOBAL_STATIC': u32 1900[233; 246) 'GLOBAL_STATIC': u32
1903[256; 257) 'w': u32 1901[256; 257) 'w': u32
1904[260; 277) 'GLOBAL...IC_MUT': u32"### 1902[260; 277) 'GLOBAL...IC_MUT': u32
1903[118; 120) '99': u32
1904[161; 163) '99': u32"###
1905 ); 1905 );
1906} 1906}
1907 1907
@@ -1926,8 +1926,8 @@ fn test() {
1926} 1926}
1927"#), 1927"#),
1928 @r###" 1928 @r###"
1929[31; 35) 'self': &{unknown} 1929[31; 35) 'self': &Self
1930[110; 114) 'self': &{unknown} 1930[110; 114) 'self': &Self
1931[170; 228) '{ ...i128 }': () 1931[170; 228) '{ ...i128 }': ()
1932[176; 178) 'S1': S1 1932[176; 178) 'S1': S1
1933[176; 187) 'S1.method()': u32 1933[176; 187) 'S1.method()': u32
@@ -1972,8 +1972,8 @@ mod bar_test {
1972} 1972}
1973"#), 1973"#),
1974 @r###" 1974 @r###"
1975[63; 67) 'self': &{unknown} 1975[63; 67) 'self': &Self
1976[169; 173) 'self': &{unknown} 1976[169; 173) 'self': &Self
1977[300; 337) '{ ... }': () 1977[300; 337) '{ ... }': ()
1978[310; 311) 'S': S 1978[310; 311) 'S': S
1979[310; 320) 'S.method()': u32 1979[310; 320) 'S.method()': u32
@@ -1998,10 +1998,45 @@ fn test() {
1998} 1998}
1999"#), 1999"#),
2000 @r###" 2000 @r###"
2001[33; 37) 'self': &{unknown} 2001[33; 37) 'self': &Self
2002[92; 111) '{ ...d(); }': () 2002[92; 111) '{ ...d(); }': ()
2003[98; 99) 'S': S 2003[98; 99) 'S': S
2004[98; 108) 'S.method()': {unknown}"### 2004[98; 108) 'S.method()': u32"###
2005 );
2006}
2007
2008#[test]
2009fn infer_trait_method_generic_more_params() {
2010 // the trait implementation is intentionally incomplete -- it shouldn't matter
2011 assert_snapshot_matches!(
2012 infer(r#"
2013trait Trait<T1, T2, T3> {
2014 fn method1(&self) -> (T1, T2, T3);
2015 fn method2(&self) -> (T3, T2, T1);
2016}
2017struct S1;
2018impl Trait<u8, u16, u32> for S1 {}
2019struct S2;
2020impl<T> Trait<i8, i16, T> for S2 {}
2021fn test() {
2022 S1.method1(); // u8, u16, u32
2023 S1.method2(); // u32, u16, u8
2024 S2.method1(); // i8, i16, {unknown}
2025 S2.method2(); // {unknown}, i16, i8
2026}
2027"#),
2028 @r###"
2029[43; 47) 'self': &Self
2030[82; 86) 'self': &Self
2031[210; 361) '{ ..., i8 }': ()
2032[216; 218) 'S1': S1
2033[216; 228) 'S1.method1()': (u8, u16, u32)
2034[250; 252) 'S1': S1
2035[250; 262) 'S1.method2()': (u32, u16, u8)
2036[284; 286) 'S2': S2
2037[284; 296) 'S2.method1()': (i8, i16, {unknown})
2038[324; 326) 'S2': S2
2039[324; 336) 'S2.method2()': ({unknown}, i16, i8)"###
2005 ); 2040 );
2006} 2041}
2007 2042
@@ -2020,7 +2055,7 @@ fn test() {
2020} 2055}
2021"#), 2056"#),
2022 @r###" 2057 @r###"
2023[33; 37) 'self': &{unknown} 2058[33; 37) 'self': &Self
2024[102; 127) '{ ...d(); }': () 2059[102; 127) '{ ...d(); }': ()
2025[108; 109) 'S': S<u32>(T) -> S<T> 2060[108; 109) 'S': S<u32>(T) -> S<T>
2026[108; 115) 'S(1u32)': S<u32> 2061[108; 115) 'S(1u32)': S<u32>
@@ -2168,7 +2203,7 @@ fn test() {
2168} 2203}
2169"#), 2204"#),
2170 @r###" 2205 @r###"
2171[29; 33) 'self': {unknown} 2206[29; 33) 'self': Self
2172[107; 198) '{ ...(S); }': () 2207[107; 198) '{ ...(S); }': ()
2173[117; 118) 'x': u32 2208[117; 118) 'x': u32
2174[126; 127) 'S': S 2209[126; 127) 'S': S
@@ -2302,13 +2337,10 @@ fn test() -> u64 {
2302} 2337}
2303 2338
2304fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 2339fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
2305 let func = source_binder::function_from_position(db, pos).unwrap(); 2340 let file = db.parse(pos.file_id);
2306 let body_source_map = func.body_source_map(db); 2341 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
2307 let inference_result = func.infer(db); 2342 let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset));
2308 let (_, syntax) = func.source(db); 2343 let ty = analyzer.type_of(db, expr).unwrap();
2309 let node = algo::find_node_at_offset::<ast::Expr>(syntax.syntax(), pos.offset).unwrap();
2310 let expr = body_source_map.node_expr(node).unwrap();
2311 let ty = &inference_result[expr];
2312 ty.display(db).to_string() 2344 ty.display(db).to_string()
2313} 2345}
2314 2346
@@ -2324,7 +2356,7 @@ fn infer(content: &str) -> String {
2324 2356
2325 for (pat, ty) in inference_result.type_of_pat.iter() { 2357 for (pat, ty) in inference_result.type_of_pat.iter() {
2326 let syntax_ptr = match body_source_map.pat_syntax(pat) { 2358 let syntax_ptr = match body_source_map.pat_syntax(pat) {
2327 Some(sp) => sp, 2359 Some(sp) => sp.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()),
2328 None => continue, 2360 None => continue,
2329 }; 2361 };
2330 types.push((syntax_ptr, ty)); 2362 types.push((syntax_ptr, ty));
@@ -2350,25 +2382,11 @@ fn infer(content: &str) -> String {
2350 } 2382 }
2351 }; 2383 };
2352 2384
2353 for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) { 2385 for node in source_file.syntax().descendants() {
2354 let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap(); 2386 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
2355 let inference_result = konst.infer(&db); 2387 let analyzer = SourceAnalyzer::new(&db, file_id, node, None);
2356 let body_source_map = konst.body_source_map(&db); 2388 infer_def(analyzer.inference_result(), analyzer.body_source_map());
2357 infer_def(inference_result, body_source_map) 2389 }
2358 }
2359
2360 for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) {
2361 let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap();
2362 let inference_result = static_.infer(&db);
2363 let body_source_map = static_.body_source_map(&db);
2364 infer_def(inference_result, body_source_map)
2365 }
2366
2367 for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) {
2368 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
2369 let inference_result = func.infer(&db);
2370 let body_source_map = func.body_source_map(&db);
2371 infer_def(inference_result, body_source_map)
2372 } 2390 }
2373 2391
2374 acc.truncate(acc.trim_end().len()); 2392 acc.truncate(acc.trim_end().len());
@@ -2403,10 +2421,12 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
2403 } 2421 }
2404 ", 2422 ",
2405 ); 2423 );
2406 let func = source_binder::function_from_position(&db, pos).unwrap();
2407 { 2424 {
2425 let file = db.parse(pos.file_id);
2426 let node =
2427 algo::find_token_at_offset(file.syntax(), pos.offset).right_biased().unwrap().parent();
2408 let events = db.log_executed(|| { 2428 let events = db.log_executed(|| {
2409 func.infer(&db); 2429 SourceAnalyzer::new(&db, pos.file_id, node, None);
2410 }); 2430 });
2411 assert!(format!("{:?}", events).contains("infer")) 2431 assert!(format!("{:?}", events).contains("infer"))
2412 } 2432 }
@@ -2423,8 +2443,11 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
2423 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text)); 2443 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text));
2424 2444
2425 { 2445 {
2446 let file = db.parse(pos.file_id);
2447 let node =
2448 algo::find_token_at_offset(file.syntax(), pos.offset).right_biased().unwrap().parent();
2426 let events = db.log_executed(|| { 2449 let events = db.log_executed(|| {
2427 func.infer(&db); 2450 SourceAnalyzer::new(&db, pos.file_id, node, None);
2428 }); 2451 });
2429 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) 2452 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
2430 } 2453 }
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
new file mode 100644
index 000000000..f8c3958bd
--- /dev/null
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -0,0 +1,112 @@
1//! Stuff that will probably mostly replaced by Chalk.
2use std::collections::HashMap;
3
4use crate::db::HirDatabase;
5use super::{ TraitRef, Substs, infer::{ TypeVarId, InferTy}, Ty};
6
7// Copied (and simplified) from Chalk
8
9#[derive(Clone, Debug, PartialEq, Eq)]
10/// A (possible) solution for a proposed goal. Usually packaged in a `Result`,
11/// where `Err` represents definite *failure* to prove a goal.
12pub enum Solution {
13 /// The goal indeed holds, and there is a unique value for all existential
14 /// variables.
15 Unique(Substs),
16
17 /// The goal may be provable in multiple ways, but regardless we may have some guidance
18 /// for type inference.
19 Ambig(Guidance),
20}
21
22#[derive(Clone, Debug, PartialEq, Eq)]
23/// When a goal holds ambiguously (e.g., because there are multiple possible
24/// solutions), we issue a set of *guidance* back to type inference.
25pub enum Guidance {
26 /// The existential variables *must* have the given values if the goal is
27 /// ever to hold, but that alone isn't enough to guarantee the goal will
28 /// actually hold.
29 Definite(Substs),
30
31 /// There are multiple plausible values for the existentials, but the ones
32 /// here are suggested as the preferred choice heuristically. These should
33 /// be used for inference fallback only.
34 Suggested(Substs),
35
36 /// There's no useful information to feed back to type inference
37 Unknown,
38}
39
40/// Something that needs to be proven (by Chalk) during type checking, e.g. that
41/// a certain type implements a certain trait. Proving the Obligation might
42/// result in additional information about inference variables.
43///
44/// This might be handled by Chalk when we integrate it?
45#[derive(Clone, Debug, PartialEq, Eq)]
46pub enum Obligation {
47 /// Prove that a certain type implements a trait (the type is the `Self` type
48 /// parameter to the `TraitRef`).
49 Trait(TraitRef),
50}
51
52/// Rudimentary check whether an impl exists for a given type and trait; this
53/// will actually be done by chalk.
54pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> Option<Solution> {
55 // FIXME use all trait impls in the whole crate graph
56 let krate = trait_ref.trait_.module(db).krate(db);
57 let krate = match krate {
58 Some(krate) => krate,
59 None => return None,
60 };
61 let crate_impl_blocks = db.impls_in_crate(krate);
62 let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_);
63 impl_blocks
64 .find_map(|impl_block| unify_trait_refs(&trait_ref, &impl_block.target_trait_ref(db)?))
65}
66
67pub(super) fn canonicalize(trait_ref: TraitRef) -> (TraitRef, Vec<TypeVarId>) {
68 let mut canonical = HashMap::new(); // mapping uncanonical -> canonical
69 let mut uncanonical = Vec::new(); // mapping canonical -> uncanonical (which is dense)
70 let mut substs = trait_ref.substs.0.to_vec();
71 for ty in &mut substs {
72 ty.walk_mut(&mut |ty| match ty {
73 Ty::Infer(InferTy::TypeVar(tv)) => {
74 let tv: &mut TypeVarId = tv;
75 *tv = *canonical.entry(*tv).or_insert_with(|| {
76 let i = uncanonical.len();
77 uncanonical.push(*tv);
78 TypeVarId(i as u32)
79 });
80 }
81 _ => {}
82 });
83 }
84 (TraitRef { substs: substs.into(), ..trait_ref }, uncanonical)
85}
86
87fn unify_trait_refs(tr1: &TraitRef, tr2: &TraitRef) -> Option<Solution> {
88 if tr1.trait_ != tr2.trait_ {
89 return None;
90 }
91 let mut solution_substs = Vec::new();
92 for (t1, t2) in tr1.substs.0.iter().zip(tr2.substs.0.iter()) {
93 // this is very bad / hacky 'unification' logic, just enough to make the simple tests pass
94 match (t1, t2) {
95 (_, Ty::Infer(InferTy::TypeVar(_))) | (_, Ty::Unknown) | (_, Ty::Param { .. }) => {
96 // type variable (or similar) in the impl, we just assume it works
97 }
98 (Ty::Infer(InferTy::TypeVar(v1)), _) => {
99 // type variable in the query and fixed type in the impl, record its value
100 solution_substs.resize_with(v1.0 as usize + 1, || Ty::Unknown);
101 solution_substs[v1.0 as usize] = t2.clone();
102 }
103 _ => {
104 // check that they're equal (actually we'd have to recurse etc.)
105 if t1 != t2 {
106 return None;
107 }
108 }
109 }
110 }
111 Some(Solution::Unique(solution_substs.into()))
112}