diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 38 |
1 files changed, 15 insertions, 23 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index c859f9491..70c56cc45 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -13,11 +13,9 @@ use log::{info, warn}; | |||
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::HirDatabase, | 15 | db::HirDatabase, |
16 | to_assoc_type_id, to_chalk_trait_id, | ||
17 | traits::{InEnvironment, Solution}, | 16 | traits::{InEnvironment, Solution}, |
18 | utils::generics, | 17 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty, |
19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, | 18 | TyBuilder, TyKind, |
20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, | ||
21 | }; | 19 | }; |
22 | 20 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 21 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -57,21 +55,20 @@ fn deref_by_trait( | |||
57 | }; | 55 | }; |
58 | let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; | 56 | let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; |
59 | 57 | ||
60 | let generic_params = generics(db.upcast(), target.into()); | 58 | let projection = { |
61 | if generic_params.len() != 1 { | 59 | let b = TyBuilder::assoc_type_projection(db, target); |
62 | // the Target type + Deref trait should only have one generic parameter, | 60 | if b.remaining() != 1 { |
63 | // namely Deref's Self type | 61 | // the Target type + Deref trait should only have one generic parameter, |
64 | return None; | 62 | // namely Deref's Self type |
65 | } | 63 | return None; |
64 | } | ||
65 | b.push(ty.goal.value.clone()).build() | ||
66 | }; | ||
66 | 67 | ||
67 | // FIXME make the Canonical / bound var handling nicer | 68 | // FIXME make the Canonical / bound var handling nicer |
68 | 69 | ||
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 | 70 | // Check that the type implements Deref at all |
73 | let trait_ref = | 71 | 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 { | 72 | let implements_goal = Canonical { |
76 | binders: ty.goal.binders.clone(), | 73 | binders: ty.goal.binders.clone(), |
77 | value: InEnvironment { | 74 | value: InEnvironment { |
@@ -84,11 +81,8 @@ fn deref_by_trait( | |||
84 | } | 81 | } |
85 | 82 | ||
86 | // Now do the assoc type projection | 83 | // Now do the assoc type projection |
87 | let projection = AliasEq { | 84 | let alias_eq = AliasEq { |
88 | alias: AliasTy::Projection(ProjectionTy { | 85 | alias: AliasTy::Projection(projection), |
89 | associated_ty_id: to_assoc_type_id(target), | ||
90 | substitution: parameters, | ||
91 | }), | ||
92 | ty: TyKind::BoundVar(BoundVar::new( | 86 | ty: TyKind::BoundVar(BoundVar::new( |
93 | DebruijnIndex::INNERMOST, | 87 | DebruijnIndex::INNERMOST, |
94 | ty.goal.binders.len(&Interner), | 88 | ty.goal.binders.len(&Interner), |
@@ -96,9 +90,7 @@ fn deref_by_trait( | |||
96 | .intern(&Interner), | 90 | .intern(&Interner), |
97 | }; | 91 | }; |
98 | 92 | ||
99 | let obligation = projection.cast(&Interner); | 93 | let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment }; |
100 | |||
101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; | ||
102 | 94 | ||
103 | let canonical = Canonical { | 95 | let canonical = Canonical { |
104 | value: in_env, | 96 | value: in_env, |