aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-03-24 16:37:27 +0000
committerFlorian Diebold <[email protected]>2019-03-25 20:28:36 +0000
commit0f7e4a7d2440e7e13a5cdf7e91f262426f0d0d18 (patch)
treeada013fd4cc4a246ae308e7f7be2ae6e07d072e3 /crates
parentc947c15ce1ec02261803f10568e4659e9396109e (diff)
Implement a very naive implements check
... to make the infer_trait_method_simple test have the correct result.
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/db.rs5
-rw-r--r--crates/ra_hir/src/ty.rs23
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs32
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
4 files changed, 50 insertions, 12 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index dd0bf6e34..143919cdc 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -14,7 +14,7 @@ use crate::{
14 impl_block::{ModuleImplBlocks, ImplSourceMap}, 14 impl_block::{ModuleImplBlocks, ImplSourceMap},
15 generics::{GenericParams, GenericDef}, 15 generics::{GenericParams, GenericDef},
16 type_ref::TypeRef, 16 type_ref::TypeRef,
17 traits::TraitData, Trait 17 traits::TraitData, Trait, ty::TraitRef
18}; 18};
19 19
20#[salsa::query_group(DefDatabaseStorage)] 20#[salsa::query_group(DefDatabaseStorage)]
@@ -102,6 +102,9 @@ pub trait HirDatabase: DefDatabase {
102 102
103 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 103 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
104 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 104 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
105
106 #[salsa::invoke(crate::ty::method_resolution::implements)]
107 fn implements(&self, trait_ref: TraitRef) -> bool;
105} 108}
106 109
107#[test] 110#[test]
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 7d25ade47..d42c61e9d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -14,7 +14,7 @@ pub(crate) mod display;
14use std::sync::Arc; 14use std::sync::Arc;
15use std::{fmt, mem}; 15use std::{fmt, mem};
16 16
17use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase}; 17use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait};
18 18
19pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig}; 19pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig};
20pub(crate) use infer::{infer, InferenceResult, InferTy}; 20pub(crate) use infer::{infer, InferenceResult, InferTy};
@@ -91,7 +91,7 @@ pub enum TypeCtor {
91/// A nominal type with (maybe 0) type parameters. This might be a primitive 91/// A nominal type with (maybe 0) type parameters. This might be a primitive
92/// type like `bool`, a struct, tuple, function pointer, reference or 92/// type like `bool`, a struct, tuple, function pointer, reference or
93/// several other things. 93/// several other things.
94#[derive(Clone, PartialEq, Eq, Debug)] 94#[derive(Clone, PartialEq, Eq, Debug, Hash)]
95pub struct ApplicationTy { 95pub struct ApplicationTy {
96 pub ctor: TypeCtor, 96 pub ctor: TypeCtor,
97 pub parameters: Substs, 97 pub parameters: Substs,
@@ -103,7 +103,7 @@ pub struct ApplicationTy {
103/// the same thing (but in a different way). 103/// the same thing (but in a different way).
104/// 104///
105/// This should be cheap to clone. 105/// This should be cheap to clone.
106#[derive(Clone, PartialEq, Eq, Debug)] 106#[derive(Clone, PartialEq, Eq, Debug, Hash)]
107pub enum Ty { 107pub enum Ty {
108 /// A nominal type with (maybe 0) type parameters. This might be a primitive 108 /// A nominal type with (maybe 0) type parameters. This might be a primitive
109 /// type like `bool`, a struct, tuple, function pointer, reference or 109 /// type like `bool`, a struct, tuple, function pointer, reference or
@@ -132,7 +132,7 @@ pub enum Ty {
132} 132}
133 133
134/// A list of substitutions for generic parameters. 134/// A list of substitutions for generic parameters.
135#[derive(Clone, PartialEq, Eq, Debug)] 135#[derive(Clone, PartialEq, Eq, Debug, Hash)]
136pub struct Substs(Arc<[Ty]>); 136pub struct Substs(Arc<[Ty]>);
137 137
138impl Substs { 138impl Substs {
@@ -169,6 +169,21 @@ impl Substs {
169 } 169 }
170} 170}
171 171
172/// 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?
174#[derive(Clone, PartialEq, Eq, Debug, Hash)]
175pub struct TraitRef {
176 /// FIXME name?
177 trait_: Trait,
178 substs: Substs,
179}
180
181impl TraitRef {
182 pub fn self_ty(&self) -> &Ty {
183 &self.substs.0[0]
184 }
185}
186
172/// A function signature as seen by type inference: Several parameter types and 187/// A function signature as seen by type inference: Several parameter types and
173/// one return type. 188/// one return type.
174#[derive(Clone, PartialEq, Eq, Debug)] 189#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 708a435b4..146e8a02e 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -8,12 +8,12 @@ use rustc_hash::FxHashMap;
8 8
9use crate::{ 9use crate::{
10 HirDatabase, Module, Crate, Name, Function, Trait, 10 HirDatabase, Module, Crate, Name, Function, Trait,
11 ids::TraitId,
12 impl_block::{ImplId, ImplBlock, ImplItem}, 11 impl_block::{ImplId, ImplBlock, ImplItem},
13 ty::{Ty, TypeCtor}, 12 ty::{Ty, TypeCtor},
14 nameres::CrateModuleId, resolve::Resolver, traits::TraitItem 13 nameres::CrateModuleId, resolve::Resolver, traits::TraitItem
15 14
16}; 15};
16use super::{ TraitRef, Substs};
17 17
18/// This is used as a key for indexing impls. 18/// This is used as a key for indexing impls.
19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -38,7 +38,7 @@ pub struct CrateImplBlocks {
38 /// To make sense of the CrateModuleIds, we need the source root. 38 /// To make sense of the CrateModuleIds, we need the source root.
39 krate: Crate, 39 krate: Crate,
40 impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>, 40 impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
41 impls_by_trait: FxHashMap<TraitId, Vec<(CrateModuleId, ImplId)>>, 41 impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
42} 42}
43 43
44impl CrateImplBlocks { 44impl CrateImplBlocks {
@@ -56,8 +56,7 @@ impl CrateImplBlocks {
56 &'a self, 56 &'a self,
57 tr: &Trait, 57 tr: &Trait,
58 ) -> impl Iterator<Item = ImplBlock> + 'a { 58 ) -> impl Iterator<Item = ImplBlock> + 'a {
59 let id = tr.id; 59 self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map(
60 self.impls_by_trait.get(&id).into_iter().flat_map(|i| i.iter()).map(
61 move |(module_id, impl_id)| { 60 move |(module_id, impl_id)| {
62 let module = Module { krate: self.krate, module_id: *module_id }; 61 let module = Module { krate: self.krate, module_id: *module_id };
63 ImplBlock::from_id(module, *impl_id) 62 ImplBlock::from_id(module, *impl_id)
@@ -75,7 +74,7 @@ impl CrateImplBlocks {
75 74
76 if let Some(tr) = impl_block.target_trait(db) { 75 if let Some(tr) = impl_block.target_trait(db) {
77 self.impls_by_trait 76 self.impls_by_trait
78 .entry(tr.id) 77 .entry(tr)
79 .or_insert_with(Vec::new) 78 .or_insert_with(Vec::new)
80 .push((module.module_id, impl_id)); 79 .push((module.module_id, impl_id));
81 } else { 80 } else {
@@ -109,6 +108,24 @@ impl CrateImplBlocks {
109 } 108 }
110} 109}
111 110
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 for impl_block in crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_) {
122 if &impl_block.target_ty(db) == trait_ref.self_ty() {
123 return true;
124 }
125 }
126 false
127}
128
112fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { 129fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
113 match ty { 130 match ty {
114 Ty::Apply(a_ty) => match a_ty.ctor { 131 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -162,7 +179,10 @@ impl Ty {
162 } 179 }
163 } 180 }
164 // FIXME the implements check may result in other obligations or unifying variables? 181 // FIXME the implements check may result in other obligations or unifying variables?
165 candidates.retain(|(_t, _m)| /* self implements t */ true); 182 candidates.retain(|(t, _m)| {
183 let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) };
184 db.implements(trait_ref)
185 });
166 // FIXME what happens if there are still multiple potential candidates? 186 // FIXME what happens if there are still multiple potential candidates?
167 let (_chosen_trait, chosen_method) = candidates.first()?; 187 let (_chosen_trait, chosen_method) = candidates.first()?;
168 Some((self.clone(), *chosen_method)) 188 Some((self.clone(), *chosen_method))
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 971043266..655f3c522 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1920,7 +1920,7 @@ fn test() {
1920[176; 178) 'S1': S1 1920[176; 178) 'S1': S1
1921[176; 187) 'S1.method()': u32 1921[176; 187) 'S1.method()': u32
1922[203; 205) 'S2': S2 1922[203; 205) 'S2': S2
1923[203; 214) 'S2.method()': u32"### 1923[203; 214) 'S2.method()': i128"###
1924 ); 1924 );
1925} 1925}
1926 1926