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.rs104
1 files changed, 6 insertions, 98 deletions
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index ccee0e5ad..7d87741b8 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -8,8 +8,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId};
8use stdx::panic_context; 8use stdx::panic_context;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind, 11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment,
12 TypeWalk, WhereClause, 12 Solution, TraitRefExt, Ty, TyKind, WhereClause,
13}; 13};
14 14
15use self::chalk::{from_chalk, Interner, ToChalk}; 15use self::chalk::{from_chalk, Interner, ToChalk};
@@ -70,55 +70,6 @@ impl Default for TraitEnvironment {
70 } 70 }
71} 71}
72 72
73/// Something (usually a goal), along with an environment.
74#[derive(Clone, Debug, PartialEq, Eq, Hash)]
75pub struct InEnvironment<T> {
76 pub environment: chalk_ir::Environment<Interner>,
77 pub goal: T,
78}
79
80impl<T> InEnvironment<T> {
81 pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
82 InEnvironment { environment, goal: value }
83 }
84}
85
86/// Something that needs to be proven (by Chalk) during type checking, e.g. that
87/// a certain type implements a certain trait. Proving the Obligation might
88/// result in additional information about inference variables.
89#[derive(Clone, Debug, PartialEq, Eq, Hash)]
90pub enum DomainGoal {
91 Holds(WhereClause),
92}
93
94#[derive(Clone, Debug, PartialEq, Eq, Hash)]
95pub struct AliasEq {
96 pub alias: AliasTy,
97 pub ty: Ty,
98}
99
100impl TypeWalk for AliasEq {
101 fn walk(&self, f: &mut impl FnMut(&Ty)) {
102 self.ty.walk(f);
103 match &self.alias {
104 AliasTy::Projection(projection_ty) => projection_ty.walk(f),
105 AliasTy::Opaque(opaque) => opaque.walk(f),
106 }
107 }
108
109 fn walk_mut_binders(
110 &mut self,
111 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
112 binders: DebruijnIndex,
113 ) {
114 self.ty.walk_mut_binders(f, binders);
115 match &mut self.alias {
116 AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
117 AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
118 }
119 }
120}
121
122/// Solve a trait goal using Chalk. 73/// Solve a trait goal using Chalk.
123pub(crate) fn trait_solve_query( 74pub(crate) fn trait_solve_query(
124 db: &dyn HirDatabase, 75 db: &dyn HirDatabase,
@@ -138,7 +89,7 @@ pub(crate) fn trait_solve_query(
138 .. 89 ..
139 })) = &goal.value.goal 90 })) = &goal.value.goal
140 { 91 {
141 if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { 92 if let TyKind::BoundVar(_) = projection_ty.self_type_parameter(&Interner).kind(&Interner) {
142 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible 93 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
143 return Some(Solution::Ambig(Guidance::Unknown)); 94 return Some(Solution::Ambig(Guidance::Unknown));
144 } 95 }
@@ -222,23 +173,15 @@ fn solution_from_chalk(
222 db: &dyn HirDatabase, 173 db: &dyn HirDatabase,
223 solution: chalk_solve::Solution<Interner>, 174 solution: chalk_solve::Solution<Interner>,
224) -> Solution { 175) -> Solution {
225 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
226 let result = from_chalk(db, subst);
227 SolutionVariables(result)
228 };
229 match solution { 176 match solution {
230 chalk_solve::Solution::Unique(constr_subst) => { 177 chalk_solve::Solution::Unique(constr_subst) => {
231 let subst = chalk_ir::Canonical { 178 Solution::Unique(from_chalk(db, constr_subst))
232 value: constr_subst.value.subst,
233 binders: constr_subst.binders,
234 };
235 Solution::Unique(convert_subst(subst))
236 } 179 }
237 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => { 180 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => {
238 Solution::Ambig(Guidance::Definite(convert_subst(subst))) 181 Solution::Ambig(Guidance::Definite(from_chalk(db, subst)))
239 } 182 }
240 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => { 183 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => {
241 Solution::Ambig(Guidance::Suggested(convert_subst(subst))) 184 Solution::Ambig(Guidance::Suggested(from_chalk(db, subst)))
242 } 185 }
243 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => { 186 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => {
244 Solution::Ambig(Guidance::Unknown) 187 Solution::Ambig(Guidance::Unknown)
@@ -246,41 +189,6 @@ fn solution_from_chalk(
246 } 189 }
247} 190}
248 191
249#[derive(Clone, Debug, PartialEq, Eq)]
250pub struct SolutionVariables(pub Canonical<Substitution>);
251
252#[derive(Clone, Debug, PartialEq, Eq)]
253/// A (possible) solution for a proposed goal.
254pub enum Solution {
255 /// The goal indeed holds, and there is a unique value for all existential
256 /// variables.
257 Unique(SolutionVariables),
258
259 /// The goal may be provable in multiple ways, but regardless we may have some guidance
260 /// for type inference. In this case, we don't return any lifetime
261 /// constraints, since we have not "committed" to any particular solution
262 /// yet.
263 Ambig(Guidance),
264}
265
266#[derive(Clone, Debug, PartialEq, Eq)]
267/// When a goal holds ambiguously (e.g., because there are multiple possible
268/// solutions), we issue a set of *guidance* back to type inference.
269pub enum Guidance {
270 /// The existential variables *must* have the given values if the goal is
271 /// ever to hold, but that alone isn't enough to guarantee the goal will
272 /// actually hold.
273 Definite(SolutionVariables),
274
275 /// There are multiple plausible values for the existentials, but the ones
276 /// here are suggested as the preferred choice heuristically. These should
277 /// be used for inference fallback only.
278 Suggested(SolutionVariables),
279
280 /// There's no useful information to feed back to type inference
281 Unknown,
282}
283
284#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 192#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
285pub enum FnTrait { 193pub enum FnTrait {
286 FnOnce, 194 FnOnce,