diff options
Diffstat (limited to 'crates/ra_hir_ty/src/traits')
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 201 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 77 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/interner.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/mapping.rs | 62 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/tls.rs | 2 |
5 files changed, 132 insertions, 225 deletions
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 6d5f2d46a..86e22e459 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs | |||
@@ -1,15 +1,12 @@ | |||
1 | //! This module provides the built-in trait implementations, e.g. to make | 1 | //! This module provides the built-in trait implementations, e.g. to make |
2 | //! closures implement `Fn`. | 2 | //! closures implement `Fn`. |
3 | use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; | 3 | use hir_def::{expr::Expr, TraitId, TypeAliasId}; |
4 | use hir_expand::name::name; | 4 | use hir_expand::name::name; |
5 | use ra_db::CrateId; | 5 | use ra_db::CrateId; |
6 | 6 | ||
7 | use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData}; | 7 | use super::{AssocTyValue, Impl}; |
8 | use crate::{ | 8 | use crate::{ |
9 | db::HirDatabase, | 9 | db::HirDatabase, ApplicationTy, BoundVar, DebruijnIndex, Substs, TraitRef, Ty, TypeCtor, |
10 | utils::{all_super_traits, generics}, | ||
11 | ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty, | ||
12 | TypeCtor, TypeWalk, | ||
13 | }; | 10 | }; |
14 | 11 | ||
15 | pub(super) struct BuiltinImplData { | 12 | pub(super) struct BuiltinImplData { |
@@ -31,7 +28,7 @@ pub(super) fn get_builtin_impls( | |||
31 | krate: CrateId, | 28 | krate: CrateId, |
32 | ty: &Ty, | 29 | ty: &Ty, |
33 | // The first argument for the trait, if present | 30 | // The first argument for the trait, if present |
34 | arg: &Option<Ty>, | 31 | _arg: &Option<Ty>, |
35 | trait_: TraitId, | 32 | trait_: TraitId, |
36 | mut callback: impl FnMut(Impl), | 33 | mut callback: impl FnMut(Impl), |
37 | ) { | 34 | ) { |
@@ -50,60 +47,12 @@ pub(super) fn get_builtin_impls( | |||
50 | } | 47 | } |
51 | } | 48 | } |
52 | } | 49 | } |
53 | |||
54 | let unsize_trait = get_unsize_trait(db, krate); | ||
55 | if let Some(actual_trait) = unsize_trait { | ||
56 | if trait_ == actual_trait { | ||
57 | get_builtin_unsize_impls(db, krate, ty, arg, callback); | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | fn get_builtin_unsize_impls( | ||
63 | db: &dyn HirDatabase, | ||
64 | krate: CrateId, | ||
65 | ty: &Ty, | ||
66 | // The first argument for the trait, if present | ||
67 | arg: &Option<Ty>, | ||
68 | mut callback: impl FnMut(Impl), | ||
69 | ) { | ||
70 | if !check_unsize_impl_prerequisites(db, krate) { | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, .. }) = ty { | ||
75 | callback(Impl::UnsizeArray); | ||
76 | return; // array is unsized, the rest of the impls shouldn't apply | ||
77 | } | ||
78 | |||
79 | if let Some(target_trait) = arg.as_ref().and_then(|t| t.dyn_trait_ref()) { | ||
80 | // FIXME what about more complicated dyn tys with marker traits? | ||
81 | if let Some(trait_ref) = ty.dyn_trait_ref() { | ||
82 | if trait_ref.trait_ != target_trait.trait_ { | ||
83 | let super_traits = all_super_traits(db.upcast(), trait_ref.trait_); | ||
84 | if super_traits.contains(&target_trait.trait_) { | ||
85 | callback(Impl::UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData { | ||
86 | trait_: trait_ref.trait_, | ||
87 | super_trait: target_trait.trait_, | ||
88 | })); | ||
89 | } | ||
90 | } | ||
91 | } else { | ||
92 | // FIXME only for sized types | ||
93 | callback(Impl::UnsizeToTraitObject(target_trait.trait_)); | ||
94 | } | ||
95 | } | ||
96 | } | 50 | } |
97 | 51 | ||
98 | pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { | 52 | pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { |
99 | match impl_ { | 53 | match impl_ { |
100 | Impl::ImplDef(_) => unreachable!(), | 54 | Impl::ImplDef(_) => unreachable!(), |
101 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), | 55 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), |
102 | Impl::UnsizeArray => array_unsize_impl_datum(db, krate), | ||
103 | Impl::UnsizeToTraitObject(trait_) => trait_object_unsize_impl_datum(db, krate, trait_), | ||
104 | Impl::UnsizeToSuperTraitObject(data) => { | ||
105 | super_trait_object_unsize_impl_datum(db, krate, data) | ||
106 | } | ||
107 | } | 56 | } |
108 | } | 57 | } |
109 | 58 | ||
@@ -227,145 +176,3 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
227 | value: output_ty, | 176 | value: output_ty, |
228 | } | 177 | } |
229 | } | 178 | } |
230 | |||
231 | // Array unsizing | ||
232 | |||
233 | fn check_unsize_impl_prerequisites(db: &dyn HirDatabase, krate: CrateId) -> bool { | ||
234 | // the Unsize trait needs to exist and have two type parameters (Self and T) | ||
235 | let unsize_trait = match get_unsize_trait(db, krate) { | ||
236 | Some(t) => t, | ||
237 | None => return false, | ||
238 | }; | ||
239 | let generic_params = generics(db.upcast(), unsize_trait.into()); | ||
240 | generic_params.len() == 2 | ||
241 | } | ||
242 | |||
243 | fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplData { | ||
244 | // impl<T> Unsize<[T]> for [T; _] | ||
245 | // (this can be a single impl because we don't distinguish array sizes currently) | ||
246 | |||
247 | let trait_ = get_unsize_trait(db, krate) // get unsize trait | ||
248 | // the existence of the Unsize trait has been checked before | ||
249 | .expect("Unsize trait missing"); | ||
250 | |||
251 | let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | ||
252 | let substs = Substs::builder(2) | ||
253 | .push(Ty::apply_one(TypeCtor::Array, var.clone())) | ||
254 | .push(Ty::apply_one(TypeCtor::Slice, var)) | ||
255 | .build(); | ||
256 | |||
257 | let trait_ref = TraitRef { trait_, substs }; | ||
258 | |||
259 | BuiltinImplData { | ||
260 | num_vars: 1, | ||
261 | trait_ref, | ||
262 | where_clauses: Vec::new(), | ||
263 | assoc_ty_values: Vec::new(), | ||
264 | } | ||
265 | } | ||
266 | |||
267 | // Trait object unsizing | ||
268 | |||
269 | fn trait_object_unsize_impl_datum( | ||
270 | db: &dyn HirDatabase, | ||
271 | krate: CrateId, | ||
272 | trait_: TraitId, | ||
273 | ) -> BuiltinImplData { | ||
274 | // impl<T, T1, ...> Unsize<dyn Trait<T1, ...>> for T where T: Trait<T1, ...> | ||
275 | |||
276 | let unsize_trait = get_unsize_trait(db, krate) // get unsize trait | ||
277 | // the existence of the Unsize trait has been checked before | ||
278 | .expect("Unsize trait missing"); | ||
279 | |||
280 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | ||
281 | |||
282 | let target_substs = Substs::build_for_def(db, trait_) | ||
283 | .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) | ||
284 | .fill_with_bound_vars(DebruijnIndex::ONE, 1) | ||
285 | .build(); | ||
286 | let num_vars = target_substs.len(); | ||
287 | let target_trait_ref = TraitRef { trait_, substs: target_substs }; | ||
288 | let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)]; | ||
289 | |||
290 | let self_substs = | ||
291 | Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); | ||
292 | let self_trait_ref = TraitRef { trait_, substs: self_substs }; | ||
293 | let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; | ||
294 | |||
295 | let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.into())).build(); | ||
296 | |||
297 | let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs }; | ||
298 | |||
299 | BuiltinImplData { num_vars, trait_ref, where_clauses, assoc_ty_values: Vec::new() } | ||
300 | } | ||
301 | |||
302 | fn super_trait_object_unsize_impl_datum( | ||
303 | db: &dyn HirDatabase, | ||
304 | krate: CrateId, | ||
305 | data: UnsizeToSuperTraitObjectData, | ||
306 | ) -> BuiltinImplData { | ||
307 | // impl<T1, ...> Unsize<dyn SuperTrait> for dyn Trait<T1, ...> | ||
308 | |||
309 | let unsize_trait = get_unsize_trait(db, krate) // get unsize trait | ||
310 | // the existence of the Unsize trait has been checked before | ||
311 | .expect("Unsize trait missing"); | ||
312 | |||
313 | let self_substs = Substs::build_for_def(db, data.trait_) | ||
314 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) | ||
315 | .build(); | ||
316 | let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() }; | ||
317 | |||
318 | let num_vars = self_substs.len() - 1; | ||
319 | |||
320 | // we need to go from our trait to the super trait, substituting type parameters | ||
321 | let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait); | ||
322 | |||
323 | let mut current_trait_ref = self_trait_ref.clone(); | ||
324 | for t in path.into_iter().skip(1) { | ||
325 | let bounds = db.generic_predicates(current_trait_ref.trait_.into()); | ||
326 | let super_trait_ref = bounds | ||
327 | .iter() | ||
328 | .find_map(|b| match &b.value { | ||
329 | GenericPredicate::Implemented(tr) | ||
330 | if tr.trait_ == t | ||
331 | && tr.substs[0] | ||
332 | == Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) => | ||
333 | { | ||
334 | Some(Binders { value: tr, num_binders: b.num_binders }) | ||
335 | } | ||
336 | _ => None, | ||
337 | }) | ||
338 | .expect("trait bound for known super trait not found"); | ||
339 | current_trait_ref = super_trait_ref.cloned().subst(¤t_trait_ref.substs); | ||
340 | } | ||
341 | |||
342 | // We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ... | ||
343 | // to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes | ||
344 | // from the dyn Trait binder, while the other variables come from the impl. | ||
345 | let new_substs = Substs::builder(num_vars + 1) | ||
346 | .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) | ||
347 | .fill_with_bound_vars(DebruijnIndex::ONE, 0) | ||
348 | .build(); | ||
349 | |||
350 | let self_bounds = | ||
351 | vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))]; | ||
352 | let super_bounds = | ||
353 | vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))]; | ||
354 | |||
355 | let substs = Substs::builder(2) | ||
356 | .push(Ty::Dyn(self_bounds.into())) | ||
357 | .push(Ty::Dyn(super_bounds.into())) | ||
358 | .build(); | ||
359 | |||
360 | let trait_ref = TraitRef { trait_: unsize_trait, substs }; | ||
361 | |||
362 | BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() } | ||
363 | } | ||
364 | |||
365 | fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> { | ||
366 | let target = db.lang_item(krate, "unsize".into())?; | ||
367 | match target { | ||
368 | LangItemTarget::TraitId(t) => Some(t), | ||
369 | _ => None, | ||
370 | } | ||
371 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index c97b81d57..c448aea65 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -3,7 +3,7 @@ use std::sync::Arc; | |||
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; | 6 | use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg, TypeName}; |
7 | use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; | 7 | use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; |
8 | 8 | ||
9 | use hir_def::{ | 9 | use hir_def::{ |
@@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId}; | |||
14 | 14 | ||
15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; | 15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; |
16 | use crate::{ | 16 | use crate::{ |
17 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 17 | db::HirDatabase, |
18 | display::HirDisplay, | ||
19 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | ||
20 | utils::generics, | ||
18 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, | 21 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, |
19 | }; | 22 | }; |
20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; | 23 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; |
@@ -66,13 +69,31 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
66 | &self, | 69 | &self, |
67 | trait_id: TraitId, | 70 | trait_id: TraitId, |
68 | parameters: &[GenericArg<Interner>], | 71 | parameters: &[GenericArg<Interner>], |
72 | binders: &CanonicalVarKinds<Interner>, | ||
69 | ) -> Vec<ImplId> { | 73 | ) -> Vec<ImplId> { |
70 | debug!("impls_for_trait {:?}", trait_id); | 74 | debug!("impls_for_trait {:?}", trait_id); |
71 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); | 75 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
72 | 76 | ||
73 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); | 77 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); |
74 | 78 | ||
79 | fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> { | ||
80 | if let Ty::Bound(bv) = ty { | ||
81 | let binders = binders.as_slice(&Interner); | ||
82 | if bv.debruijn == DebruijnIndex::INNERMOST { | ||
83 | if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { | ||
84 | return Some(tk); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | None | ||
89 | } | ||
90 | |||
75 | let self_ty_fp = TyFingerprint::for_impl(&ty); | 91 | let self_ty_fp = TyFingerprint::for_impl(&ty); |
92 | let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { | ||
93 | Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS, | ||
94 | Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS, | ||
95 | _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), | ||
96 | }; | ||
76 | 97 | ||
77 | // Note: Since we're using impls_for_trait, only impls where the trait | 98 | // Note: Since we're using impls_for_trait, only impls where the trait |
78 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | 99 | // can be resolved should ever reach Chalk. `impl_datum` relies on that |
@@ -83,17 +104,21 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
83 | 104 | ||
84 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); | 105 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); |
85 | 106 | ||
86 | let mut result: Vec<_> = match self_ty_fp { | 107 | let mut result: Vec<_> = if fps.is_empty() { |
87 | Some(fp) => impl_maps | 108 | debug!("Unrestricted search for {:?} impls...", trait_); |
109 | impl_maps | ||
110 | .iter() | ||
111 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) | ||
112 | .collect() | ||
113 | } else { | ||
114 | impl_maps | ||
88 | .iter() | 115 | .iter() |
89 | .flat_map(|crate_impl_defs| { | 116 | .flat_map(|crate_impl_defs| { |
90 | crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk) | 117 | fps.iter().flat_map(move |fp| { |
118 | crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) | ||
119 | }) | ||
91 | }) | 120 | }) |
92 | .collect(), | 121 | .collect() |
93 | None => impl_maps | ||
94 | .iter() | ||
95 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) | ||
96 | .collect(), | ||
97 | }; | 122 | }; |
98 | 123 | ||
99 | let arg: Option<Ty> = | 124 | let arg: Option<Ty> = |
@@ -219,6 +244,22 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
219 | // FIXME: implement closure support | 244 | // FIXME: implement closure support |
220 | unimplemented!() | 245 | unimplemented!() |
221 | } | 246 | } |
247 | |||
248 | fn trait_name(&self, _trait_id: chalk_ir::TraitId<Interner>) -> String { | ||
249 | unimplemented!() | ||
250 | } | ||
251 | fn adt_name(&self, _struct_id: chalk_ir::AdtId<Interner>) -> String { | ||
252 | unimplemented!() | ||
253 | } | ||
254 | fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String { | ||
255 | unimplemented!() | ||
256 | } | ||
257 | fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String { | ||
258 | unimplemented!() | ||
259 | } | ||
260 | fn fn_def_name(&self, _fn_def_id: chalk_ir::FnDefId<Interner>) -> String { | ||
261 | unimplemented!() | ||
262 | } | ||
222 | } | 263 | } |
223 | 264 | ||
224 | pub(crate) fn program_clauses_for_chalk_env_query( | 265 | pub(crate) fn program_clauses_for_chalk_env_query( |
@@ -354,12 +395,18 @@ pub(crate) fn struct_datum_query( | |||
354 | fundamental: false, | 395 | fundamental: false, |
355 | phantom_data: false, | 396 | phantom_data: false, |
356 | }; | 397 | }; |
357 | let struct_datum_bound = rust_ir::AdtDatumBound { | 398 | // FIXME provide enum variants properly (for auto traits) |
358 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 399 | let variant = rust_ir::AdtVariantDatum { |
359 | where_clauses, | 400 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits), |
401 | }; | ||
402 | let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses }; | ||
403 | let struct_datum = StructDatum { | ||
404 | // FIXME set ADT kind | ||
405 | kind: rust_ir::AdtKind::Struct, | ||
406 | id: struct_id, | ||
407 | binders: make_binders(struct_datum_bound, num_params), | ||
408 | flags, | ||
360 | }; | 409 | }; |
361 | let struct_datum = | ||
362 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
363 | Arc::new(struct_datum) | 410 | Arc::new(struct_datum) |
364 | } | 411 | } |
365 | 412 | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs index 15426b022..156b691b4 100644 --- a/crates/ra_hir_ty/src/traits/chalk/interner.rs +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs | |||
@@ -39,6 +39,7 @@ impl chalk_ir::interner::Interner for Interner { | |||
39 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | 39 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; |
40 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; | 40 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; |
41 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; | 41 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; |
42 | type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; | ||
42 | type DefId = InternId; | 43 | type DefId = InternId; |
43 | type InternedAdtId = crate::TypeCtorId; | 44 | type InternedAdtId = crate::TypeCtorId; |
44 | type Identifier = TypeAliasId; | 45 | type Identifier = TypeAliasId; |
@@ -349,6 +350,20 @@ impl chalk_ir::interner::Interner for Interner { | |||
349 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { | 350 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { |
350 | &canonical_var_kinds | 351 | &canonical_var_kinds |
351 | } | 352 | } |
353 | |||
354 | fn intern_constraints<E>( | ||
355 | &self, | ||
356 | data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>, | ||
357 | ) -> Result<Self::InternedConstraints, E> { | ||
358 | data.into_iter().collect() | ||
359 | } | ||
360 | |||
361 | fn constraints_data<'a>( | ||
362 | &self, | ||
363 | constraints: &'a Self::InternedConstraints, | ||
364 | ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] { | ||
365 | constraints | ||
366 | } | ||
352 | } | 367 | } |
353 | 368 | ||
354 | impl chalk_ir::interner::HasInterner for Interner { | 369 | impl chalk_ir::interner::HasInterner for Interner { |
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index 433d6aa03..7dc9ee759 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs | |||
@@ -29,6 +29,7 @@ impl ToChalk for Ty { | |||
29 | match self { | 29 | match self { |
30 | Ty::Apply(apply_ty) => match apply_ty.ctor { | 30 | Ty::Apply(apply_ty) => match apply_ty.ctor { |
31 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), | 31 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), |
32 | TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), | ||
32 | TypeCtor::FnPtr { num_args: _ } => { | 33 | TypeCtor::FnPtr { num_args: _ } => { |
33 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); | 34 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); |
34 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) | 35 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) |
@@ -61,13 +62,13 @@ impl ToChalk for Ty { | |||
61 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), | 62 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), |
62 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 63 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
63 | Ty::Dyn(predicates) => { | 64 | Ty::Dyn(predicates) => { |
64 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from( | 65 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
65 | &Interner, | 66 | &Interner, |
66 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | 67 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), |
67 | ); | 68 | ); |
68 | let bounded_ty = chalk_ir::DynTy { | 69 | let bounded_ty = chalk_ir::DynTy { |
69 | bounds: make_binders(where_clauses, 1), | 70 | bounds: make_binders(where_clauses, 1), |
70 | lifetime: LIFETIME_PLACEHOLDER.to_lifetime(&Interner), | 71 | lifetime: FAKE_PLACEHOLDER.to_lifetime(&Interner), |
71 | }; | 72 | }; |
72 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | 73 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) |
73 | } | 74 | } |
@@ -92,6 +93,7 @@ impl ToChalk for Ty { | |||
92 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | 93 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { |
93 | TypeName::Error => Ty::Unknown, | 94 | TypeName::Error => Ty::Unknown, |
94 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | 95 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), |
96 | TypeName::Array => array_from_chalk(db, apply_ty.substitution), | ||
95 | _ => { | 97 | _ => { |
96 | let ctor = from_chalk(db, apply_ty.name); | 98 | let ctor = from_chalk(db, apply_ty.name); |
97 | let parameters = from_chalk(db, apply_ty.substitution); | 99 | let parameters = from_chalk(db, apply_ty.substitution); |
@@ -138,7 +140,7 @@ impl ToChalk for Ty { | |||
138 | } | 140 | } |
139 | } | 141 | } |
140 | 142 | ||
141 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | 143 | const FAKE_PLACEHOLDER: PlaceholderIndex = |
142 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | 144 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; |
143 | 145 | ||
144 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | 146 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a |
@@ -149,10 +151,10 @@ fn ref_to_chalk( | |||
149 | subst: Substs, | 151 | subst: Substs, |
150 | ) -> chalk_ir::Ty<Interner> { | 152 | ) -> chalk_ir::Ty<Interner> { |
151 | let arg = subst[0].clone().to_chalk(db); | 153 | let arg = subst[0].clone().to_chalk(db); |
152 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | 154 | let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner); |
153 | chalk_ir::ApplicationTy { | 155 | chalk_ir::ApplicationTy { |
154 | name: TypeName::Ref(mutability.to_chalk(db)), | 156 | name: TypeName::Ref(mutability.to_chalk(db)), |
155 | substitution: chalk_ir::Substitution::from( | 157 | substitution: chalk_ir::Substitution::from_iter( |
156 | &Interner, | 158 | &Interner, |
157 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | 159 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], |
158 | ), | 160 | ), |
@@ -173,11 +175,40 @@ fn ref_from_chalk( | |||
173 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | 175 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) |
174 | } | 176 | } |
175 | 177 | ||
178 | /// We currently don't model constants, but Chalk does. So, we have to insert a | ||
179 | /// fake constant here, because Chalks built-in logic may expect it to be there. | ||
180 | fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { | ||
181 | let arg = subst[0].clone().to_chalk(db); | ||
182 | let usize_ty = chalk_ir::ApplicationTy { | ||
183 | name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)), | ||
184 | substitution: chalk_ir::Substitution::empty(&Interner), | ||
185 | } | ||
186 | .intern(&Interner); | ||
187 | let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty); | ||
188 | chalk_ir::ApplicationTy { | ||
189 | name: TypeName::Array, | ||
190 | substitution: chalk_ir::Substitution::from_iter( | ||
191 | &Interner, | ||
192 | vec![arg.cast(&Interner), const_.cast(&Interner)], | ||
193 | ), | ||
194 | } | ||
195 | .intern(&Interner) | ||
196 | } | ||
197 | |||
198 | /// Here we remove the const from the type we got from Chalk. | ||
199 | fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty { | ||
200 | let tys = subst | ||
201 | .iter(&Interner) | ||
202 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
203 | .collect(); | ||
204 | Ty::apply(TypeCtor::Array, Substs(tys)) | ||
205 | } | ||
206 | |||
176 | impl ToChalk for Substs { | 207 | impl ToChalk for Substs { |
177 | type Chalk = chalk_ir::Substitution<Interner>; | 208 | type Chalk = chalk_ir::Substitution<Interner>; |
178 | 209 | ||
179 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { | 210 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { |
180 | chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) | 211 | chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) |
181 | } | 212 | } |
182 | 213 | ||
183 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { | 214 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { |
@@ -263,6 +294,7 @@ impl ToChalk for TypeCtor { | |||
263 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | 294 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), |
264 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | 295 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), |
265 | TypeCtor::Slice => TypeName::Slice, | 296 | TypeCtor::Slice => TypeName::Slice, |
297 | TypeCtor::Array => TypeName::Array, | ||
266 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | 298 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), |
267 | TypeCtor::Str => TypeName::Str, | 299 | TypeCtor::Str => TypeName::Str, |
268 | TypeCtor::FnDef(callable_def) => { | 300 | TypeCtor::FnDef(callable_def) => { |
@@ -271,10 +303,8 @@ impl ToChalk for TypeCtor { | |||
271 | } | 303 | } |
272 | TypeCtor::Never => TypeName::Never, | 304 | TypeCtor::Never => TypeName::Never, |
273 | 305 | ||
274 | TypeCtor::Adt(_) | 306 | // FIXME convert these |
275 | | TypeCtor::Array | 307 | TypeCtor::Adt(_) | TypeCtor::FnPtr { .. } | TypeCtor::Closure { .. } => { |
276 | | TypeCtor::FnPtr { .. } | ||
277 | | TypeCtor::Closure { .. } => { | ||
278 | // other TypeCtors get interned and turned into a chalk StructId | 308 | // other TypeCtors get interned and turned into a chalk StructId |
279 | let struct_id = db.intern_type_ctor(self).into(); | 309 | let struct_id = db.intern_type_ctor(self).into(); |
280 | TypeName::Adt(struct_id) | 310 | TypeName::Adt(struct_id) |
@@ -492,6 +522,11 @@ impl ToChalk for GenericPredicate { | |||
492 | // we shouldn't get these from Chalk | 522 | // we shouldn't get these from Chalk |
493 | panic!("encountered LifetimeOutlives from Chalk") | 523 | panic!("encountered LifetimeOutlives from Chalk") |
494 | } | 524 | } |
525 | |||
526 | chalk_ir::WhereClause::TypeOutlives(_) => { | ||
527 | // we shouldn't get these from Chalk | ||
528 | panic!("encountered TypeOutlives from Chalk") | ||
529 | } | ||
495 | } | 530 | } |
496 | } | 531 | } |
497 | } | 532 | } |
@@ -570,7 +605,10 @@ where | |||
570 | ) | 605 | ) |
571 | }); | 606 | }); |
572 | let value = self.value.to_chalk(db); | 607 | let value = self.value.to_chalk(db); |
573 | chalk_ir::Canonical { value, binders: chalk_ir::CanonicalVarKinds::from(&Interner, kinds) } | 608 | chalk_ir::Canonical { |
609 | value, | ||
610 | binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds), | ||
611 | } | ||
574 | } | 612 | } |
575 | 613 | ||
576 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | 614 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { |
@@ -691,7 +729,7 @@ where | |||
691 | T: HasInterner<Interner = Interner>, | 729 | T: HasInterner<Interner = Interner>, |
692 | { | 730 | { |
693 | chalk_ir::Binders::new( | 731 | chalk_ir::Binders::new( |
694 | chalk_ir::VariableKinds::from( | 732 | chalk_ir::VariableKinds::from_iter( |
695 | &Interner, | 733 | &Interner, |
696 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), | 734 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), |
697 | ), | 735 | ), |
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs index e6a9d3211..1e226baea 100644 --- a/crates/ra_hir_ty/src/traits/chalk/tls.rs +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs | |||
@@ -157,7 +157,7 @@ impl DebugContext<'_> { | |||
157 | _ => panic!("associated type not in trait"), | 157 | _ => panic!("associated type not in trait"), |
158 | }; | 158 | }; |
159 | let trait_data = self.0.trait_data(trait_); | 159 | let trait_data = self.0.trait_data(trait_); |
160 | let params = projection_ty.substitution.parameters(&Interner); | 160 | let params = projection_ty.substitution.as_slice(&Interner); |
161 | write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; | 161 | write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; |
162 | if params.len() > 1 { | 162 | if params.len() > 1 { |
163 | write!( | 163 | write!( |