aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-07-08 20:43:52 +0100
committerFlorian Diebold <[email protected]>2019-07-08 20:47:37 +0100
commit9afbf2dff43dee3227358f10162d4c77d192ce7a (patch)
tree82d38315b9be21dec920f59389ea89cdb3ae0a41 /crates/ra_hir/src
parent15862fc04183c7f9b3f3af666336a594a6a52cd9 (diff)
Unify `normalize` and `implements` to simplify code
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/db.rs13
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs6
-rw-r--r--crates/ra_hir/src/ty/infer.rs64
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs32
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs16
-rw-r--r--crates/ra_hir/src/ty/traits.rs21
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs17
8 files changed, 66 insertions, 105 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};
29pub(crate) use traits::{Environment, InEnvironment, ProjectionPredicate}; 29pub(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
3use super::InferenceContext; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{ 5use 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.
282fn canonical_trait_ref( 282fn 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)]
97pub enum Obligation { 97pub 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.
120pub(crate) fn implements_query( 120pub(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
134pub(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
147fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { 134fn 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};
12use ra_db::salsa::{InternId, InternKey}; 12use ra_db::salsa::{InternId, InternKey};
13use test_utils::tested_by; 13use test_utils::tested_by;
14 14
15use super::{Canonical, ChalkContext}; 15use super::{Canonical, ChalkContext, Obligation};
16use crate::{ 16use 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
236impl 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
236impl<T> ToChalk for Canonical<T> 251impl<T> ToChalk for Canonical<T>
237where 252where
238 T: ToChalk, 253 T: ToChalk,