diff options
Diffstat (limited to 'crates/hir_ty/src/traits.rs')
-rw-r--r-- | crates/hir_ty/src/traits.rs | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 40eb1034e..ac7de7605 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -8,10 +8,9 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; | |||
8 | use hir_def::{lang_item::LangItemTarget, TraitId}; | 8 | use hir_def::{lang_item::LangItemTarget, TraitId}; |
9 | use stdx::panic_context; | 9 | use stdx::panic_context; |
10 | 10 | ||
11 | use crate::{db::HirDatabase, DebruijnIndex, Substitution}; | 11 | use crate::{ |
12 | 12 | db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution, | |
13 | use super::{ | 13 | TraitRef, Ty, TyKind, TypeWalk, |
14 | Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk, | ||
15 | }; | 14 | }; |
16 | 15 | ||
17 | use self::chalk::{from_chalk, Interner, ToChalk}; | 16 | use self::chalk::{from_chalk, Interner, ToChalk}; |
@@ -93,31 +92,32 @@ pub enum Obligation { | |||
93 | /// Prove that a certain type implements a trait (the type is the `Self` type | 92 | /// Prove that a certain type implements a trait (the type is the `Self` type |
94 | /// parameter to the `TraitRef`). | 93 | /// parameter to the `TraitRef`). |
95 | Trait(TraitRef), | 94 | Trait(TraitRef), |
96 | Projection(ProjectionPredicate), | 95 | AliasEq(AliasEq), |
97 | } | 96 | } |
98 | 97 | ||
99 | impl Obligation { | 98 | impl Obligation { |
100 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { | 99 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { |
101 | match predicate { | 100 | match predicate { |
102 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), | 101 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), |
103 | GenericPredicate::Projection(projection_pred) => { | 102 | GenericPredicate::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)), |
104 | Some(Obligation::Projection(projection_pred)) | ||
105 | } | ||
106 | GenericPredicate::Error => None, | 103 | GenericPredicate::Error => None, |
107 | } | 104 | } |
108 | } | 105 | } |
109 | } | 106 | } |
110 | 107 | ||
111 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 108 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
112 | pub struct ProjectionPredicate { | 109 | pub struct AliasEq { |
113 | pub projection_ty: ProjectionTy, | 110 | pub alias: AliasTy, |
114 | pub ty: Ty, | 111 | pub ty: Ty, |
115 | } | 112 | } |
116 | 113 | ||
117 | impl TypeWalk for ProjectionPredicate { | 114 | impl TypeWalk for AliasEq { |
118 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 115 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
119 | self.projection_ty.walk(f); | ||
120 | self.ty.walk(f); | 116 | self.ty.walk(f); |
117 | match &self.alias { | ||
118 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
119 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
120 | } | ||
121 | } | 121 | } |
122 | 122 | ||
123 | fn walk_mut_binders( | 123 | fn walk_mut_binders( |
@@ -125,8 +125,11 @@ impl TypeWalk for ProjectionPredicate { | |||
125 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | 125 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), |
126 | binders: DebruijnIndex, | 126 | binders: DebruijnIndex, |
127 | ) { | 127 | ) { |
128 | self.projection_ty.walk_mut_binders(f, binders); | ||
129 | self.ty.walk_mut_binders(f, binders); | 128 | self.ty.walk_mut_binders(f, binders); |
129 | match &mut self.alias { | ||
130 | AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), | ||
131 | AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), | ||
132 | } | ||
130 | } | 133 | } |
131 | } | 134 | } |
132 | 135 | ||
@@ -137,13 +140,15 @@ pub(crate) fn trait_solve_query( | |||
137 | goal: Canonical<InEnvironment<Obligation>>, | 140 | goal: Canonical<InEnvironment<Obligation>>, |
138 | ) -> Option<Solution> { | 141 | ) -> Option<Solution> { |
139 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { | 142 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { |
140 | Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(), | 143 | Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(), |
141 | Obligation::Projection(_) => "projection".to_string(), | 144 | Obligation::AliasEq(_) => "alias_eq".to_string(), |
142 | }); | 145 | }); |
143 | log::info!("trait_solve_query({})", goal.value.value.display(db)); | 146 | log::info!("trait_solve_query({})", goal.value.value.display(db)); |
144 | 147 | ||
145 | if let Obligation::Projection(pred) = &goal.value.value { | 148 | if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) = |
146 | if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) { | 149 | &goal.value.value |
150 | { | ||
151 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { | ||
147 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | 152 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible |
148 | return Some(Solution::Ambig(Guidance::Unknown)); | 153 | return Some(Solution::Ambig(Guidance::Unknown)); |
149 | } | 154 | } |