diff options
Diffstat (limited to 'crates/ra_hir/src/ty/autoderef.rs')
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 41c99d227..44547197c 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -5,42 +5,49 @@ | |||
5 | 5 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use hir_expand::name; | 9 | use hir_expand::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | use ra_db::CrateId; | ||
11 | 12 | ||
12 | use crate::{db::HirDatabase, Trait}; | 13 | use crate::{db::HirDatabase, Trait}; |
13 | 14 | ||
14 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; | 15 | use super::{ |
16 | traits::{InEnvironment, Solution}, | ||
17 | Canonical, Substs, Ty, TypeWalk, | ||
18 | }; | ||
15 | 19 | ||
16 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 20 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
17 | 21 | ||
18 | pub(crate) fn autoderef<'a>( | 22 | pub(crate) fn autoderef<'a>( |
19 | db: &'a impl HirDatabase, | 23 | db: &'a impl HirDatabase, |
20 | resolver: &'a Resolver, | 24 | krate: Option<CrateId>, |
21 | ty: Canonical<Ty>, | 25 | ty: InEnvironment<Canonical<Ty>>, |
22 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 26 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
23 | successors(Some(ty), move |ty| deref(db, resolver, ty)).take(AUTODEREF_RECURSION_LIMIT) | 27 | let InEnvironment { value: ty, environment } = ty; |
28 | successors(Some(ty), move |ty| { | ||
29 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | ||
30 | }) | ||
31 | .take(AUTODEREF_RECURSION_LIMIT) | ||
24 | } | 32 | } |
25 | 33 | ||
26 | pub(crate) fn deref( | 34 | pub(crate) fn deref( |
27 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
28 | resolver: &Resolver, | 36 | krate: CrateId, |
29 | ty: &Canonical<Ty>, | 37 | ty: InEnvironment<&Canonical<Ty>>, |
30 | ) -> Option<Canonical<Ty>> { | 38 | ) -> Option<Canonical<Ty>> { |
31 | if let Some(derefed) = ty.value.builtin_deref() { | 39 | if let Some(derefed) = ty.value.value.builtin_deref() { |
32 | Some(Canonical { value: derefed, num_vars: ty.num_vars }) | 40 | Some(Canonical { value: derefed, num_vars: ty.value.num_vars }) |
33 | } else { | 41 | } else { |
34 | deref_by_trait(db, resolver, ty) | 42 | deref_by_trait(db, krate, ty) |
35 | } | 43 | } |
36 | } | 44 | } |
37 | 45 | ||
38 | fn deref_by_trait( | 46 | fn deref_by_trait( |
39 | db: &impl HirDatabase, | 47 | db: &impl HirDatabase, |
40 | resolver: &Resolver, | 48 | krate: CrateId, |
41 | ty: &Canonical<Ty>, | 49 | ty: InEnvironment<&Canonical<Ty>>, |
42 | ) -> Option<Canonical<Ty>> { | 50 | ) -> Option<Canonical<Ty>> { |
43 | let krate = resolver.krate()?; | ||
44 | let deref_trait = match db.lang_item(krate.into(), "deref".into())? { | 51 | let deref_trait = match db.lang_item(krate.into(), "deref".into())? { |
45 | LangItemTarget::TraitId(t) => Trait::from(t), | 52 | LangItemTarget::TraitId(t) => Trait::from(t), |
46 | _ => return None, | 53 | _ => return None, |
@@ -56,10 +63,8 @@ fn deref_by_trait( | |||
56 | 63 | ||
57 | // FIXME make the Canonical handling nicer | 64 | // FIXME make the Canonical handling nicer |
58 | 65 | ||
59 | let env = super::lower::trait_env(db, resolver); | ||
60 | |||
61 | let parameters = Substs::build_for_generics(&generic_params) | 66 | let parameters = Substs::build_for_generics(&generic_params) |
62 | .push(ty.value.clone().shift_bound_vars(1)) | 67 | .push(ty.value.value.clone().shift_bound_vars(1)) |
63 | .build(); | 68 | .build(); |
64 | 69 | ||
65 | let projection = super::traits::ProjectionPredicate { | 70 | let projection = super::traits::ProjectionPredicate { |
@@ -69,9 +74,9 @@ fn deref_by_trait( | |||
69 | 74 | ||
70 | let obligation = super::Obligation::Projection(projection); | 75 | let obligation = super::Obligation::Projection(projection); |
71 | 76 | ||
72 | let in_env = super::traits::InEnvironment { value: obligation, environment: env }; | 77 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; |
73 | 78 | ||
74 | let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; | 79 | let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env }; |
75 | 80 | ||
76 | let solution = db.trait_solve(krate.into(), canonical)?; | 81 | let solution = db.trait_solve(krate.into(), canonical)?; |
77 | 82 | ||
@@ -89,14 +94,14 @@ fn deref_by_trait( | |||
89 | // the case. | 94 | // the case. |
90 | for i in 1..vars.0.num_vars { | 95 | for i in 1..vars.0.num_vars { |
91 | if vars.0.value[i] != Ty::Bound((i - 1) as u32) { | 96 | if vars.0.value[i] != Ty::Bound((i - 1) as u32) { |
92 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution); | 97 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); |
93 | return None; | 98 | return None; |
94 | } | 99 | } |
95 | } | 100 | } |
96 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) | 101 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) |
97 | } | 102 | } |
98 | Solution::Ambig(_) => { | 103 | Solution::Ambig(_) => { |
99 | info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution); | 104 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); |
100 | None | 105 | None |
101 | } | 106 | } |
102 | } | 107 | } |