From a1ed53a4f183b5826162eb9e998207b92be9c57f Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 31 Mar 2019 20:02:16 +0200 Subject: More trait infrastructure - make it possible to get parent trait from method - add 'obligation' machinery for checking that a type implements a trait (and inferring facts about type variables from that) - handle type parameters of traits (to a certain degree) - improve the hacky implements check to cover enough cases to exercise the handling of traits with type parameters - basic canonicalization (will probably also be done by Chalk) --- crates/ra_hir/src/code_model_api.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir/src/code_model_api.rs') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 5d8cf57b6..b53fe1f63 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -194,7 +194,7 @@ impl Module { Resolver::default().push_module_scope(def_map, self.module_id) } - pub fn declarations(self, db: &impl HirDatabase) -> Vec { + pub fn declarations(self, db: &impl DefDatabase) -> Vec { let def_map = db.crate_def_map(self.krate); def_map[self.module_id] .scope @@ -547,13 +547,20 @@ impl Function { ImplBlock::containing(module_impls, (*self).into()) } + /// The containing trait, if this is a trait method definition. + pub fn parent_trait(&self, db: &impl DefDatabase) -> Option { + db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) + } + // FIXME: move to a more general type for 'body-having' items /// Builds a resolver for code inside this item. pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... + // FIXME abstract over containers (trait/impl) let r = self .impl_block(db) .map(|ib| ib.resolver(db)) + .or_else(|| self.parent_trait(db).map(|tr| tr.resolver(db))) .unwrap_or_else(|| self.module(db).resolver(db)); // ...and add generic params, if present let p = self.generic_params(db); @@ -699,6 +706,14 @@ impl Trait { pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc { db.trait_data(self) } + + pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + let r = self.module(db).resolver(db); + // add generic params, if present + let p = self.generic_params(db); + let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; + r + } } impl Docs for Trait { -- cgit v1.2.3 From 4497e1d3eae0a72ee1e52be6ab547c67d31279c6 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 14 Apr 2019 11:15:11 +0200 Subject: Add Container enum to handle both kinds of container (impl/trait) --- crates/ra_hir/src/code_model_api.rs | 51 +++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'crates/ra_hir/src/code_model_api.rs') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index b53fe1f63..28de9e76a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -189,7 +189,7 @@ impl Module { } } - pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let def_map = db.crate_def_map(self.krate); Resolver::default().push_module_scope(def_map, self.module_id) } @@ -552,16 +552,21 @@ impl Function { db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) } + pub fn container(&self, db: &impl DefDatabase) -> Option { + if let Some(impl_block) = self.impl_block(db) { + Some(impl_block.into()) + } else if let Some(trait_) = self.parent_trait(db) { + Some(trait_.into()) + } else { + None + } + } + // FIXME: move to a more general type for 'body-having' items /// Builds a resolver for code inside this item. pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... - // FIXME abstract over containers (trait/impl) - let r = self - .impl_block(db) - .map(|ib| ib.resolver(db)) - .or_else(|| self.parent_trait(db).map(|tr| tr.resolver(db))) - .unwrap_or_else(|| self.module(db).resolver(db)); + let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db)); // ...and add generic params, if present let p = self.generic_params(db); let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; @@ -707,7 +712,7 @@ impl Trait { db.trait_data(self) } - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let r = self.module(db).resolver(db); // add generic params, if present let p = self.generic_params(db); @@ -746,6 +751,21 @@ impl TypeAlias { ImplBlock::containing(module_impls, (*self).into()) } + /// The containing trait, if this is a trait method definition. + pub fn parent_trait(&self, db: &impl DefDatabase) -> Option { + db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) + } + + pub fn container(&self, db: &impl DefDatabase) -> Option { + if let Some(impl_block) = self.impl_block(db) { + Some(impl_block.into()) + } else if let Some(trait_) = self.parent_trait(db) { + Some(trait_.into()) + } else { + None + } + } + pub fn type_ref(self, db: &impl DefDatabase) -> Arc { db.type_alias_ref(self) } @@ -769,3 +789,18 @@ impl Docs for TypeAlias { docs_from_ast(&*self.source(db).1) } } + +pub enum Container { + Trait(Trait), + ImplBlock(ImplBlock), +} +impl_froms!(Container: Trait, ImplBlock); + +impl Container { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { + match self { + Container::Trait(trait_) => trait_.resolver(db), + Container::ImplBlock(impl_block) => impl_block.resolver(db), + } + } +} -- cgit v1.2.3 From 8bcbcc454cbb48b897083c122566c0b4c2b780aa Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 14 Apr 2019 13:07:45 +0200 Subject: Extract generic_params method to a HasGenericParams trait --- crates/ra_hir/src/code_model_api.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'crates/ra_hir/src/code_model_api.rs') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 28de9e76a..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::{ expr::{Body, BodySourceMap}, ty::InferenceResult, adt::{EnumVariantId, StructFieldId, VariantDef}, - generics::GenericParams, + generics::HasGenericParams, docs::{Documentation, Docs, docs_from_ast}, ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId}, impl_block::ImplBlock, @@ -299,10 +299,6 @@ impl Struct { .map(|(id, _)| StructField { parent: (*self).into(), id }) } - pub fn generic_params(&self, db: &impl DefDatabase) -> Arc { - db.generic_params((*self).into()) - } - pub fn ty(&self, db: &impl HirDatabase) -> Ty { db.type_for_def((*self).into(), Namespace::Types) } @@ -363,10 +359,6 @@ impl Enum { .map(|(id, _)| EnumVariant { parent: *self, id }) } - pub fn generic_params(&self, db: &impl DefDatabase) -> Arc { - db.generic_params((*self).into()) - } - pub fn ty(&self, db: &impl HirDatabase) -> Ty { db.type_for_def((*self).into(), Namespace::Types) } @@ -537,10 +529,6 @@ impl Function { db.infer((*self).into()) } - pub fn generic_params(&self, db: &impl DefDatabase) -> Arc { - db.generic_params((*self).into()) - } - /// The containing impl block, if this is a method. pub fn impl_block(&self, db: &impl DefDatabase) -> Option { let module_impls = db.impls_in_module(self.module(db)); @@ -696,10 +684,6 @@ impl Trait { self.id.module(db) } - pub fn generic_params(&self, db: &impl DefDatabase) -> Arc { - db.generic_params((*self).into()) - } - pub fn name(self, db: &impl DefDatabase) -> Option { self.trait_data(db).name().clone() } @@ -737,10 +721,6 @@ impl TypeAlias { self.id.source(db) } - pub fn generic_params(&self, db: &impl DefDatabase) -> Arc { - db.generic_params((*self).into()) - } - pub fn module(&self, db: &impl DefDatabase) -> Module { self.id.module(db) } -- cgit v1.2.3