aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/autoderef.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/autoderef.rs')
-rw-r--r--crates/hir_ty/src/autoderef.rs51
1 files changed, 30 insertions, 21 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 23ab042c1..dc5fc759a 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -16,8 +16,8 @@ use crate::{
16 to_assoc_type_id, to_chalk_trait_id, 16 to_assoc_type_id, to_chalk_trait_id,
17 traits::{InEnvironment, Solution}, 17 traits::{InEnvironment, Solution},
18 utils::generics, 18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution, 19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 TraitRef, Ty, TyKind, 20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 21};
22 22
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 23const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -27,9 +27,9 @@ pub fn autoderef<'a>(
27 krate: Option<CrateId>, 27 krate: Option<CrateId>,
28 ty: InEnvironment<Canonical<Ty>>, 28 ty: InEnvironment<Canonical<Ty>>,
29) -> impl Iterator<Item = Canonical<Ty>> + 'a { 29) -> impl Iterator<Item = Canonical<Ty>> + 'a {
30 let InEnvironment { value: ty, environment } = ty; 30 let InEnvironment { goal: ty, environment } = ty;
31 successors(Some(ty), move |ty| { 31 successors(Some(ty), move |ty| {
32 deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) 32 deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() })
33 }) 33 })
34 .take(AUTODEREF_RECURSION_LIMIT) 34 .take(AUTODEREF_RECURSION_LIMIT)
35} 35}
@@ -39,8 +39,8 @@ pub(crate) fn deref(
39 krate: CrateId, 39 krate: CrateId,
40 ty: InEnvironment<&Canonical<Ty>>, 40 ty: InEnvironment<&Canonical<Ty>>,
41) -> Option<Canonical<Ty>> { 41) -> Option<Canonical<Ty>> {
42 if let Some(derefed) = ty.value.value.builtin_deref() { 42 if let Some(derefed) = ty.goal.value.builtin_deref() {
43 Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() }) 43 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
44 } else { 44 } else {
45 deref_by_trait(db, krate, ty) 45 deref_by_trait(db, krate, ty)
46 } 46 }
@@ -67,15 +67,15 @@ fn deref_by_trait(
67 // FIXME make the Canonical / bound var handling nicer 67 // FIXME make the Canonical / bound var handling nicer
68 68
69 let parameters = 69 let parameters =
70 Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); 70 Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71 71
72 // Check that the type implements Deref at all 72 // Check that the type implements Deref at all
73 let trait_ref = 73 let trait_ref =
74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; 74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
75 let implements_goal = Canonical { 75 let implements_goal = Canonical {
76 kinds: ty.value.kinds.clone(), 76 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 77 value: InEnvironment {
78 value: trait_ref.cast(&Interner), 78 goal: trait_ref.cast(&Interner),
79 environment: ty.environment.clone(), 79 environment: ty.environment.clone(),
80 }, 80 },
81 }; 81 };
@@ -89,18 +89,27 @@ fn deref_by_trait(
89 associated_ty_id: to_assoc_type_id(target), 89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters, 90 substitution: parameters,
91 }), 91 }),
92 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) 92 ty: TyKind::BoundVar(BoundVar::new(
93 .intern(&Interner), 93 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner),
95 ))
96 .intern(&Interner),
94 }; 97 };
95 98
96 let obligation = projection.cast(&Interner); 99 let obligation = projection.cast(&Interner);
97 100
98 let in_env = InEnvironment { value: obligation, environment: ty.environment }; 101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
99 102
100 let canonical = Canonical::new( 103 let canonical = Canonical {
101 in_env, 104 value: in_env,
102 ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), 105 binders: CanonicalVarKinds::from_iter(
103 ); 106 &Interner,
107 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
108 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
109 chalk_ir::UniverseIndex::ROOT,
110 ))),
111 ),
112 };
104 113
105 let solution = db.trait_solve(krate, canonical)?; 114 let solution = db.trait_solve(krate, canonical)?;
106 115
@@ -121,21 +130,21 @@ fn deref_by_trait(
121 // assumptions will be broken. We would need to properly introduce 130 // assumptions will be broken. We would need to properly introduce
122 // new variables in that case 131 // new variables in that case
123 132
124 for i in 1..vars.0.kinds.len() { 133 for i in 1..vars.0.binders.len(&Interner) {
125 if vars.0.value[i - 1].interned(&Interner) 134 if vars.0.value[i - 1].interned(&Interner)
126 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
127 { 136 {
128 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
129 return None; 138 return None;
130 } 139 }
131 } 140 }
132 Some(Canonical { 141 Some(Canonical {
133 value: vars.0.value[vars.0.value.len() - 1].clone(), 142 value: vars.0.value[vars.0.value.len() - 1].clone(),
134 kinds: vars.0.kinds.clone(), 143 binders: vars.0.binders.clone(),
135 }) 144 })
136 } 145 }
137 Solution::Ambig(_) => { 146 Solution::Ambig(_) => {
138 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); 147 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
139 None 148 None
140 } 149 }
141 } 150 }