diff options
Diffstat (limited to 'crates/hir_ty/src/traits.rs')
-rw-r--r-- | crates/hir_ty/src/traits.rs | 104 |
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}; | |||
8 | use stdx::panic_context; | 8 | use stdx::panic_context; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 | ||
15 | use self::chalk::{from_chalk, Interner, ToChalk}; | 15 | use 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)] | ||
75 | pub struct InEnvironment<T> { | ||
76 | pub environment: chalk_ir::Environment<Interner>, | ||
77 | pub goal: T, | ||
78 | } | ||
79 | |||
80 | impl<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)] | ||
90 | pub enum DomainGoal { | ||
91 | Holds(WhereClause), | ||
92 | } | ||
93 | |||
94 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
95 | pub struct AliasEq { | ||
96 | pub alias: AliasTy, | ||
97 | pub ty: Ty, | ||
98 | } | ||
99 | |||
100 | impl 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. |
123 | pub(crate) fn trait_solve_query( | 74 | pub(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)] | ||
250 | pub struct SolutionVariables(pub Canonical<Substitution>); | ||
251 | |||
252 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
253 | /// A (possible) solution for a proposed goal. | ||
254 | pub 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. | ||
269 | pub 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)] |
285 | pub enum FnTrait { | 193 | pub enum FnTrait { |
286 | FnOnce, | 194 | FnOnce, |