diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-07-09 08:50:18 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-07-09 08:50:18 +0100 |
commit | f59cd1a4a0d6c369025a7014e838d25f91d478e4 (patch) | |
tree | 2c4b9dc868a87507ed63e9dc46530cc60f38ae64 /crates/ra_hir/src/ty/traits | |
parent | 35f28c538a9b9f461bb4db1a78d02e9f02a3d296 (diff) | |
parent | 9afbf2dff43dee3227358f10162d4c77d192ce7a (diff) |
Merge #1515
1515: Trait environment r=matklad a=flodiebold
This adds the environment, i.e. the set of `where` clauses in scope, when solving trait goals. That means that e.g. in
```rust
fn foo<T: SomeTrait>(t: T) {}
```
, we are able to complete methods of `SomeTrait` on the `t`. This affects the trait APIs quite a bit (since every method that needs to be able to solve for some trait needs to get this environment somehow), so I thought I'd do it rather sooner than later ;)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/traits')
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 4c3744b44..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::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, |
@@ -218,6 +218,103 @@ impl ToChalk for ProjectionTy { | |||
218 | } | 218 | } |
219 | } | 219 | } |
220 | 220 | ||
221 | impl ToChalk for super::ProjectionPredicate { | ||
222 | type Chalk = chalk_ir::Normalize; | ||
223 | |||
224 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { | ||
225 | chalk_ir::Normalize { | ||
226 | projection: self.projection_ty.to_chalk(db), | ||
227 | ty: self.ty.to_chalk(db), | ||
228 | } | ||
229 | } | ||
230 | |||
231 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { | ||
232 | unimplemented!() | ||
233 | } | ||
234 | } | ||
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 | |||
251 | impl<T> ToChalk for Canonical<T> | ||
252 | where | ||
253 | T: ToChalk, | ||
254 | { | ||
255 | type Chalk = chalk_ir::Canonical<T::Chalk>; | ||
256 | |||
257 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | ||
258 | let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); | ||
259 | let value = self.value.to_chalk(db); | ||
260 | let canonical = chalk_ir::Canonical { value, binders: vec![parameter; self.num_vars] }; | ||
261 | canonical | ||
262 | } | ||
263 | |||
264 | fn from_chalk(db: &impl HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | ||
265 | Canonical { num_vars: canonical.binders.len(), value: from_chalk(db, canonical.value) } | ||
266 | } | ||
267 | } | ||
268 | |||
269 | impl ToChalk for Arc<super::Environment> { | ||
270 | type Chalk = Arc<chalk_ir::Environment>; | ||
271 | |||
272 | fn to_chalk(self, db: &impl HirDatabase) -> Arc<chalk_ir::Environment> { | ||
273 | let mut clauses = Vec::new(); | ||
274 | for pred in &self.predicates { | ||
275 | if pred.is_error() { | ||
276 | // for env, we just ignore errors | ||
277 | continue; | ||
278 | } | ||
279 | if let GenericPredicate::Implemented(trait_ref) = pred { | ||
280 | if blacklisted_trait(db, trait_ref.trait_) { | ||
281 | continue; | ||
282 | } | ||
283 | } | ||
284 | clauses.push(pred.clone().to_chalk(db).cast()); | ||
285 | } | ||
286 | chalk_ir::Environment::new().add_clauses(clauses) | ||
287 | } | ||
288 | |||
289 | fn from_chalk( | ||
290 | _db: &impl HirDatabase, | ||
291 | _env: Arc<chalk_ir::Environment>, | ||
292 | ) -> Arc<super::Environment> { | ||
293 | unimplemented!() | ||
294 | } | ||
295 | } | ||
296 | |||
297 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> { | ||
298 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | ||
299 | |||
300 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | ||
301 | chalk_ir::InEnvironment { | ||
302 | environment: self.environment.to_chalk(db), | ||
303 | goal: self.value.to_chalk(db), | ||
304 | } | ||
305 | } | ||
306 | |||
307 | fn from_chalk( | ||
308 | db: &impl HirDatabase, | ||
309 | in_env: chalk_ir::InEnvironment<T::Chalk>, | ||
310 | ) -> super::InEnvironment<T> { | ||
311 | super::InEnvironment { | ||
312 | environment: from_chalk(db, in_env.environment), | ||
313 | value: from_chalk(db, in_env.goal), | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
221 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 318 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { |
222 | chalk_ir::Binders { | 319 | chalk_ir::Binders { |
223 | value, | 320 | value, |