aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/traits
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/traits')
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs371
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs182
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs29
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs184
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs28
5 files changed, 241 insertions, 553 deletions
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
deleted file mode 100644
index 6d5f2d46a..000000000
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ /dev/null
@@ -1,371 +0,0 @@
1//! This module provides the built-in trait implementations, e.g. to make
2//! closures implement `Fn`.
3use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
4use hir_expand::name::name;
5use ra_db::CrateId;
6
7use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData};
8use crate::{
9 db::HirDatabase,
10 utils::{all_super_traits, generics},
11 ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty,
12 TypeCtor, TypeWalk,
13};
14
15pub(super) struct BuiltinImplData {
16 pub num_vars: usize,
17 pub trait_ref: TraitRef,
18 pub where_clauses: Vec<super::GenericPredicate>,
19 pub assoc_ty_values: Vec<AssocTyValue>,
20}
21
22pub(super) struct BuiltinImplAssocTyValueData {
23 pub impl_: Impl,
24 pub assoc_ty_id: TypeAliasId,
25 pub num_vars: usize,
26 pub value: Ty,
27}
28
29pub(super) fn get_builtin_impls(
30 db: &dyn HirDatabase,
31 krate: CrateId,
32 ty: &Ty,
33 // The first argument for the trait, if present
34 arg: &Option<Ty>,
35 trait_: TraitId,
36 mut callback: impl FnMut(Impl),
37) {
38 // Note: since impl_datum needs to be infallible, we need to make sure here
39 // that we have all prerequisites to build the respective impls.
40 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
41 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
42 {
43 if let Some(actual_trait) = fn_trait.get_id(db, krate) {
44 if trait_ == actual_trait {
45 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
46 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
47 callback(Impl::ClosureFnTraitImpl(impl_));
48 }
49 }
50 }
51 }
52 }
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}
97
98pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData {
99 match impl_ {
100 Impl::ImplDef(_) => unreachable!(),
101 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 }
108}
109
110pub(super) fn associated_ty_value(
111 db: &dyn HirDatabase,
112 krate: CrateId,
113 data: AssocTyValue,
114) -> BuiltinImplAssocTyValueData {
115 match data {
116 AssocTyValue::TypeAlias(_) => unreachable!(),
117 AssocTyValue::ClosureFnTraitImplOutput(data) => {
118 closure_fn_trait_output_assoc_ty_value(db, krate, data)
119 }
120 }
121}
122
123// Closure Fn trait impls
124
125fn check_closure_fn_trait_impl_prerequisites(
126 db: &dyn HirDatabase,
127 krate: CrateId,
128 data: super::ClosureFnTraitImplData,
129) -> bool {
130 // the respective Fn/FnOnce/FnMut trait needs to exist
131 if data.fn_trait.get_id(db, krate).is_none() {
132 return false;
133 }
134
135 // FIXME: there are more assumptions that we should probably check here:
136 // the traits having no type params, FnOnce being a supertrait
137
138 // the FnOnce trait needs to exist and have an assoc type named Output
139 let fn_once_trait = match (super::FnTrait::FnOnce).get_id(db, krate) {
140 Some(t) => t,
141 None => return false,
142 };
143 db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some()
144}
145
146fn closure_fn_trait_impl_datum(
147 db: &dyn HirDatabase,
148 krate: CrateId,
149 data: super::ClosureFnTraitImplData,
150) -> BuiltinImplData {
151 // for some closure |X, Y| -> Z:
152 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
153
154 let trait_ = data
155 .fn_trait
156 .get_id(db, krate) // get corresponding fn trait
157 // the existence of the Fn trait has been checked before
158 .expect("fn trait for closure impl missing");
159
160 let num_args: u16 = match &db.body(data.def)[data.expr] {
161 Expr::Lambda { args, .. } => args.len() as u16,
162 _ => {
163 log::warn!("closure for closure type {:?} not found", data);
164 0
165 }
166 };
167
168 let arg_ty = Ty::apply(
169 TypeCtor::Tuple { cardinality: num_args },
170 Substs::builder(num_args as usize)
171 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
172 .build(),
173 );
174 let sig_ty = Ty::apply(
175 TypeCtor::FnPtr { num_args },
176 Substs::builder(num_args as usize + 1)
177 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
178 .build(),
179 );
180
181 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
182
183 let trait_ref = TraitRef {
184 trait_,
185 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
186 };
187
188 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data);
189
190 BuiltinImplData {
191 num_vars: num_args as usize + 1,
192 trait_ref,
193 where_clauses: Vec::new(),
194 assoc_ty_values: vec![output_ty_id],
195 }
196}
197
198fn closure_fn_trait_output_assoc_ty_value(
199 db: &dyn HirDatabase,
200 krate: CrateId,
201 data: super::ClosureFnTraitImplData,
202) -> BuiltinImplAssocTyValueData {
203 let impl_ = Impl::ClosureFnTraitImpl(data);
204
205 let num_args: u16 = match &db.body(data.def)[data.expr] {
206 Expr::Lambda { args, .. } => args.len() as u16,
207 _ => {
208 log::warn!("closure for closure type {:?} not found", data);
209 0
210 }
211 };
212
213 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
214
215 let fn_once_trait =
216 (super::FnTrait::FnOnce).get_id(db, krate).expect("assoc ty value should not exist");
217
218 let output_ty_id = db
219 .trait_data(fn_once_trait)
220 .associated_type_by_name(&name![Output])
221 .expect("assoc ty value should not exist");
222
223 BuiltinImplAssocTyValueData {
224 impl_,
225 assoc_ty_id: output_ty_id,
226 num_vars: num_args as usize + 1,
227 value: output_ty,
228 }
229}
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..5298dbecf 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::{
@@ -12,12 +12,17 @@ use hir_def::{
12}; 12};
13use ra_db::{salsa::InternKey, CrateId}; 13use ra_db::{salsa::InternKey, CrateId};
14 14
15use super::{builtin, AssocTyValue, ChalkContext, Impl}; 15use super::ChalkContext;
16use crate::{ 16use crate::{
17 db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, 17 db::HirDatabase,
18 CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, 18 display::HirDisplay,
19 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
20 utils::generics,
21 CallableDefId, DebruijnIndex, FnSig, GenericPredicate, Substs, Ty, TypeCtor,
22};
23use mapping::{
24 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
19}; 25};
20use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders};
21 26
22pub use self::interner::*; 27pub use self::interner::*;
23 28
@@ -49,7 +54,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
49 self.db.struct_datum(self.krate, struct_id) 54 self.db.struct_datum(self.krate, struct_id)
50 } 55 }
51 fn adt_repr(&self, _struct_id: AdtId) -> rust_ir::AdtRepr { 56 fn adt_repr(&self, _struct_id: AdtId) -> rust_ir::AdtRepr {
52 unreachable!() 57 rust_ir::AdtRepr { repr_c: false, repr_packed: false }
53 } 58 }
54 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { 59 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
55 self.db.impl_datum(self.krate, impl_id) 60 self.db.impl_datum(self.krate, impl_id)
@@ -66,13 +71,31 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
66 &self, 71 &self,
67 trait_id: TraitId, 72 trait_id: TraitId,
68 parameters: &[GenericArg<Interner>], 73 parameters: &[GenericArg<Interner>],
74 binders: &CanonicalVarKinds<Interner>,
69 ) -> Vec<ImplId> { 75 ) -> Vec<ImplId> {
70 debug!("impls_for_trait {:?}", trait_id); 76 debug!("impls_for_trait {:?}", trait_id);
71 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 77 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
72 78
73 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); 79 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
74 80
81 fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> {
82 if let Ty::Bound(bv) = ty {
83 let binders = binders.as_slice(&Interner);
84 if bv.debruijn == DebruijnIndex::INNERMOST {
85 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
86 return Some(tk);
87 }
88 }
89 }
90 None
91 }
92
75 let self_ty_fp = TyFingerprint::for_impl(&ty); 93 let self_ty_fp = TyFingerprint::for_impl(&ty);
94 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
95 Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS,
96 Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS,
97 _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
98 };
76 99
77 // Note: Since we're using impls_for_trait, only impls where the trait 100 // 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 101 // can be resolved should ever reach Chalk. `impl_datum` relies on that
@@ -81,28 +104,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
81 let in_self = self.db.trait_impls_in_crate(self.krate); 104 let in_self = self.db.trait_impls_in_crate(self.krate);
82 let impl_maps = [in_deps, in_self]; 105 let impl_maps = [in_deps, in_self];
83 106
84 let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); 107 let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
85 108
86 let mut result: Vec<_> = match self_ty_fp { 109 let result: Vec<_> = if fps.is_empty() {
87 Some(fp) => impl_maps 110 debug!("Unrestricted search for {:?} impls...", trait_);
111 impl_maps
112 .iter()
113 .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk))
114 .collect()
115 } else {
116 impl_maps
88 .iter() 117 .iter()
89 .flat_map(|crate_impl_defs| { 118 .flat_map(|crate_impl_defs| {
90 crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk) 119 fps.iter().flat_map(move |fp| {
120 crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
121 })
91 }) 122 })
92 .collect(), 123 .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 }; 124 };
98 125
99 let arg: Option<Ty> =
100 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
101
102 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| {
103 result.push(i.to_chalk(self.db))
104 });
105
106 debug!("impls_for_trait returned {} impls", result.len()); 126 debug!("impls_for_trait returned {} impls", result.len());
107 result 127 result
108 } 128 }
@@ -192,31 +212,55 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
192 _closure_id: chalk_ir::ClosureId<Interner>, 212 _closure_id: chalk_ir::ClosureId<Interner>,
193 _substs: &chalk_ir::Substitution<Interner>, 213 _substs: &chalk_ir::Substitution<Interner>,
194 ) -> rust_ir::ClosureKind { 214 ) -> rust_ir::ClosureKind {
195 // FIXME: implement closure support 215 // Fn is the closure kind that implements all three traits
196 unimplemented!() 216 rust_ir::ClosureKind::Fn
197 } 217 }
198 fn closure_inputs_and_output( 218 fn closure_inputs_and_output(
199 &self, 219 &self,
200 _closure_id: chalk_ir::ClosureId<Interner>, 220 _closure_id: chalk_ir::ClosureId<Interner>,
201 _substs: &chalk_ir::Substitution<Interner>, 221 substs: &chalk_ir::Substitution<Interner>,
202 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 222 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
203 // FIXME: implement closure support 223 let sig_ty: Ty =
204 unimplemented!() 224 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
225 let sig = FnSig::from_fn_ptr_substs(
226 &sig_ty.substs().expect("first closure param should be fn ptr"),
227 false,
228 );
229 let io = rust_ir::FnDefInputsAndOutputDatum {
230 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(),
231 return_type: sig.ret().clone().to_chalk(self.db),
232 };
233 make_binders(io.shifted_in(&Interner), 0)
205 } 234 }
206 fn closure_upvars( 235 fn closure_upvars(
207 &self, 236 &self,
208 _closure_id: chalk_ir::ClosureId<Interner>, 237 _closure_id: chalk_ir::ClosureId<Interner>,
209 _substs: &chalk_ir::Substitution<Interner>, 238 _substs: &chalk_ir::Substitution<Interner>,
210 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 239 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
211 // FIXME: implement closure support 240 let ty = Ty::unit().to_chalk(self.db);
212 unimplemented!() 241 make_binders(ty, 0)
213 } 242 }
214 fn closure_fn_substitution( 243 fn closure_fn_substitution(
215 &self, 244 &self,
216 _closure_id: chalk_ir::ClosureId<Interner>, 245 _closure_id: chalk_ir::ClosureId<Interner>,
217 _substs: &chalk_ir::Substitution<Interner>, 246 _substs: &chalk_ir::Substitution<Interner>,
218 ) -> chalk_ir::Substitution<Interner> { 247 ) -> chalk_ir::Substitution<Interner> {
219 // FIXME: implement closure support 248 Substs::empty().to_chalk(self.db)
249 }
250
251 fn trait_name(&self, _trait_id: chalk_ir::TraitId<Interner>) -> String {
252 unimplemented!()
253 }
254 fn adt_name(&self, _struct_id: chalk_ir::AdtId<Interner>) -> String {
255 unimplemented!()
256 }
257 fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String {
258 unimplemented!()
259 }
260 fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String {
261 unimplemented!()
262 }
263 fn fn_def_name(&self, _fn_def_id: chalk_ir::FnDefId<Interner>) -> String {
220 unimplemented!() 264 unimplemented!()
221 } 265 }
222} 266}
@@ -354,12 +398,18 @@ pub(crate) fn struct_datum_query(
354 fundamental: false, 398 fundamental: false,
355 phantom_data: false, 399 phantom_data: false,
356 }; 400 };
357 let struct_datum_bound = rust_ir::AdtDatumBound { 401 // FIXME provide enum variants properly (for auto traits)
358 fields: Vec::new(), // FIXME add fields (only relevant for auto traits) 402 let variant = rust_ir::AdtVariantDatum {
359 where_clauses, 403 fields: Vec::new(), // FIXME add fields (only relevant for auto traits),
404 };
405 let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses };
406 let struct_datum = StructDatum {
407 // FIXME set ADT kind
408 kind: rust_ir::AdtKind::Struct,
409 id: struct_id,
410 binders: make_binders(struct_datum_bound, num_params),
411 flags,
360 }; 412 };
361 let struct_datum =
362 StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags };
363 Arc::new(struct_datum) 413 Arc::new(struct_datum)
364} 414}
365 415
@@ -370,11 +420,8 @@ pub(crate) fn impl_datum_query(
370) -> Arc<ImplDatum> { 420) -> Arc<ImplDatum> {
371 let _p = ra_prof::profile("impl_datum"); 421 let _p = ra_prof::profile("impl_datum");
372 debug!("impl_datum {:?}", impl_id); 422 debug!("impl_datum {:?}", impl_id);
373 let impl_: Impl = from_chalk(db, impl_id); 423 let impl_: hir_def::ImplId = from_chalk(db, impl_id);
374 match impl_ { 424 impl_def_datum(db, krate, impl_id, impl_)
375 Impl::ImplDef(impl_def) => impl_def_datum(db, krate, impl_id, impl_def),
376 _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)),
377 }
378} 425}
379 426
380fn impl_def_datum( 427fn impl_def_datum(
@@ -425,7 +472,7 @@ fn impl_def_datum(
425 let name = &db.type_alias_data(type_alias).name; 472 let name = &db.type_alias_data(type_alias).name;
426 trait_data.associated_type_by_name(name).is_some() 473 trait_data.associated_type_by_name(name).is_some()
427 }) 474 })
428 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) 475 .map(|type_alias| TypeAliasAsValue(type_alias).to_chalk(db))
429 .collect(); 476 .collect();
430 debug!("impl_datum: {:?}", impl_datum_bound); 477 debug!("impl_datum: {:?}", impl_datum_bound);
431 let impl_datum = ImplDatum { 478 let impl_datum = ImplDatum {
@@ -442,13 +489,8 @@ pub(crate) fn associated_ty_value_query(
442 krate: CrateId, 489 krate: CrateId,
443 id: AssociatedTyValueId, 490 id: AssociatedTyValueId,
444) -> Arc<AssociatedTyValue> { 491) -> Arc<AssociatedTyValue> {
445 let data: AssocTyValue = from_chalk(db, id); 492 let type_alias: TypeAliasAsValue = from_chalk(db, id);
446 match data { 493 type_alias_associated_ty_value(db, krate, type_alias.0)
447 AssocTyValue::TypeAlias(type_alias) => {
448 type_alias_associated_ty_value(db, krate, type_alias)
449 }
450 _ => Arc::new(builtin::associated_ty_value(db, krate, data).to_chalk(db)),
451 }
452} 494}
453 495
454fn type_alias_associated_ty_value( 496fn type_alias_associated_ty_value(
@@ -471,7 +513,7 @@ fn type_alias_associated_ty_value(
471 let ty = db.ty(type_alias.into()); 513 let ty = db.ty(type_alias.into());
472 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; 514 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
473 let value = rust_ir::AssociatedTyValue { 515 let value = rust_ir::AssociatedTyValue {
474 impl_id: Impl::ImplDef(impl_id).to_chalk(db), 516 impl_id: impl_id.to_chalk(db),
475 associated_ty_id: assoc_ty.to_chalk(db), 517 associated_ty_id: assoc_ty.to_chalk(db),
476 value: make_binders(value_bound, ty.num_binders), 518 value: make_binders(value_bound, ty.num_binders),
477 }; 519 };
@@ -483,7 +525,7 @@ pub(crate) fn fn_def_datum_query(
483 _krate: CrateId, 525 _krate: CrateId,
484 fn_def_id: FnDefId, 526 fn_def_id: FnDefId,
485) -> Arc<FnDefDatum> { 527) -> Arc<FnDefDatum> {
486 let callable_def: CallableDef = from_chalk(db, fn_def_id); 528 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
487 let generic_params = generics(db.upcast(), callable_def.into()); 529 let generic_params = generics(db.upcast(), callable_def.into());
488 let sig = db.callable_item_signature(callable_def); 530 let sig = db.callable_item_signature(callable_def);
489 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 531 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
@@ -510,42 +552,18 @@ pub(crate) fn fn_def_datum_query(
510 Arc::new(datum) 552 Arc::new(datum)
511} 553}
512 554
513impl From<AdtId> for crate::TypeCtorId { 555impl From<FnDefId> for crate::db::InternedCallableDefId {
514 fn from(struct_id: AdtId) -> Self {
515 struct_id.0
516 }
517}
518
519impl From<crate::TypeCtorId> for AdtId {
520 fn from(type_ctor_id: crate::TypeCtorId) -> Self {
521 chalk_ir::AdtId(type_ctor_id)
522 }
523}
524
525impl From<FnDefId> for crate::CallableDefId {
526 fn from(fn_def_id: FnDefId) -> Self { 556 fn from(fn_def_id: FnDefId) -> Self {
527 InternKey::from_intern_id(fn_def_id.0) 557 InternKey::from_intern_id(fn_def_id.0)
528 } 558 }
529} 559}
530 560
531impl From<crate::CallableDefId> for FnDefId { 561impl From<crate::db::InternedCallableDefId> for FnDefId {
532 fn from(callable_def_id: crate::CallableDefId) -> Self { 562 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self {
533 chalk_ir::FnDefId(callable_def_id.as_intern_id()) 563 chalk_ir::FnDefId(callable_def_id.as_intern_id())
534 } 564 }
535} 565}
536 566
537impl From<ImplId> for crate::traits::GlobalImplId {
538 fn from(impl_id: ImplId) -> Self {
539 InternKey::from_intern_id(impl_id.0)
540 }
541}
542
543impl From<crate::traits::GlobalImplId> for ImplId {
544 fn from(impl_id: crate::traits::GlobalImplId) -> Self {
545 chalk_ir::ImplId(impl_id.as_intern_id())
546 }
547}
548
549impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId { 567impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
550 fn from(id: OpaqueTyId) -> Self { 568 fn from(id: OpaqueTyId) -> Self {
551 InternKey::from_intern_id(id.0) 569 InternKey::from_intern_id(id.0)
@@ -558,14 +576,14 @@ impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
558 } 576 }
559} 577}
560 578
561impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { 579impl From<chalk_ir::ClosureId<Interner>> for crate::db::ClosureId {
562 fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self { 580 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
563 Self::from_intern_id(id.0) 581 Self::from_intern_id(id.0)
564 } 582 }
565} 583}
566 584
567impl From<crate::traits::AssocTyValueId> for rust_ir::AssociatedTyValueId<Interner> { 585impl From<crate::db::ClosureId> for chalk_ir::ClosureId<Interner> {
568 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { 586 fn from(id: crate::db::ClosureId) -> Self {
569 rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id()) 587 chalk_ir::ClosureId(id.as_intern_id())
570 } 588 }
571} 589}
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs
index 15426b022..8d4c51a8f 100644
--- a/crates/ra_hir_ty/src/traits/chalk/interner.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs
@@ -39,8 +39,9 @@ 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 = hir_def::AdtId;
44 type Identifier = TypeAliasId; 45 type Identifier = TypeAliasId;
45 type FnAbi = (); 46 type FnAbi = ();
46 47
@@ -349,6 +350,32 @@ 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 }
367 fn debug_closure_id(
368 _fn_def_id: chalk_ir::ClosureId<Self>,
369 _fmt: &mut fmt::Formatter<'_>,
370 ) -> Option<fmt::Result> {
371 None
372 }
373 fn debug_constraints(
374 _clauses: &chalk_ir::Constraints<Self>,
375 _fmt: &mut fmt::Formatter<'_>,
376 ) -> Option<fmt::Result> {
377 None
378 }
352} 379}
353 380
354impl chalk_ir::interner::HasInterner for Interner { 381impl 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..09d8347ca 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -15,8 +15,8 @@ use ra_db::salsa::InternKey;
15use crate::{ 15use crate::{
16 db::HirDatabase, 16 db::HirDatabase,
17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness},
18 traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, 18 traits::{Canonical, Obligation},
19 ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, 19 ApplicationTy, CallableDefId, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId,
20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor, 20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
21}; 21};
22 22
@@ -29,7 +29,9 @@ 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::FnPtr { num_args: _ } => { 32 TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
33 TypeCtor::FnPtr { num_args: _, is_varargs: _ } => {
34 // FIXME: handle is_varargs
33 let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); 35 let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
34 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) 36 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution })
35 .intern(&Interner) 37 .intern(&Interner)
@@ -61,13 +63,13 @@ impl ToChalk for Ty {
61 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), 63 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner),
62 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 64 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
63 Ty::Dyn(predicates) => { 65 Ty::Dyn(predicates) => {
64 let where_clauses = chalk_ir::QuantifiedWhereClauses::from( 66 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
65 &Interner, 67 &Interner,
66 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), 68 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
67 ); 69 );
68 let bounded_ty = chalk_ir::DynTy { 70 let bounded_ty = chalk_ir::DynTy {
69 bounds: make_binders(where_clauses, 1), 71 bounds: make_binders(where_clauses, 1),
70 lifetime: LIFETIME_PLACEHOLDER.to_lifetime(&Interner), 72 lifetime: FAKE_PLACEHOLDER.to_lifetime(&Interner),
71 }; 73 };
72 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 74 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
73 } 75 }
@@ -92,6 +94,7 @@ impl ToChalk for Ty {
92 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { 94 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
93 TypeName::Error => Ty::Unknown, 95 TypeName::Error => Ty::Unknown,
94 TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), 96 TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution),
97 TypeName::Array => array_from_chalk(db, apply_ty.substitution),
95 _ => { 98 _ => {
96 let ctor = from_chalk(db, apply_ty.name); 99 let ctor = from_chalk(db, apply_ty.name);
97 let parameters = from_chalk(db, apply_ty.substitution); 100 let parameters = from_chalk(db, apply_ty.substitution);
@@ -115,10 +118,17 @@ impl ToChalk for Ty {
115 let parameters = from_chalk(db, opaque_ty.substitution); 118 let parameters = from_chalk(db, opaque_ty.substitution);
116 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) 119 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
117 } 120 }
118 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { 121 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders, substitution }) => {
119 let parameters: Substs = from_chalk(db, substitution); 122 assert_eq!(num_binders, 0);
123 let parameters: Substs = from_chalk(
124 db,
125 substitution.shifted_out(&Interner).expect("fn ptr should have no binders"),
126 );
120 Ty::Apply(ApplicationTy { 127 Ty::Apply(ApplicationTy {
121 ctor: TypeCtor::FnPtr { num_args: (parameters.len() - 1) as u16 }, 128 ctor: TypeCtor::FnPtr {
129 num_args: (parameters.len() - 1) as u16,
130 is_varargs: false,
131 },
122 parameters, 132 parameters,
123 }) 133 })
124 } 134 }
@@ -138,7 +148,7 @@ impl ToChalk for Ty {
138 } 148 }
139} 149}
140 150
141const LIFETIME_PLACEHOLDER: PlaceholderIndex = 151const FAKE_PLACEHOLDER: PlaceholderIndex =
142 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; 152 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX };
143 153
144/// We currently don't model lifetimes, but Chalk does. So, we have to insert a 154/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
@@ -149,10 +159,10 @@ fn ref_to_chalk(
149 subst: Substs, 159 subst: Substs,
150) -> chalk_ir::Ty<Interner> { 160) -> chalk_ir::Ty<Interner> {
151 let arg = subst[0].clone().to_chalk(db); 161 let arg = subst[0].clone().to_chalk(db);
152 let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); 162 let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner);
153 chalk_ir::ApplicationTy { 163 chalk_ir::ApplicationTy {
154 name: TypeName::Ref(mutability.to_chalk(db)), 164 name: TypeName::Ref(mutability.to_chalk(db)),
155 substitution: chalk_ir::Substitution::from( 165 substitution: chalk_ir::Substitution::from_iter(
156 &Interner, 166 &Interner,
157 vec![lifetime.cast(&Interner), arg.cast(&Interner)], 167 vec![lifetime.cast(&Interner), arg.cast(&Interner)],
158 ), 168 ),
@@ -173,11 +183,40 @@ fn ref_from_chalk(
173 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) 183 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys))
174} 184}
175 185
186/// We currently don't model constants, but Chalk does. So, we have to insert a
187/// fake constant here, because Chalks built-in logic may expect it to be there.
188fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
189 let arg = subst[0].clone().to_chalk(db);
190 let usize_ty = chalk_ir::ApplicationTy {
191 name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)),
192 substitution: chalk_ir::Substitution::empty(&Interner),
193 }
194 .intern(&Interner);
195 let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty);
196 chalk_ir::ApplicationTy {
197 name: TypeName::Array,
198 substitution: chalk_ir::Substitution::from_iter(
199 &Interner,
200 vec![arg.cast(&Interner), const_.cast(&Interner)],
201 ),
202 }
203 .intern(&Interner)
204}
205
206/// Here we remove the const from the type we got from Chalk.
207fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty {
208 let tys = subst
209 .iter(&Interner)
210 .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone())))
211 .collect();
212 Ty::apply(TypeCtor::Array, Substs(tys))
213}
214
176impl ToChalk for Substs { 215impl ToChalk for Substs {
177 type Chalk = chalk_ir::Substitution<Interner>; 216 type Chalk = chalk_ir::Substitution<Interner>;
178 217
179 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { 218 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))) 219 chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
181 } 220 }
182 221
183 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { 222 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs {
@@ -263,6 +302,7 @@ impl ToChalk for TypeCtor {
263 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), 302 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()),
264 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), 303 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)),
265 TypeCtor::Slice => TypeName::Slice, 304 TypeCtor::Slice => TypeName::Slice,
305 TypeCtor::Array => TypeName::Array,
266 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), 306 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)),
267 TypeCtor::Str => TypeName::Str, 307 TypeCtor::Str => TypeName::Str,
268 TypeCtor::FnDef(callable_def) => { 308 TypeCtor::FnDef(callable_def) => {
@@ -271,20 +311,24 @@ impl ToChalk for TypeCtor {
271 } 311 }
272 TypeCtor::Never => TypeName::Never, 312 TypeCtor::Never => TypeName::Never,
273 313
274 TypeCtor::Adt(_) 314 TypeCtor::Closure { def, expr } => {
275 | TypeCtor::Array 315 let closure_id = db.intern_closure((def, expr));
276 | TypeCtor::FnPtr { .. } 316 TypeName::Closure(closure_id.into())
277 | TypeCtor::Closure { .. } => { 317 }
278 // other TypeCtors get interned and turned into a chalk StructId 318
279 let struct_id = db.intern_type_ctor(self).into(); 319 TypeCtor::Adt(adt_id) => TypeName::Adt(chalk_ir::AdtId(adt_id)),
280 TypeName::Adt(struct_id) 320
321 TypeCtor::FnPtr { .. } => {
322 // This should not be reached, since Chalk doesn't represent
323 // function pointers with TypeName
324 unreachable!()
281 } 325 }
282 } 326 }
283 } 327 }
284 328
285 fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { 329 fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor {
286 match type_name { 330 match type_name {
287 TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), 331 TypeName::Adt(struct_id) => TypeCtor::Adt(struct_id.0),
288 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), 332 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
289 TypeName::OpaqueType(opaque_type_id) => { 333 TypeName::OpaqueType(opaque_type_id) => {
290 TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) 334 TypeCtor::OpaqueType(from_chalk(db, opaque_type_id))
@@ -317,13 +361,16 @@ impl ToChalk for TypeCtor {
317 let callable_def = from_chalk(db, fn_def_id); 361 let callable_def = from_chalk(db, fn_def_id);
318 TypeCtor::FnDef(callable_def) 362 TypeCtor::FnDef(callable_def)
319 } 363 }
364 TypeName::Array => TypeCtor::Array,
320 365
321 TypeName::Array | TypeName::Error => { 366 TypeName::Closure(id) => {
322 // this should not be reached, since we don't represent TypeName::Error with TypeCtor 367 let id: crate::db::ClosureId = id.into();
323 unreachable!() 368 let (def, expr) = db.lookup_intern_closure(id);
369 TypeCtor::Closure { def, expr }
324 } 370 }
325 TypeName::Closure(_) => { 371
326 // FIXME: implement closure support 372 TypeName::Error => {
373 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
327 unreachable!() 374 unreachable!()
328 } 375 }
329 } 376 }
@@ -395,26 +442,26 @@ impl ToChalk for Mutability {
395 } 442 }
396} 443}
397 444
398impl ToChalk for Impl { 445impl ToChalk for hir_def::ImplId {
399 type Chalk = ImplId; 446 type Chalk = ImplId;
400 447
401 fn to_chalk(self, db: &dyn HirDatabase) -> ImplId { 448 fn to_chalk(self, _db: &dyn HirDatabase) -> ImplId {
402 db.intern_chalk_impl(self).into() 449 chalk_ir::ImplId(self.as_intern_id())
403 } 450 }
404 451
405 fn from_chalk(db: &dyn HirDatabase, impl_id: ImplId) -> Impl { 452 fn from_chalk(_db: &dyn HirDatabase, impl_id: ImplId) -> hir_def::ImplId {
406 db.lookup_intern_chalk_impl(impl_id.into()) 453 InternKey::from_intern_id(impl_id.0)
407 } 454 }
408} 455}
409 456
410impl ToChalk for CallableDef { 457impl ToChalk for CallableDefId {
411 type Chalk = FnDefId; 458 type Chalk = FnDefId;
412 459
413 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId { 460 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
414 db.intern_callable_def(self).into() 461 db.intern_callable_def(self).into()
415 } 462 }
416 463
417 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDef { 464 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
418 db.lookup_intern_callable_def(fn_def_id.into()) 465 db.lookup_intern_callable_def(fn_def_id.into())
419 } 466 }
420} 467}
@@ -431,15 +478,20 @@ impl ToChalk for TypeAliasId {
431 } 478 }
432} 479}
433 480
434impl ToChalk for AssocTyValue { 481pub struct TypeAliasAsValue(pub TypeAliasId);
482
483impl ToChalk for TypeAliasAsValue {
435 type Chalk = AssociatedTyValueId; 484 type Chalk = AssociatedTyValueId;
436 485
437 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValueId { 486 fn to_chalk(self, _db: &dyn HirDatabase) -> AssociatedTyValueId {
438 db.intern_assoc_ty_value(self).into() 487 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
439 } 488 }
440 489
441 fn from_chalk(db: &dyn HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { 490 fn from_chalk(
442 db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) 491 _db: &dyn HirDatabase,
492 assoc_ty_value_id: AssociatedTyValueId,
493 ) -> TypeAliasAsValue {
494 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
443 } 495 }
444} 496}
445 497
@@ -492,6 +544,11 @@ impl ToChalk for GenericPredicate {
492 // we shouldn't get these from Chalk 544 // we shouldn't get these from Chalk
493 panic!("encountered LifetimeOutlives from Chalk") 545 panic!("encountered LifetimeOutlives from Chalk")
494 } 546 }
547
548 chalk_ir::WhereClause::TypeOutlives(_) => {
549 // we shouldn't get these from Chalk
550 panic!("encountered TypeOutlives from Chalk")
551 }
495 } 552 }
496 } 553 }
497} 554}
@@ -570,7 +627,10 @@ where
570 ) 627 )
571 }); 628 });
572 let value = self.value.to_chalk(db); 629 let value = self.value.to_chalk(db);
573 chalk_ir::Canonical { value, binders: chalk_ir::CanonicalVarKinds::from(&Interner, kinds) } 630 chalk_ir::Canonical {
631 value,
632 binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
633 }
574 } 634 }
575 635
576 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 636 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
@@ -640,58 +700,12 @@ where
640 } 700 }
641} 701}
642 702
643impl ToChalk for builtin::BuiltinImplData {
644 type Chalk = ImplDatum;
645
646 fn to_chalk(self, db: &dyn HirDatabase) -> ImplDatum {
647 let impl_type = rust_ir::ImplType::External;
648 let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect();
649
650 let impl_datum_bound =
651 rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses };
652 let associated_ty_value_ids =
653 self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect();
654 rust_ir::ImplDatum {
655 binders: make_binders(impl_datum_bound, self.num_vars),
656 impl_type,
657 polarity: rust_ir::Polarity::Positive,
658 associated_ty_value_ids,
659 }
660 }
661
662 fn from_chalk(_db: &dyn HirDatabase, _data: ImplDatum) -> Self {
663 unimplemented!()
664 }
665}
666
667impl ToChalk for builtin::BuiltinImplAssocTyValueData {
668 type Chalk = AssociatedTyValue;
669
670 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue {
671 let ty = self.value.to_chalk(db);
672 let value_bound = rust_ir::AssociatedTyValueBound { ty };
673
674 rust_ir::AssociatedTyValue {
675 associated_ty_id: self.assoc_ty_id.to_chalk(db),
676 impl_id: self.impl_.to_chalk(db),
677 value: make_binders(value_bound, self.num_vars),
678 }
679 }
680
681 fn from_chalk(
682 _db: &dyn HirDatabase,
683 _data: AssociatedTyValue,
684 ) -> builtin::BuiltinImplAssocTyValueData {
685 unimplemented!()
686 }
687}
688
689pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 703pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
690where 704where
691 T: HasInterner<Interner = Interner>, 705 T: HasInterner<Interner = Interner>,
692{ 706{
693 chalk_ir::Binders::new( 707 chalk_ir::Binders::new(
694 chalk_ir::VariableKinds::from( 708 chalk_ir::VariableKinds::from_iter(
695 &Interner, 709 &Interner,
696 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), 710 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars),
697 ), 711 ),
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs
index 556af7098..db915625c 100644
--- a/crates/ra_hir_ty/src/traits/chalk/tls.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs
@@ -5,12 +5,12 @@ use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplicat
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use super::{from_chalk, Interner}; 7use super::{from_chalk, Interner};
8use crate::{db::HirDatabase, CallableDef, TypeCtor}; 8use crate::{db::HirDatabase, CallableDefId, TypeCtor};
9use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId}; 9use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId};
10 10
11pub use unsafe_tls::{set_current_program, with_current_program}; 11pub use unsafe_tls::{set_current_program, with_current_program};
12 12
13pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a)); 13pub struct DebugContext<'a>(&'a dyn HirDatabase);
14 14
15impl DebugContext<'_> { 15impl DebugContext<'_> {
16 pub fn debug_struct_id( 16 pub fn debug_struct_id(
@@ -38,16 +38,16 @@ impl DebugContext<'_> {
38 } 38 }
39 TypeCtor::FnDef(def) => { 39 TypeCtor::FnDef(def) => {
40 let name = match def { 40 let name = match def {
41 CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(), 41 CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
42 CallableDef::StructId(s) => self.0.struct_data(s).name.clone(), 42 CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
43 CallableDef::EnumVariantId(e) => { 43 CallableDefId::EnumVariantId(e) => {
44 let enum_data = self.0.enum_data(e.parent); 44 let enum_data = self.0.enum_data(e.parent);
45 enum_data.variants[e.local_id].name.clone() 45 enum_data.variants[e.local_id].name.clone()
46 } 46 }
47 }; 47 };
48 match def { 48 match def {
49 CallableDef::FunctionId(_) => write!(f, "{{fn {}}}", name)?, 49 CallableDefId::FunctionId(_) => write!(f, "{{fn {}}}", name)?,
50 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => { 50 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {
51 write!(f, "{{ctor {}}}", name)? 51 write!(f, "{{ctor {}}}", name)?
52 } 52 }
53 } 53 }
@@ -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!(
@@ -255,18 +255,18 @@ impl DebugContext<'_> {
255 fn_def_id: chalk_ir::FnDefId<Interner>, 255 fn_def_id: chalk_ir::FnDefId<Interner>,
256 fmt: &mut fmt::Formatter<'_>, 256 fmt: &mut fmt::Formatter<'_>,
257 ) -> Result<(), fmt::Error> { 257 ) -> Result<(), fmt::Error> {
258 let def: CallableDef = from_chalk(self.0, fn_def_id); 258 let def: CallableDefId = from_chalk(self.0, fn_def_id);
259 let name = match def { 259 let name = match def {
260 CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(), 260 CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
261 CallableDef::StructId(s) => self.0.struct_data(s).name.clone(), 261 CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
262 CallableDef::EnumVariantId(e) => { 262 CallableDefId::EnumVariantId(e) => {
263 let enum_data = self.0.enum_data(e.parent); 263 let enum_data = self.0.enum_data(e.parent);
264 enum_data.variants[e.local_id].name.clone() 264 enum_data.variants[e.local_id].name.clone()
265 } 265 }
266 }; 266 };
267 match def { 267 match def {
268 CallableDef::FunctionId(_) => write!(fmt, "{{fn {}}}", name), 268 CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name),
269 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => { 269 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {
270 write!(fmt, "{{ctor {}}}", name) 270 write!(fmt, "{{ctor {}}}", name)
271 } 271 }
272 } 272 }