aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-06-29 16:40:00 +0100
committerFlorian Diebold <[email protected]>2019-07-08 20:20:17 +0100
commit638100dc8bea69cc4093d15f1641ed39a8d27a43 (patch)
treebb7cf46f4095e9e427f7d4277f28693a3bd671a6 /crates/ra_hir/src/ty
parent32100022010ecfefd1ea06caa71d1a508d2eb75d (diff)
Refactor a bit & introduce Environment struct
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs7
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs20
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs10
-rw-r--r--crates/ra_hir/src/ty/traits.rs31
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs56
5 files changed, 105 insertions, 19 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 52a49070a..84edd3d46 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -29,7 +29,8 @@ use test_utils::tested_by;
29use super::{ 29use super::{
30 autoderef, method_resolution, op, primitive, 30 autoderef, method_resolution, op, primitive,
31 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 31 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
32 ApplicationTy, CallableDef, ProjectionTy, Substs, TraitRef, Ty, TypableDef, TypeCtor, 32 ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitRef, Ty, TypableDef,
33 TypeCtor,
33}; 34};
34use crate::{ 35use crate::{
35 adt::VariantDef, 36 adt::VariantDef,
@@ -330,7 +331,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
330 for obligation in obligations { 331 for obligation in obligations {
331 match &obligation { 332 match &obligation {
332 Obligation::Trait(tr) => { 333 Obligation::Trait(tr) => {
333 let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone()); 334 let env = Arc::new(super::Environment); // FIXME add environment
335 let in_env = InEnvironment::new(env, tr.clone());
336 let canonicalized = self.canonicalizer().canonicalize_trait_ref(in_env);
334 let solution = self 337 let solution = self
335 .db 338 .db
336 .implements(self.resolver.krate().unwrap(), canonicalized.value.clone()); 339 .implements(self.resolver.krate().unwrap(), canonicalized.value.clone());
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index a24e5eb5c..ad2eefcaf 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -2,7 +2,9 @@
2 2
3use super::InferenceContext; 3use super::InferenceContext;
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{Canonical, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty}; 5use crate::ty::{
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty,
7};
6 8
7impl<'a, D: HirDatabase> InferenceContext<'a, D> { 9impl<'a, D: HirDatabase> InferenceContext<'a, D> {
8 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D> 10 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D>
@@ -105,14 +107,24 @@ where
105 ProjectionPredicate { ty, projection_ty } 107 ProjectionPredicate { ty, projection_ty }
106 } 108 }
107 109
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)
112
108 pub fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { 113 pub fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
109 let result = self.do_canonicalize_ty(ty); 114 let result = self.do_canonicalize_ty(ty);
110 self.into_canonicalized(result) 115 self.into_canonicalized(result)
111 } 116 }
112 117
113 pub fn canonicalize_trait_ref(mut self, trait_ref: TraitRef) -> Canonicalized<TraitRef> { 118 pub fn canonicalize_trait_ref(
114 let result = self.do_canonicalize_trait_ref(trait_ref); 119 mut self,
115 self.into_canonicalized(result) 120 trait_ref_in_env: InEnvironment<TraitRef>,
121 ) -> Canonicalized<InEnvironment<TraitRef>> {
122 let result = self.do_canonicalize_trait_ref(trait_ref_in_env.value);
123 // FIXME canonicalize env
124 self.into_canonicalized(InEnvironment {
125 value: result,
126 environment: trait_ref_in_env.environment,
127 })
116 } 128 }
117 129
118 pub fn canonicalize_projection( 130 pub fn canonicalize_projection(
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 76ace66ea..770e1964e 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -7,7 +7,7 @@ use std::sync::Arc;
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9 9
10use super::{autoderef, Canonical, TraitRef}; 10use super::{autoderef, Canonical, Environment, InEnvironment, TraitRef};
11use crate::{ 11use crate::{
12 generics::HasGenericParams, 12 generics::HasGenericParams,
13 impl_block::{ImplBlock, ImplId, ImplItem}, 13 impl_block::{ImplBlock, ImplId, ImplItem},
@@ -209,7 +209,8 @@ fn iterate_trait_method_candidates<T>(
209 let data = m.data(db); 209 let data = m.data(db);
210 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 210 if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
211 if !known_implemented { 211 if !known_implemented {
212 let trait_ref = canonical_trait_ref(db, t, ty.clone()); 212 let env = Arc::new(super::Environment); // FIXME add environment
213 let trait_ref = canonical_trait_ref(db, env, t, ty.clone());
213 if db.implements(krate, trait_ref).is_none() { 214 if db.implements(krate, trait_ref).is_none() {
214 continue 'traits; 215 continue 'traits;
215 } 216 }
@@ -279,9 +280,10 @@ impl Ty {
279/// for all other parameters, to query Chalk with it. 280/// for all other parameters, to query Chalk with it.
280fn canonical_trait_ref( 281fn canonical_trait_ref(
281 db: &impl HirDatabase, 282 db: &impl HirDatabase,
283 env: Arc<Environment>,
282 trait_: Trait, 284 trait_: Trait,
283 self_ty: Canonical<Ty>, 285 self_ty: Canonical<Ty>,
284) -> Canonical<TraitRef> { 286) -> Canonical<InEnvironment<TraitRef>> {
285 let mut substs = Vec::new(); 287 let mut substs = Vec::new();
286 let generics = trait_.generic_params(db); 288 let generics = trait_.generic_params(db);
287 let num_vars = self_ty.num_vars; 289 let num_vars = self_ty.num_vars;
@@ -296,6 +298,6 @@ fn canonical_trait_ref(
296 ); 298 );
297 Canonical { 299 Canonical {
298 num_vars: substs.len() - 1 + self_ty.num_vars, 300 num_vars: substs.len() - 1 + self_ty.num_vars,
299 value: TraitRef { trait_, substs: substs.into() }, 301 value: InEnvironment::new(env, TraitRef { trait_, substs: substs.into() }),
300 } 302 }
301} 303}
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 3e28852b6..718970553 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -67,6 +67,27 @@ fn solve(
67 solution 67 solution
68} 68}
69 69
70/// A set of clauses that we assume to be true. E.g. if we are inside this function:
71/// ```rust
72/// fn foo<T: Default>(t: T) {}
73/// ```
74/// we assume that `T: Default`.
75#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
76pub struct Environment;
77
78/// Something (usually a goal), along with an environment.
79#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
80pub struct InEnvironment<T> {
81 pub environment: Arc<Environment>,
82 pub value: T,
83}
84
85impl<T> InEnvironment<T> {
86 pub fn new(environment: Arc<Environment>, value: T) -> InEnvironment<T> {
87 InEnvironment { environment, value }
88 }
89}
90
70/// Something that needs to be proven (by Chalk) during type checking, e.g. that 91/// Something that needs to be proven (by Chalk) during type checking, e.g. that
71/// a certain type implements a certain trait. Proving the Obligation might 92/// a certain type implements a certain trait. Proving the Obligation might
72/// result in additional information about inference variables. 93/// result in additional information about inference variables.
@@ -97,16 +118,10 @@ pub struct ProjectionPredicate {
97pub(crate) fn implements_query( 118pub(crate) fn implements_query(
98 db: &impl HirDatabase, 119 db: &impl HirDatabase,
99 krate: Crate, 120 krate: Crate,
100 trait_ref: Canonical<TraitRef>, 121 trait_ref: Canonical<InEnvironment<TraitRef>>,
101) -> Option<Solution> { 122) -> Option<Solution> {
102 let _p = profile("implements_query"); 123 let _p = profile("implements_query");
103 let goal: chalk_ir::Goal = trait_ref.value.to_chalk(db).cast(); 124 let canonical = trait_ref.to_chalk(db).cast();
104 debug!("goal: {:?}", goal);
105 let env = chalk_ir::Environment::new();
106 let in_env = chalk_ir::InEnvironment::new(&env, goal);
107 let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT);
108 let canonical =
109 chalk_ir::Canonical { value: in_env, binders: vec![parameter; trait_ref.num_vars] };
110 // We currently don't deal with universes (I think / hope they're not yet 125 // We currently don't deal with universes (I think / hope they're not yet
111 // relevant for our use cases?) 126 // relevant for our use cases?)
112 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; 127 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 4c3744b44..bee35fa62 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::ChalkContext; 15use super::{Canonical, ChalkContext};
16use crate::{ 16use crate::{
17 db::HirDatabase, 17 db::HirDatabase,
18 generics::GenericDef, 18 generics::GenericDef,
@@ -218,6 +218,60 @@ impl ToChalk for ProjectionTy {
218 } 218 }
219} 219}
220 220
221impl<T> ToChalk for Canonical<T>
222where
223 T: ToChalk,
224{
225 type Chalk = chalk_ir::Canonical<T::Chalk>;
226
227 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
228 let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT);
229 let value = self.value.to_chalk(db);
230 let canonical = chalk_ir::Canonical { value, binders: vec![parameter; self.num_vars] };
231 canonical
232 }
233
234 fn from_chalk(db: &impl HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
235 Canonical { num_vars: canonical.binders.len(), value: from_chalk(db, canonical.value) }
236 }
237}
238
239impl ToChalk for Arc<super::Environment> {
240 type Chalk = Arc<chalk_ir::Environment>;
241
242 fn to_chalk(self, _db: &impl HirDatabase) -> Arc<chalk_ir::Environment> {
243 chalk_ir::Environment::new()
244 }
245
246 fn from_chalk(
247 _db: &impl HirDatabase,
248 _env: Arc<chalk_ir::Environment>,
249 ) -> Arc<super::Environment> {
250 Arc::new(super::Environment)
251 }
252}
253
254impl<T: ToChalk> ToChalk for super::InEnvironment<T> {
255 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
256
257 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
258 chalk_ir::InEnvironment {
259 environment: self.environment.to_chalk(db),
260 goal: self.value.to_chalk(db),
261 }
262 }
263
264 fn from_chalk(
265 db: &impl HirDatabase,
266 in_env: chalk_ir::InEnvironment<T::Chalk>,
267 ) -> super::InEnvironment<T> {
268 super::InEnvironment {
269 environment: from_chalk(db, in_env.environment),
270 value: from_chalk(db, in_env.goal),
271 }
272 }
273}
274
221fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { 275fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> {
222 chalk_ir::Binders { 276 chalk_ir::Binders {
223 value, 277 value,