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.rs49
1 files changed, 22 insertions, 27 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index dc5fc759a..7ca4af80e 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -12,12 +12,8 @@ use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, 15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex,
16 to_assoc_type_id, to_chalk_trait_id, 16 InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind,
17 traits::{InEnvironment, Solution},
18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 17};
22 18
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 19const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -57,21 +53,20 @@ fn deref_by_trait(
57 }; 53 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 54 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 55
60 let generic_params = generics(db.upcast(), target.into()); 56 let projection = {
61 if generic_params.len() != 1 { 57 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 58 if b.remaining() != 1 {
63 // namely Deref's Self type 59 // the Target type + Deref trait should only have one generic parameter,
64 return None; 60 // namely Deref's Self type
65 } 61 return None;
62 }
63 b.push(ty.goal.value.clone()).build()
64 };
66 65
67 // FIXME make the Canonical / bound var handling nicer 66 // FIXME make the Canonical / bound var handling nicer
68 67
69 let parameters =
70 Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71
72 // Check that the type implements Deref at all 68 // Check that the type implements Deref at all
73 let trait_ref = 69 let trait_ref = projection.trait_ref(db);
74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
75 let implements_goal = Canonical { 70 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 71 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 72 value: InEnvironment {
@@ -84,11 +79,8 @@ fn deref_by_trait(
84 } 79 }
85 80
86 // Now do the assoc type projection 81 // Now do the assoc type projection
87 let projection = AliasEq { 82 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 83 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 84 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 85 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 86 ty.goal.binders.len(&Interner),
@@ -96,9 +88,7 @@ fn deref_by_trait(
96 .intern(&Interner), 88 .intern(&Interner),
97 }; 89 };
98 90
99 let obligation = projection.cast(&Interner); 91 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 92
103 let canonical = Canonical { 93 let canonical = Canonical {
104 value: in_env, 94 value: in_env,
@@ -131,7 +121,7 @@ fn deref_by_trait(
131 // new variables in that case 121 // new variables in that case
132 122
133 for i in 1..vars.0.binders.len(&Interner) { 123 for i in 1..vars.0.binders.len(&Interner) {
134 if vars.0.value[i - 1].interned(&Interner) 124 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
136 { 126 {
137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -139,7 +129,12 @@ fn deref_by_trait(
139 } 129 }
140 } 130 }
141 Some(Canonical { 131 Some(Canonical {
142 value: vars.0.value[vars.0.value.len() - 1].clone(), 132 value: vars
133 .0
134 .value
135 .at(&Interner, vars.0.value.len(&Interner) - 1)
136 .assert_ty_ref(&Interner)
137 .clone(),
143 binders: vars.0.binders.clone(), 138 binders: vars.0.binders.clone(),
144 }) 139 })
145 } 140 }