aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model_api.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-04-14 15:06:48 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-04-14 15:06:48 +0100
commitfcbd0269545f2b6687a64a868654c74f876b7851 (patch)
treecb439cc77b5445f00cda86e932c199cb69ae47d6 /crates/ra_hir/src/code_model_api.rs
parent23b876bc3b00c53ce24b8a99b4f4bf190fc6300e (diff)
parent8bcbcc454cbb48b897083c122566c0b4c2b780aa (diff)
Merge #1120
1120: More trait infrastructure r=matklad a=flodiebold This adds enough trait infrastructure to be able to make some deductions about type variables when resolving trait methods, while at the same time doing as little as possible that will be later replaced by Chalk :smile: E.g. (as the tests show) if we have ```rust trait Trait<T> { fn method(self) -> T } impl Trait<u32> for S {} ... S.method() ``` we can infer that the return type is `u32`. On the other hand the unification logic is so primitive that we can't handle e.g. `impl<T> Trait<T> for S<T>`. It's all quite hacky, I plan to refactor the parts that will stay, while hopefully the other parts will be replaced soon :slightly_smiling_face: In particular, we need to handle 'containers' (impls and trait defs) more cleanly, and I need to reorganize the method resolution / type inference code... Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/code_model_api.rs')
-rw-r--r--crates/ra_hir/src/code_model_api.rs84
1 files changed, 57 insertions, 27 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 5d8cf57b6..8f1ed1086 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -11,7 +11,7 @@ use crate::{
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,
@@ -189,12 +189,12 @@ impl Module {
189 } 189 }
190 } 190 }
191 191
192 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { 192 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
193 let def_map = db.crate_def_map(self.krate); 193 let def_map = db.crate_def_map(self.krate);
194 Resolver::default().push_module_scope(def_map, self.module_id) 194 Resolver::default().push_module_scope(def_map, self.module_id)
195 } 195 }
196 196
197 pub fn declarations(self, db: &impl HirDatabase) -> Vec<ModuleDef> { 197 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
198 let def_map = db.crate_def_map(self.krate); 198 let def_map = db.crate_def_map(self.krate);
199 def_map[self.module_id] 199 def_map[self.module_id]
200 .scope 200 .scope
@@ -299,10 +299,6 @@ impl Struct {
299 .map(|(id, _)| StructField { parent: (*self).into(), id }) 299 .map(|(id, _)| StructField { parent: (*self).into(), id })
300 } 300 }
301 301
302 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
303 db.generic_params((*self).into())
304 }
305
306 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 302 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
307 db.type_for_def((*self).into(), Namespace::Types) 303 db.type_for_def((*self).into(), Namespace::Types)
308 } 304 }
@@ -363,10 +359,6 @@ impl Enum {
363 .map(|(id, _)| EnumVariant { parent: *self, id }) 359 .map(|(id, _)| EnumVariant { parent: *self, id })
364 } 360 }
365 361
366 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
367 db.generic_params((*self).into())
368 }
369
370 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 362 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
371 db.type_for_def((*self).into(), Namespace::Types) 363 db.type_for_def((*self).into(), Namespace::Types)
372 } 364 }
@@ -537,24 +529,32 @@ impl Function {
537 db.infer((*self).into()) 529 db.infer((*self).into())
538 } 530 }
539 531
540 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
541 db.generic_params((*self).into())
542 }
543
544 /// The containing impl block, if this is a method. 532 /// The containing impl block, if this is a method.
545 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { 533 pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> {
546 let module_impls = db.impls_in_module(self.module(db)); 534 let module_impls = db.impls_in_module(self.module(db));
547 ImplBlock::containing(module_impls, (*self).into()) 535 ImplBlock::containing(module_impls, (*self).into())
548 } 536 }
549 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
550 // FIXME: move to a more general type for 'body-having' items 553 // FIXME: move to a more general type for 'body-having' items
551 /// Builds a resolver for code inside this item. 554 /// Builds a resolver for code inside this item.
552 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { 555 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver {
553 // take the outer scope... 556 // take the outer scope...
554 let r = self 557 let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db));
555 .impl_block(db)
556 .map(|ib| ib.resolver(db))
557 .unwrap_or_else(|| self.module(db).resolver(db));
558 // ...and add generic params, if present 558 // ...and add generic params, if present
559 let p = self.generic_params(db); 559 let p = self.generic_params(db);
560 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 };
@@ -684,10 +684,6 @@ impl Trait {
684 self.id.module(db) 684 self.id.module(db)
685 } 685 }
686 686
687 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
688 db.generic_params((*self).into())
689 }
690
691 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 687 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
692 self.trait_data(db).name().clone() 688 self.trait_data(db).name().clone()
693 } 689 }
@@ -699,6 +695,14 @@ impl Trait {
699 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 695 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
700 db.trait_data(self) 696 db.trait_data(self)
701 } 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 }
702} 706}
703 707
704impl Docs for Trait { 708impl Docs for Trait {
@@ -717,10 +721,6 @@ impl TypeAlias {
717 self.id.source(db) 721 self.id.source(db)
718 } 722 }
719 723
720 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
721 db.generic_params((*self).into())
722 }
723
724 pub fn module(&self, db: &impl DefDatabase) -> Module { 724 pub fn module(&self, db: &impl DefDatabase) -> Module {
725 self.id.module(db) 725 self.id.module(db)
726 } 726 }
@@ -731,6 +731,21 @@ impl TypeAlias {
731 ImplBlock::containing(module_impls, (*self).into()) 731 ImplBlock::containing(module_impls, (*self).into())
732 } 732 }
733 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
734 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> { 749 pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> {
735 db.type_alias_ref(self) 750 db.type_alias_ref(self)
736 } 751 }
@@ -754,3 +769,18 @@ impl Docs for TypeAlias {
754 docs_from_ast(&*self.source(db).1) 769 docs_from_ast(&*self.source(db).1)
755 } 770 }
756} 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}