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