Skip to content

Commit 9afbf2d

Browse files
committed
Unify normalize and implements to simplify code
1 parent 15862fc commit 9afbf2d

File tree

9 files changed

+67
-107
lines changed

9 files changed

+67
-107
lines changed

crates/ra_hir/src/db.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,11 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
213213
#[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)]
214214
fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>;
215215

216-
#[salsa::invoke(crate::ty::traits::implements_query)]
217-
fn implements(
216+
#[salsa::invoke(crate::ty::traits::solve_query)]
217+
fn solve(
218218
&self,
219219
krate: Crate,
220-
goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::TraitRef>>,
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>>,
220+
goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::Obligation>>,
228221
) -> Option<crate::ty::traits::Solution>;
229222
}
230223

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::{Environment, InEnvironment, ProjectionPredicate};
29+
pub(crate) use traits::{Environment, InEnvironment, Obligation, 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/autoderef.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@ fn deref_by_trait(
6262
},
6363
};
6464

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 };
6668

6769
let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env };
6870

69-
let solution = db.normalize(krate, canonical)?;
71+
let solution = db.solve(krate, canonical)?;
7072

7173
match &solution {
7274
Solution::Unique(vars) => {

crates/ra_hir/src/ty/infer.rs

Lines changed: 18 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -331,53 +331,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
331331
fn resolve_obligations_as_possible(&mut self) {
332332
let obligations = mem::replace(&mut self.obligations, Vec::new());
333333
for obligation in obligations {
334-
match &obligation {
335-
Obligation::Trait(tr) => {
336-
let in_env = InEnvironment::new(self.trait_env.clone(), tr.clone());
337-
let canonicalized = self.canonicalizer().canonicalize_trait_ref(in_env);
338-
let solution = self
339-
.db
340-
.implements(self.resolver.krate().unwrap(), canonicalized.value.clone());
341-
match solution {
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-
};
334+
let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone());
335+
let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
336+
let solution =
337+
self.db.solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
338+
339+
match solution {
340+
Some(Solution::Unique(substs)) => {
341+
canonicalized.apply_solution(self, substs.0);
357342
}
358-
Obligation::Projection(pr) => {
359-
let in_env = InEnvironment::new(self.trait_env.clone(), pr.clone());
360-
let canonicalized = self.canonicalizer().canonicalize_projection(in_env);
361-
let solution = self
362-
.db
363-
.normalize(self.resolver.krate().unwrap(), canonicalized.value.clone());
364-
365-
match solution {
366-
Some(Solution::Unique(substs)) => {
367-
canonicalized.apply_solution(self, substs.0);
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-
};
343+
Some(Solution::Ambig(Guidance::Definite(substs))) => {
344+
canonicalized.apply_solution(self, substs.0);
345+
self.obligations.push(obligation);
346+
}
347+
Some(_) => {
348+
// FIXME use this when trying to resolve everything at the end
349+
self.obligations.push(obligation);
350+
}
351+
None => {
352+
// FIXME obligation cannot be fulfilled => diagnostic
381353
}
382354
};
383355
}

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

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Unification and canonicalization logic.
22
3-
use super::InferenceContext;
3+
use super::{InferenceContext, Obligation};
44
use crate::db::HirDatabase;
55
use crate::ty::{
66
Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty,
@@ -110,32 +110,24 @@ where
110110
// FIXME: add some point, we need to introduce a `Fold` trait that abstracts
111111
// over all the things that can be canonicalized (like Chalk and rustc have)
112112

113-
pub fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
113+
pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
114114
let result = self.do_canonicalize_ty(ty);
115115
self.into_canonicalized(result)
116116
}
117117

118-
pub fn canonicalize_trait_ref(
118+
pub(crate) fn canonicalize_obligation(
119119
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-
})
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
120+
obligation: InEnvironment<Obligation>,
121+
) -> Canonicalized<InEnvironment<Obligation>> {
122+
let result = match obligation.value {
123+
Obligation::Trait(tr) => Obligation::Trait(self.do_canonicalize_trait_ref(tr)),
124+
Obligation::Projection(pr) => {
125+
Obligation::Projection(self.do_canonicalize_projection_predicate(pr))
126+
}
127+
};
136128
self.into_canonicalized(InEnvironment {
137129
value: result,
138-
environment: projection.environment,
130+
environment: obligation.environment,
139131
})
140132
}
141133
}

crates/ra_hir/src/ty/method_resolution.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ fn iterate_trait_method_candidates<T>(
211211
let data = m.data(db);
212212
if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
213213
if !known_implemented {
214-
let trait_ref = canonical_trait_ref(db, env.clone(), t, ty.clone());
215-
if db.implements(krate, trait_ref).is_none() {
214+
let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
215+
if db.solve(krate, goal).is_none() {
216216
continue 'traits;
217217
}
218218
}
@@ -279,12 +279,12 @@ impl Ty {
279279

280280
/// This creates Substs for a trait with the given Self type and type variables
281281
/// for all other parameters, to query Chalk with it.
282-
fn canonical_trait_ref(
282+
fn generic_implements_goal(
283283
db: &impl HirDatabase,
284284
env: Arc<Environment>,
285285
trait_: Trait,
286286
self_ty: Canonical<Ty>,
287-
) -> Canonical<InEnvironment<TraitRef>> {
287+
) -> Canonical<InEnvironment<super::Obligation>> {
288288
let mut substs = Vec::new();
289289
let generics = trait_.generic_params(db);
290290
let num_vars = self_ty.num_vars;
@@ -297,8 +297,8 @@ fn canonical_trait_ref(
297297
.enumerate()
298298
.map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
299299
);
300-
Canonical {
301-
num_vars: substs.len() - 1 + self_ty.num_vars,
302-
value: InEnvironment::new(env, TraitRef { trait_, substs: substs.into() }),
303-
}
300+
let num_vars = substs.len() - 1 + self_ty.num_vars;
301+
let trait_ref = TraitRef { trait_, substs: substs.into() };
302+
let obligation = super::Obligation::Trait(trait_ref);
303+
Canonical { num_vars, value: InEnvironment::new(env, obligation) }
304304
}

crates/ra_hir/src/ty/traits.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl<T> InEnvironment<T> {
9393
/// Something that needs to be proven (by Chalk) during type checking, e.g. that
9494
/// a certain type implements a certain trait. Proving the Obligation might
9595
/// result in additional information about inference variables.
96-
#[derive(Clone, Debug, PartialEq, Eq)]
96+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
9797
pub enum Obligation {
9898
/// Prove that a certain type implements a trait (the type is the `Self` type
9999
/// parameter to the `TraitRef`).
@@ -116,11 +116,11 @@ pub struct ProjectionPredicate {
116116
pub ty: Ty,
117117
}
118118

119-
/// Check using Chalk whether trait is implemented for given parameters including `Self` type.
120-
pub(crate) fn implements_query(
119+
/// Solve a trait goal using Chalk.
120+
pub(crate) fn solve_query(
121121
db: &impl HirDatabase,
122122
krate: Crate,
123-
trait_ref: Canonical<InEnvironment<TraitRef>>,
123+
trait_ref: Canonical<InEnvironment<Obligation>>,
124124
) -> Option<Solution> {
125125
let _p = profile("implements_query");
126126
let canonical = trait_ref.to_chalk(db).cast();
@@ -131,19 +131,6 @@ pub(crate) fn implements_query(
131131
solution.map(|solution| solution_from_chalk(db, solution))
132132
}
133133

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-
147134
fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution {
148135
let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| {
149136
let value = subst

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

Lines changed: 16 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::{Canonical, ChalkContext};
15+
use super::{Canonical, ChalkContext, Obligation};
1616
use crate::{
1717
db::HirDatabase,
1818
generics::GenericDef,
@@ -233,6 +233,21 @@ impl ToChalk for super::ProjectionPredicate {
233233
}
234234
}
235235

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+
236251
impl<T> ToChalk for Canonical<T>
237252
where
238253
T: ToChalk,

crates/ra_ide_api/src/change.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,7 @@ impl RootDatabase {
295295
hir::db::TraitDatumQuery
296296
hir::db::StructDatumQuery
297297
hir::db::ImplDatumQuery
298-
hir::db::ImplementsQuery
299-
hir::db::NormalizeQuery
298+
hir::db::SolveQuery
300299
];
301300
acc.sort_by_key(|it| std::cmp::Reverse(it.1));
302301
acc

0 commit comments

Comments
 (0)