aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/traits.rs')
-rw-r--r--crates/hir_ty/src/traits.rs39
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};
8use hir_def::{lang_item::LangItemTarget, TraitId}; 8use hir_def::{lang_item::LangItemTarget, TraitId};
9use stdx::panic_context; 9use stdx::panic_context;
10 10
11use crate::{db::HirDatabase, DebruijnIndex, Substitution}; 11use crate::{
12 12 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution,
13use super::{ 13 TraitRef, Ty, TyKind, TypeWalk,
14 Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
15}; 14};
16 15
17use self::chalk::{from_chalk, Interner, ToChalk}; 16use 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
99impl Obligation { 98impl 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)]
112pub struct ProjectionPredicate { 109pub struct AliasEq {
113 pub projection_ty: ProjectionTy, 110 pub alias: AliasTy,
114 pub ty: Ty, 111 pub ty: Ty,
115} 112}
116 113
117impl TypeWalk for ProjectionPredicate { 114impl 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 }