diff options
author | Florian Diebold <[email protected]> | 2019-07-08 20:43:52 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-07-08 20:47:37 +0100 |
commit | 9afbf2dff43dee3227358f10162d4c77d192ce7a (patch) | |
tree | 82d38315b9be21dec920f59389ea89cdb3ae0a41 /crates | |
parent | 15862fc04183c7f9b3f3af666336a594a6a52cd9 (diff) |
Unify `normalize` and `implements` to simplify code
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/db.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 64 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide_api/src/change.rs | 3 |
9 files changed, 67 insertions, 107 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index e0a37e13d..b0c027631 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -213,18 +213,11 @@ pub trait HirDatabase: DefDatabase + AstDatabase { | |||
213 | #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)] | 213 | #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)] |
214 | fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>; | 214 | fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>; |
215 | 215 | ||
216 | #[salsa::invoke(crate::ty::traits::implements_query)] | 216 | #[salsa::invoke(crate::ty::traits::solve_query)] |
217 | fn implements( | 217 | fn solve( |
218 | &self, | 218 | &self, |
219 | krate: Crate, | 219 | krate: Crate, |
220 | goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::TraitRef>>, | 220 | goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::Obligation>>, |
221 | ) -> Option<crate::ty::traits::Solution>; | ||
222 | |||
223 | #[salsa::invoke(crate::ty::traits::normalize_query)] | ||
224 | fn normalize( | ||
225 | &self, | ||
226 | krate: Crate, | ||
227 | goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::ProjectionPredicate>>, | ||
228 | ) -> Option<crate::ty::traits::Solution>; | 221 | ) -> Option<crate::ty::traits::Solution>; |
229 | } | 222 | } |
230 | 223 | ||
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index b45a188d1..9accffcbc 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -26,7 +26,7 @@ pub(crate) use lower::{ | |||
26 | callable_item_sig, generic_defaults_query, generic_predicates_query, type_for_def, | 26 | callable_item_sig, generic_defaults_query, generic_predicates_query, type_for_def, |
27 | type_for_field, TypableDef, | 27 | type_for_field, TypableDef, |
28 | }; | 28 | }; |
29 | pub(crate) use traits::{Environment, InEnvironment, ProjectionPredicate}; | 29 | pub(crate) use traits::{Environment, InEnvironment, Obligation, ProjectionPredicate}; |
30 | 30 | ||
31 | /// A type constructor or type name: this might be something like the primitive | 31 | /// A type constructor or type name: this might be something like the primitive |
32 | /// type `bool`, a struct like `Vec`, or things like function pointers or | 32 | /// type `bool`, a struct like `Vec`, or things like function pointers or |
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 214aa7d03..c26513871 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -62,11 +62,13 @@ fn deref_by_trait( | |||
62 | }, | 62 | }, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | let in_env = super::traits::InEnvironment { value: projection, environment: env }; | 65 | let obligation = super::Obligation::Projection(projection); |
66 | |||
67 | let in_env = super::traits::InEnvironment { value: obligation, environment: env }; | ||
66 | 68 | ||
67 | let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; | 69 | let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; |
68 | 70 | ||
69 | let solution = db.normalize(krate, canonical)?; | 71 | let solution = db.solve(krate, canonical)?; |
70 | 72 | ||
71 | match &solution { | 73 | match &solution { |
72 | Solution::Unique(vars) => { | 74 | Solution::Unique(vars) => { |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index f6cf61ad2..1f74108a4 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -331,53 +331,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
331 | fn resolve_obligations_as_possible(&mut self) { | 331 | fn resolve_obligations_as_possible(&mut self) { |
332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
333 | for obligation in obligations { | 333 | for obligation in obligations { |
334 | match &obligation { | 334 | let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); |
335 | Obligation::Trait(tr) => { | 335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
336 | let in_env = InEnvironment::new(self.trait_env.clone(), tr.clone()); | 336 | let solution = |
337 | let canonicalized = self.canonicalizer().canonicalize_trait_ref(in_env); | 337 | self.db.solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
338 | let solution = self | 338 | |
339 | .db | 339 | match solution { |
340 | .implements(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 340 | Some(Solution::Unique(substs)) => { |
341 | match solution { | 341 | canonicalized.apply_solution(self, substs.0); |
342 | Some(Solution::Unique(substs)) => { | ||
343 | canonicalized.apply_solution(self, substs.0); | ||
344 | } | ||
345 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | ||
346 | canonicalized.apply_solution(self, substs.0); | ||
347 | self.obligations.push(obligation); | ||
348 | } | ||
349 | Some(_) => { | ||
350 | // FIXME use this when trying to resolve everything at the end | ||
351 | self.obligations.push(obligation); | ||
352 | } | ||
353 | None => { | ||
354 | // FIXME obligation cannot be fulfilled => diagnostic | ||
355 | } | ||
356 | }; | ||
357 | } | 342 | } |
358 | Obligation::Projection(pr) => { | 343 | Some(Solution::Ambig(Guidance::Definite(substs))) => { |
359 | let in_env = InEnvironment::new(self.trait_env.clone(), pr.clone()); | 344 | canonicalized.apply_solution(self, substs.0); |
360 | let canonicalized = self.canonicalizer().canonicalize_projection(in_env); | 345 | self.obligations.push(obligation); |
361 | let solution = self | 346 | } |
362 | .db | 347 | Some(_) => { |
363 | .normalize(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 348 | // FIXME use this when trying to resolve everything at the end |
364 | 349 | self.obligations.push(obligation); | |
365 | match solution { | 350 | } |
366 | Some(Solution::Unique(substs)) => { | 351 | None => { |
367 | canonicalized.apply_solution(self, substs.0); | 352 | // FIXME obligation cannot be fulfilled => diagnostic |
368 | } | ||
369 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | ||
370 | canonicalized.apply_solution(self, substs.0); | ||
371 | self.obligations.push(obligation); | ||
372 | } | ||
373 | Some(_) => { | ||
374 | // FIXME use this when trying to resolve everything at the end | ||
375 | self.obligations.push(obligation); | ||
376 | } | ||
377 | None => { | ||
378 | // FIXME obligation cannot be fulfilled => diagnostic | ||
379 | } | ||
380 | }; | ||
381 | } | 353 | } |
382 | }; | 354 | }; |
383 | } | 355 | } |
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index 2ed326cd5..e7e8825d1 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Unification and canonicalization logic. | 1 | //! Unification and canonicalization logic. |
2 | 2 | ||
3 | use super::InferenceContext; | 3 | use super::{InferenceContext, Obligation}; |
4 | use crate::db::HirDatabase; | 4 | use crate::db::HirDatabase; |
5 | use crate::ty::{ | 5 | use crate::ty::{ |
6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, | 6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, |
@@ -110,32 +110,24 @@ where | |||
110 | // FIXME: add some point, we need to introduce a `Fold` trait that abstracts | 110 | // FIXME: add some point, we need to introduce a `Fold` trait that abstracts |
111 | // over all the things that can be canonicalized (like Chalk and rustc have) | 111 | // over all the things that can be canonicalized (like Chalk and rustc have) |
112 | 112 | ||
113 | pub fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 113 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
114 | let result = self.do_canonicalize_ty(ty); | 114 | let result = self.do_canonicalize_ty(ty); |
115 | self.into_canonicalized(result) | 115 | self.into_canonicalized(result) |
116 | } | 116 | } |
117 | 117 | ||
118 | pub fn canonicalize_trait_ref( | 118 | pub(crate) fn canonicalize_obligation( |
119 | mut self, | 119 | mut self, |
120 | trait_ref_in_env: InEnvironment<TraitRef>, | 120 | obligation: InEnvironment<Obligation>, |
121 | ) -> Canonicalized<InEnvironment<TraitRef>> { | 121 | ) -> Canonicalized<InEnvironment<Obligation>> { |
122 | let result = self.do_canonicalize_trait_ref(trait_ref_in_env.value); | 122 | let result = match obligation.value { |
123 | // FIXME canonicalize env | 123 | Obligation::Trait(tr) => Obligation::Trait(self.do_canonicalize_trait_ref(tr)), |
124 | self.into_canonicalized(InEnvironment { | 124 | Obligation::Projection(pr) => { |
125 | value: result, | 125 | Obligation::Projection(self.do_canonicalize_projection_predicate(pr)) |
126 | environment: trait_ref_in_env.environment, | 126 | } |
127 | }) | 127 | }; |
128 | } | ||
129 | |||
130 | pub fn canonicalize_projection( | ||
131 | mut self, | ||
132 | projection: InEnvironment<ProjectionPredicate>, | ||
133 | ) -> Canonicalized<InEnvironment<ProjectionPredicate>> { | ||
134 | let result = self.do_canonicalize_projection_predicate(projection.value); | ||
135 | // FIXME canonicalize env | ||
136 | self.into_canonicalized(InEnvironment { | 128 | self.into_canonicalized(InEnvironment { |
137 | value: result, | 129 | value: result, |
138 | environment: projection.environment, | 130 | environment: obligation.environment, |
139 | }) | 131 | }) |
140 | } | 132 | } |
141 | } | 133 | } |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 40f5eabf0..e214bf1af 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -211,8 +211,8 @@ fn iterate_trait_method_candidates<T>( | |||
211 | let data = m.data(db); | 211 | let data = m.data(db); |
212 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { | 212 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { |
213 | if !known_implemented { | 213 | if !known_implemented { |
214 | let trait_ref = canonical_trait_ref(db, env.clone(), t, ty.clone()); | 214 | let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); |
215 | if db.implements(krate, trait_ref).is_none() { | 215 | if db.solve(krate, goal).is_none() { |
216 | continue 'traits; | 216 | continue 'traits; |
217 | } | 217 | } |
218 | } | 218 | } |
@@ -279,12 +279,12 @@ impl Ty { | |||
279 | 279 | ||
280 | /// This creates Substs for a trait with the given Self type and type variables | 280 | /// This creates Substs for a trait with the given Self type and type variables |
281 | /// for all other parameters, to query Chalk with it. | 281 | /// for all other parameters, to query Chalk with it. |
282 | fn canonical_trait_ref( | 282 | fn generic_implements_goal( |
283 | db: &impl HirDatabase, | 283 | db: &impl HirDatabase, |
284 | env: Arc<Environment>, | 284 | env: Arc<Environment>, |
285 | trait_: Trait, | 285 | trait_: Trait, |
286 | self_ty: Canonical<Ty>, | 286 | self_ty: Canonical<Ty>, |
287 | ) -> Canonical<InEnvironment<TraitRef>> { | 287 | ) -> Canonical<InEnvironment<super::Obligation>> { |
288 | let mut substs = Vec::new(); | 288 | let mut substs = Vec::new(); |
289 | let generics = trait_.generic_params(db); | 289 | let generics = trait_.generic_params(db); |
290 | let num_vars = self_ty.num_vars; | 290 | let num_vars = self_ty.num_vars; |
@@ -297,8 +297,8 @@ fn canonical_trait_ref( | |||
297 | .enumerate() | 297 | .enumerate() |
298 | .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)), | 298 | .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)), |
299 | ); | 299 | ); |
300 | Canonical { | 300 | let num_vars = substs.len() - 1 + self_ty.num_vars; |
301 | num_vars: substs.len() - 1 + self_ty.num_vars, | 301 | let trait_ref = TraitRef { trait_, substs: substs.into() }; |
302 | value: InEnvironment::new(env, TraitRef { trait_, substs: substs.into() }), | 302 | let obligation = super::Obligation::Trait(trait_ref); |
303 | } | 303 | Canonical { num_vars, value: InEnvironment::new(env, obligation) } |
304 | } | 304 | } |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 01f350bc1..d99843319 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -93,7 +93,7 @@ impl<T> InEnvironment<T> { | |||
93 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | 93 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that |
94 | /// a certain type implements a certain trait. Proving the Obligation might | 94 | /// a certain type implements a certain trait. Proving the Obligation might |
95 | /// result in additional information about inference variables. | 95 | /// result in additional information about inference variables. |
96 | #[derive(Clone, Debug, PartialEq, Eq)] | 96 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
97 | pub enum Obligation { | 97 | pub enum Obligation { |
98 | /// Prove that a certain type implements a trait (the type is the `Self` type | 98 | /// Prove that a certain type implements a trait (the type is the `Self` type |
99 | /// parameter to the `TraitRef`). | 99 | /// parameter to the `TraitRef`). |
@@ -116,11 +116,11 @@ pub struct ProjectionPredicate { | |||
116 | pub ty: Ty, | 116 | pub ty: Ty, |
117 | } | 117 | } |
118 | 118 | ||
119 | /// Check using Chalk whether trait is implemented for given parameters including `Self` type. | 119 | /// Solve a trait goal using Chalk. |
120 | pub(crate) fn implements_query( | 120 | pub(crate) fn solve_query( |
121 | db: &impl HirDatabase, | 121 | db: &impl HirDatabase, |
122 | krate: Crate, | 122 | krate: Crate, |
123 | trait_ref: Canonical<InEnvironment<TraitRef>>, | 123 | trait_ref: Canonical<InEnvironment<Obligation>>, |
124 | ) -> Option<Solution> { | 124 | ) -> Option<Solution> { |
125 | let _p = profile("implements_query"); | 125 | let _p = profile("implements_query"); |
126 | let canonical = trait_ref.to_chalk(db).cast(); | 126 | let canonical = trait_ref.to_chalk(db).cast(); |
@@ -131,19 +131,6 @@ pub(crate) fn implements_query( | |||
131 | solution.map(|solution| solution_from_chalk(db, solution)) | 131 | solution.map(|solution| solution_from_chalk(db, solution)) |
132 | } | 132 | } |
133 | 133 | ||
134 | pub(crate) fn normalize_query( | ||
135 | db: &impl HirDatabase, | ||
136 | krate: Crate, | ||
137 | projection: Canonical<InEnvironment<ProjectionPredicate>>, | ||
138 | ) -> Option<Solution> { | ||
139 | let canonical = projection.to_chalk(db).cast(); | ||
140 | // We currently don't deal with universes (I think / hope they're not yet | ||
141 | // relevant for our use cases?) | ||
142 | let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; | ||
143 | let solution = solve(db, krate, &u_canonical); | ||
144 | solution.map(|solution| solution_from_chalk(db, solution)) | ||
145 | } | ||
146 | |||
147 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { | 134 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { |
148 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| { | 135 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| { |
149 | let value = subst | 136 | let value = subst |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 32a45731d..2df4dd13f 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -12,7 +12,7 @@ use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | |||
12 | use ra_db::salsa::{InternId, InternKey}; | 12 | use ra_db::salsa::{InternId, InternKey}; |
13 | use test_utils::tested_by; | 13 | use test_utils::tested_by; |
14 | 14 | ||
15 | use super::{Canonical, ChalkContext}; | 15 | use super::{Canonical, ChalkContext, Obligation}; |
16 | use crate::{ | 16 | use crate::{ |
17 | db::HirDatabase, | 17 | db::HirDatabase, |
18 | generics::GenericDef, | 18 | generics::GenericDef, |
@@ -233,6 +233,21 @@ impl ToChalk for super::ProjectionPredicate { | |||
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | impl ToChalk for Obligation { | ||
237 | type Chalk = chalk_ir::DomainGoal; | ||
238 | |||
239 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { | ||
240 | match self { | ||
241 | Obligation::Trait(tr) => tr.to_chalk(db).cast(), | ||
242 | Obligation::Projection(pr) => pr.to_chalk(db).cast(), | ||
243 | } | ||
244 | } | ||
245 | |||
246 | fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { | ||
247 | unimplemented!() | ||
248 | } | ||
249 | } | ||
250 | |||
236 | impl<T> ToChalk for Canonical<T> | 251 | impl<T> ToChalk for Canonical<T> |
237 | where | 252 | where |
238 | T: ToChalk, | 253 | T: ToChalk, |
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 2a1af0a0a..efc9a92de 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs | |||
@@ -295,8 +295,7 @@ impl RootDatabase { | |||
295 | hir::db::TraitDatumQuery | 295 | hir::db::TraitDatumQuery |
296 | hir::db::StructDatumQuery | 296 | hir::db::StructDatumQuery |
297 | hir::db::ImplDatumQuery | 297 | hir::db::ImplDatumQuery |
298 | hir::db::ImplementsQuery | 298 | hir::db::SolveQuery |
299 | hir::db::NormalizeQuery | ||
300 | ]; | 299 | ]; |
301 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); | 300 | acc.sort_by_key(|it| std::cmp::Reverse(it.1)); |
302 | acc | 301 | acc |