aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/autoderef.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/autoderef.rs')
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs45
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
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; 8use hir_def::lang_item::LangItemTarget;
9use hir_expand::name; 9use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId;
11 12
12use crate::{db::HirDatabase, Trait}; 13use crate::{db::HirDatabase, Trait};
13 14
14use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 15use super::{
16 traits::{InEnvironment, Solution},
17 Canonical, Substs, Ty, TypeWalk,
18};
15 19
16const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
17 21
18pub(crate) fn autoderef<'a>( 22pub(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
26pub(crate) fn deref( 34pub(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
38fn deref_by_trait( 46fn 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 }