diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-14 15:06:48 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-14 15:06:48 +0100 |
commit | fcbd0269545f2b6687a64a868654c74f876b7851 (patch) | |
tree | cb439cc77b5445f00cda86e932c199cb69ae47d6 /crates/ra_hir/src/code_model_api.rs | |
parent | 23b876bc3b00c53ce24b8a99b4f4bf190fc6300e (diff) | |
parent | 8bcbcc454cbb48b897083c122566c0b4c2b780aa (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.rs | 84 |
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 | ||
704 | impl Docs for Trait { | 708 | impl 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 | |||
773 | pub enum Container { | ||
774 | Trait(Trait), | ||
775 | ImplBlock(ImplBlock), | ||
776 | } | ||
777 | impl_froms!(Container: Trait, ImplBlock); | ||
778 | |||
779 | impl 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 | } | ||