diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-07-09 08:50:18 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-07-09 08:50:18 +0100 |
commit | f59cd1a4a0d6c369025a7014e838d25f91d478e4 (patch) | |
tree | 2c4b9dc868a87507ed63e9dc46530cc60f38ae64 /crates/ra_hir/src/ty/method_resolution.rs | |
parent | 35f28c538a9b9f461bb4db1a78d02e9f02a3d296 (diff) | |
parent | 9afbf2dff43dee3227358f10162d4c77d192ce7a (diff) |
Merge #1515
1515: Trait environment r=matklad a=flodiebold
This adds the environment, i.e. the set of `where` clauses in scope, when solving trait goals. That means that e.g. in
```rust
fn foo<T: SomeTrait>(t: T) {}
```
, we are able to complete methods of `SomeTrait` on the `t`. This affects the trait APIs quite a bit (since every method that needs to be able to solve for some trait needs to get this environment somehow), so I thought I'd do it rather sooner than later ;)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index f65ad08a8..353820436 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -7,7 +7,7 @@ use std::sync::Arc; | |||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | 9 | ||
10 | use super::{autoderef, Canonical, TraitRef}; | 10 | use super::{autoderef, lower, Canonical, Environment, InEnvironment, TraitRef}; |
11 | use crate::{ | 11 | use crate::{ |
12 | generics::HasGenericParams, | 12 | generics::HasGenericParams, |
13 | impl_block::{ImplBlock, ImplId, ImplItem}, | 13 | impl_block::{ImplBlock, ImplId, ImplItem}, |
@@ -200,6 +200,8 @@ fn iterate_trait_method_candidates<T>( | |||
200 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 200 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
201 | ) -> Option<T> { | 201 | ) -> Option<T> { |
202 | let krate = resolver.krate()?; | 202 | let krate = resolver.krate()?; |
203 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | ||
204 | let env = lower::trait_env(db, resolver); | ||
203 | 'traits: for t in resolver.traits_in_scope(db) { | 205 | 'traits: for t in resolver.traits_in_scope(db) { |
204 | let data = t.trait_data(db); | 206 | let data = t.trait_data(db); |
205 | // we'll be lazy about checking whether the type implements the | 207 | // we'll be lazy about checking whether the type implements the |
@@ -211,8 +213,8 @@ fn iterate_trait_method_candidates<T>( | |||
211 | let data = m.data(db); | 213 | let data = m.data(db); |
212 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { | 214 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { |
213 | if !known_implemented { | 215 | if !known_implemented { |
214 | let trait_ref = canonical_trait_ref(db, t, ty.clone()); | 216 | let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); |
215 | if db.implements(krate, trait_ref).is_none() { | 217 | if db.solve(krate, goal).is_none() { |
216 | continue 'traits; | 218 | continue 'traits; |
217 | } | 219 | } |
218 | } | 220 | } |
@@ -279,11 +281,12 @@ impl Ty { | |||
279 | 281 | ||
280 | /// This creates Substs for a trait with the given Self type and type variables | 282 | /// This creates Substs for a trait with the given Self type and type variables |
281 | /// for all other parameters, to query Chalk with it. | 283 | /// for all other parameters, to query Chalk with it. |
282 | fn canonical_trait_ref( | 284 | fn generic_implements_goal( |
283 | db: &impl HirDatabase, | 285 | db: &impl HirDatabase, |
286 | env: Arc<Environment>, | ||
284 | trait_: Trait, | 287 | trait_: Trait, |
285 | self_ty: Canonical<Ty>, | 288 | self_ty: Canonical<Ty>, |
286 | ) -> Canonical<TraitRef> { | 289 | ) -> Canonical<InEnvironment<super::Obligation>> { |
287 | let mut substs = Vec::new(); | 290 | let mut substs = Vec::new(); |
288 | let generics = trait_.generic_params(db); | 291 | let generics = trait_.generic_params(db); |
289 | let num_vars = self_ty.num_vars; | 292 | let num_vars = self_ty.num_vars; |
@@ -296,8 +299,8 @@ fn canonical_trait_ref( | |||
296 | .enumerate() | 299 | .enumerate() |
297 | .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)), | 300 | .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)), |
298 | ); | 301 | ); |
299 | Canonical { | 302 | let num_vars = substs.len() - 1 + self_ty.num_vars; |
300 | num_vars: substs.len() - 1 + self_ty.num_vars, | 303 | let trait_ref = TraitRef { trait_, substs: substs.into() }; |
301 | value: TraitRef { trait_, substs: substs.into() }, | 304 | let obligation = super::Obligation::Trait(trait_ref); |
302 | } | 305 | Canonical { num_vars, value: InEnvironment::new(env, obligation) } |
303 | } | 306 | } |