Skip to content

Commit 638100d

Browse files
committed
Refactor a bit & introduce Environment struct
1 parent 3210002 commit 638100d

File tree

7 files changed

+107
-21
lines changed

7 files changed

+107
-21
lines changed

crates/ra_hir/src/db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
217217
fn implements(
218218
&self,
219219
krate: Crate,
220-
goal: crate::ty::Canonical<crate::ty::TraitRef>,
220+
goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::TraitRef>>,
221221
) -> Option<crate::ty::traits::Solution>;
222222

223223
#[salsa::invoke(crate::ty::traits::normalize_query)]

crates/ra_hir/src/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub(crate) use lower::{
2626
callable_item_sig, generic_defaults_query, generic_predicates_query, type_for_def,
2727
type_for_field, TypableDef,
2828
};
29-
pub(crate) use traits::ProjectionPredicate;
29+
pub(crate) use traits::{Environment, InEnvironment, ProjectionPredicate};
3030

3131
/// A type constructor or type name: this might be something like the primitive
3232
/// type `bool`, a struct like `Vec`, or things like function pointers or

crates/ra_hir/src/ty/infer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ use test_utils::tested_by;
2929
use super::{
3030
autoderef, method_resolution, op, primitive,
3131
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,
3334
};
3435
use crate::{
3536
adt::VariantDef,
@@ -330,7 +331,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
330331
for obligation in obligations {
331332
match &obligation {
332333
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);
334337
let solution = self
335338
.db
336339
.implements(self.resolver.krate().unwrap(), canonicalized.value.clone());

crates/ra_hir/src/ty/infer/unify.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
33
use super::InferenceContext;
44
use crate::db::HirDatabase;
5-
use crate::ty::{Canonical, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty};
5+
use crate::ty::{
6+
Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty,
7+
};
68

79
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
810
pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D>
@@ -105,14 +107,24 @@ where
105107
ProjectionPredicate { ty, projection_ty }
106108
}
107109

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+
108113
pub fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
109114
let result = self.do_canonicalize_ty(ty);
110115
self.into_canonicalized(result)
111116
}
112117

113-
pub fn canonicalize_trait_ref(mut self, trait_ref: TraitRef) -> Canonicalized<TraitRef> {
114-
let result = self.do_canonicalize_trait_ref(trait_ref);
115-
self.into_canonicalized(result)
118+
pub fn canonicalize_trait_ref(
119+
mut self,
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+
})
116128
}
117129

118130
pub fn canonicalize_projection(

crates/ra_hir/src/ty/method_resolution.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::sync::Arc;
77
use arrayvec::ArrayVec;
88
use rustc_hash::FxHashMap;
99

10-
use super::{autoderef, Canonical, TraitRef};
10+
use super::{autoderef, Canonical, Environment, InEnvironment, TraitRef};
1111
use crate::{
1212
generics::HasGenericParams,
1313
impl_block::{ImplBlock, ImplId, ImplItem},
@@ -209,7 +209,8 @@ fn iterate_trait_method_candidates<T>(
209209
let data = m.data(db);
210210
if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
211211
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());
213214
if db.implements(krate, trait_ref).is_none() {
214215
continue 'traits;
215216
}
@@ -279,9 +280,10 @@ impl Ty {
279280
/// for all other parameters, to query Chalk with it.
280281
fn canonical_trait_ref(
281282
db: &impl HirDatabase,
283+
env: Arc<Environment>,
282284
trait_: Trait,
283285
self_ty: Canonical<Ty>,
284-
) -> Canonical<TraitRef> {
286+
) -> Canonical<InEnvironment<TraitRef>> {
285287
let mut substs = Vec::new();
286288
let generics = trait_.generic_params(db);
287289
let num_vars = self_ty.num_vars;
@@ -296,6 +298,6 @@ fn canonical_trait_ref(
296298
);
297299
Canonical {
298300
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() }),
300302
}
301303
}

crates/ra_hir/src/ty/traits.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,27 @@ fn solve(
6767
solution
6868
}
6969

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)]
76+
pub struct Environment;
77+
78+
/// Something (usually a goal), along with an environment.
79+
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
80+
pub struct InEnvironment<T> {
81+
pub environment: Arc<Environment>,
82+
pub value: T,
83+
}
84+
85+
impl<T> InEnvironment<T> {
86+
pub fn new(environment: Arc<Environment>, value: T) -> InEnvironment<T> {
87+
InEnvironment { environment, value }
88+
}
89+
}
90+
7091
/// Something that needs to be proven (by Chalk) during type checking, e.g. that
7192
/// a certain type implements a certain trait. Proving the Obligation might
7293
/// result in additional information about inference variables.
@@ -97,16 +118,10 @@ pub struct ProjectionPredicate {
97118
pub(crate) fn implements_query(
98119
db: &impl HirDatabase,
99120
krate: Crate,
100-
trait_ref: Canonical<TraitRef>,
121+
trait_ref: Canonical<InEnvironment<TraitRef>>,
101122
) -> Option<Solution> {
102123
let _p = profile("implements_query");
103-
let goal: chalk_ir::Goal = trait_ref.value.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] };
124+
let canonical = trait_ref.to_chalk(db).cast();
110125
// We currently don't deal with universes (I think / hope they're not yet
111126
// relevant for our use cases?)
112127
let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };

crates/ra_hir/src/ty/traits/chalk.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
1212
use ra_db::salsa::{InternId, InternKey};
1313
use test_utils::tested_by;
1414

15-
use super::ChalkContext;
15+
use super::{Canonical, ChalkContext};
1616
use crate::{
1717
db::HirDatabase,
1818
generics::GenericDef,
@@ -218,6 +218,60 @@ impl ToChalk for ProjectionTy {
218218
}
219219
}
220220

221+
impl<T> ToChalk for Canonical<T>
222+
where
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+
239+
impl 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+
254+
impl<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+
221275
fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> {
222276
chalk_ir::Binders {
223277
value,

0 commit comments

Comments
 (0)