diff options
Diffstat (limited to 'crates/hir_ty/src/autoderef.rs')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 49 |
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; | |||
12 | use log::{info, warn}; | 12 | use log::{info, warn}; |
13 | 13 | ||
14 | use crate::{ | 14 | use 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 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 19 | const 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 | } |