aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/traits
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-07-12 21:20:36 +0100
committerGitHub <[email protected]>2020-07-12 21:20:36 +0100
commit39e049d2a1d7e0adbd9546f9e8124843443b31ce (patch)
treec4bd56eaa24b25db28d8f213bae39c3b47703c46 /crates/ra_hir_ty/src/traits
parentab1ad19f552e1b11055ed60f87cc420871d902eb (diff)
parentd885f38011b6d4265b527744234b3c317fe86501 (diff)
Merge #5319
5319: Chalk upgrade r=flodiebold a=flodiebold - upgrade Chalk - make use of Chalk's `Unsize` impls, remove ours - use Chalk's built-in array type - search efficiently for impls for an int/float variable - output Chalk tracing logs in hir_ty tests Fixes #2534. Fixes #5057. Fixes #4374. Fixes #4281. Co-authored-by: Florian Diebold <[email protected]> Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/traits')
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs201
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs77
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs15
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs62
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs2
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`.
3use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; 3use hir_def::{expr::Expr, TraitId, TypeAliasId};
4use hir_expand::name::name; 4use hir_expand::name::name;
5use ra_db::CrateId; 5use ra_db::CrateId;
6 6
7use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData}; 7use super::{AssocTyValue, Impl};
8use crate::{ 8use 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
15pub(super) struct BuiltinImplData { 12pub(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
62fn 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
98pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { 52pub(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
233fn 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
243fn 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
269fn 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
302fn 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(&current_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
365fn 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
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; 6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg, TypeName};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 8
9use hir_def::{ 9use hir_def::{
@@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId};
14 14
15use super::{builtin, AssocTyValue, ChalkContext, Impl}; 15use super::{builtin, AssocTyValue, ChalkContext, Impl};
16use crate::{ 16use 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};
20use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; 23use 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
224pub(crate) fn program_clauses_for_chalk_env_query( 265pub(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
354impl chalk_ir::interner::HasInterner for Interner { 369impl 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
141const LIFETIME_PLACEHOLDER: PlaceholderIndex = 143const 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.
180fn 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.
199fn 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
176impl ToChalk for Substs { 207impl 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 {}", &params[0], trait_data.name,)?; 161 write!(fmt, "<{:?} as {}", &params[0], trait_data.name,)?;
162 if params.len() > 1 { 162 if params.len() > 1 {
163 write!( 163 write!(