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.rs205
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs29
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs233
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs28
5 files changed, 288 insertions, 578 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 8ef4941c0..1c7065364 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,45 +71,58 @@ 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
79 // and will panic if the trait can't be resolved. 102 // and will panic if the trait can't be resolved.
80 let in_deps = self.db.impls_from_deps(self.krate); 103 let in_deps = self.db.trait_impls_in_deps(self.krate);
81 let in_self = self.db.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
88 .iter() 112 .iter()
89 .flat_map(|crate_impl_defs| { 113 .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk))
90 crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk) 114 .collect()
91 }) 115 } else {
92 .collect(), 116 impl_maps
93 None => impl_maps
94 .iter() 117 .iter()
95 .flat_map(|crate_impl_defs| { 118 .flat_map(|crate_impl_defs| {
96 crate_impl_defs.lookup_impl_defs_for_trait(trait_).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 })
97 }) 122 })
98 .collect(), 123 .collect()
99 }; 124 };
100 125
101 let arg: Option<Ty> =
102 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
103
104 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| {
105 result.push(i.to_chalk(self.db))
106 });
107
108 debug!("impls_for_trait returned {} impls", result.len()); 126 debug!("impls_for_trait returned {} impls", result.len());
109 result 127 result
110 } 128 }
@@ -165,6 +183,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
165 .collect(), 183 .collect(),
166 1, 184 1,
167 ), 185 ),
186 where_clauses: make_binders(vec![], 0),
168 }; 187 };
169 let num_vars = datas.num_binders; 188 let num_vars = datas.num_binders;
170 Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) }) 189 Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) })
@@ -175,15 +194,6 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
175 Ty::Unknown.to_chalk(self.db) 194 Ty::Unknown.to_chalk(self.db)
176 } 195 }
177 196
178 fn force_impl_for(
179 &self,
180 _well_known: rust_ir::WellKnownTrait,
181 _ty: &chalk_ir::TyData<Interner>,
182 ) -> Option<bool> {
183 // this method is mostly for rustc
184 None
185 }
186
187 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { 197 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
188 // FIXME: implement actual object safety 198 // FIXME: implement actual object safety
189 true 199 true
@@ -194,31 +204,55 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
194 _closure_id: chalk_ir::ClosureId<Interner>, 204 _closure_id: chalk_ir::ClosureId<Interner>,
195 _substs: &chalk_ir::Substitution<Interner>, 205 _substs: &chalk_ir::Substitution<Interner>,
196 ) -> rust_ir::ClosureKind { 206 ) -> rust_ir::ClosureKind {
197 // FIXME: implement closure support 207 // Fn is the closure kind that implements all three traits
198 unimplemented!() 208 rust_ir::ClosureKind::Fn
199 } 209 }
200 fn closure_inputs_and_output( 210 fn closure_inputs_and_output(
201 &self, 211 &self,
202 _closure_id: chalk_ir::ClosureId<Interner>, 212 _closure_id: chalk_ir::ClosureId<Interner>,
203 _substs: &chalk_ir::Substitution<Interner>, 213 substs: &chalk_ir::Substitution<Interner>,
204 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 214 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
205 // FIXME: implement closure support 215 let sig_ty: Ty =
206 unimplemented!() 216 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
217 let sig = FnSig::from_fn_ptr_substs(
218 &sig_ty.substs().expect("first closure param should be fn ptr"),
219 false,
220 );
221 let io = rust_ir::FnDefInputsAndOutputDatum {
222 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(),
223 return_type: sig.ret().clone().to_chalk(self.db),
224 };
225 make_binders(io.shifted_in(&Interner), 0)
207 } 226 }
208 fn closure_upvars( 227 fn closure_upvars(
209 &self, 228 &self,
210 _closure_id: chalk_ir::ClosureId<Interner>, 229 _closure_id: chalk_ir::ClosureId<Interner>,
211 _substs: &chalk_ir::Substitution<Interner>, 230 _substs: &chalk_ir::Substitution<Interner>,
212 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 231 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
213 // FIXME: implement closure support 232 let ty = Ty::unit().to_chalk(self.db);
214 unimplemented!() 233 make_binders(ty, 0)
215 } 234 }
216 fn closure_fn_substitution( 235 fn closure_fn_substitution(
217 &self, 236 &self,
218 _closure_id: chalk_ir::ClosureId<Interner>, 237 _closure_id: chalk_ir::ClosureId<Interner>,
219 _substs: &chalk_ir::Substitution<Interner>, 238 _substs: &chalk_ir::Substitution<Interner>,
220 ) -> chalk_ir::Substitution<Interner> { 239 ) -> chalk_ir::Substitution<Interner> {
221 // FIXME: implement closure support 240 Substs::empty().to_chalk(self.db)
241 }
242
243 fn trait_name(&self, _trait_id: chalk_ir::TraitId<Interner>) -> String {
244 unimplemented!()
245 }
246 fn adt_name(&self, _struct_id: chalk_ir::AdtId<Interner>) -> String {
247 unimplemented!()
248 }
249 fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String {
250 unimplemented!()
251 }
252 fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String {
253 unimplemented!()
254 }
255 fn fn_def_name(&self, _fn_def_id: chalk_ir::FnDefId<Interner>) -> String {
222 unimplemented!() 256 unimplemented!()
223 } 257 }
224} 258}
@@ -356,12 +390,18 @@ pub(crate) fn struct_datum_query(
356 fundamental: false, 390 fundamental: false,
357 phantom_data: false, 391 phantom_data: false,
358 }; 392 };
359 let struct_datum_bound = rust_ir::AdtDatumBound { 393 // FIXME provide enum variants properly (for auto traits)
360 fields: Vec::new(), // FIXME add fields (only relevant for auto traits) 394 let variant = rust_ir::AdtVariantDatum {
361 where_clauses, 395 fields: Vec::new(), // FIXME add fields (only relevant for auto traits),
396 };
397 let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses };
398 let struct_datum = StructDatum {
399 // FIXME set ADT kind
400 kind: rust_ir::AdtKind::Struct,
401 id: struct_id,
402 binders: make_binders(struct_datum_bound, num_params),
403 flags,
362 }; 404 };
363 let struct_datum =
364 StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags };
365 Arc::new(struct_datum) 405 Arc::new(struct_datum)
366} 406}
367 407
@@ -372,11 +412,8 @@ pub(crate) fn impl_datum_query(
372) -> Arc<ImplDatum> { 412) -> Arc<ImplDatum> {
373 let _p = ra_prof::profile("impl_datum"); 413 let _p = ra_prof::profile("impl_datum");
374 debug!("impl_datum {:?}", impl_id); 414 debug!("impl_datum {:?}", impl_id);
375 let impl_: Impl = from_chalk(db, impl_id); 415 let impl_: hir_def::ImplId = from_chalk(db, impl_id);
376 match impl_ { 416 impl_def_datum(db, krate, impl_id, impl_)
377 Impl::ImplDef(impl_def) => impl_def_datum(db, krate, impl_id, impl_def),
378 _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)),
379 }
380} 417}
381 418
382fn impl_def_datum( 419fn impl_def_datum(
@@ -427,7 +464,7 @@ fn impl_def_datum(
427 let name = &db.type_alias_data(type_alias).name; 464 let name = &db.type_alias_data(type_alias).name;
428 trait_data.associated_type_by_name(name).is_some() 465 trait_data.associated_type_by_name(name).is_some()
429 }) 466 })
430 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) 467 .map(|type_alias| TypeAliasAsValue(type_alias).to_chalk(db))
431 .collect(); 468 .collect();
432 debug!("impl_datum: {:?}", impl_datum_bound); 469 debug!("impl_datum: {:?}", impl_datum_bound);
433 let impl_datum = ImplDatum { 470 let impl_datum = ImplDatum {
@@ -444,13 +481,8 @@ pub(crate) fn associated_ty_value_query(
444 krate: CrateId, 481 krate: CrateId,
445 id: AssociatedTyValueId, 482 id: AssociatedTyValueId,
446) -> Arc<AssociatedTyValue> { 483) -> Arc<AssociatedTyValue> {
447 let data: AssocTyValue = from_chalk(db, id); 484 let type_alias: TypeAliasAsValue = from_chalk(db, id);
448 match data { 485 type_alias_associated_ty_value(db, krate, type_alias.0)
449 AssocTyValue::TypeAlias(type_alias) => {
450 type_alias_associated_ty_value(db, krate, type_alias)
451 }
452 _ => Arc::new(builtin::associated_ty_value(db, krate, data).to_chalk(db)),
453 }
454} 486}
455 487
456fn type_alias_associated_ty_value( 488fn type_alias_associated_ty_value(
@@ -473,7 +505,7 @@ fn type_alias_associated_ty_value(
473 let ty = db.ty(type_alias.into()); 505 let ty = db.ty(type_alias.into());
474 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; 506 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
475 let value = rust_ir::AssociatedTyValue { 507 let value = rust_ir::AssociatedTyValue {
476 impl_id: Impl::ImplDef(impl_id).to_chalk(db), 508 impl_id: impl_id.to_chalk(db),
477 associated_ty_id: assoc_ty.to_chalk(db), 509 associated_ty_id: assoc_ty.to_chalk(db),
478 value: make_binders(value_bound, ty.num_binders), 510 value: make_binders(value_bound, ty.num_binders),
479 }; 511 };
@@ -485,7 +517,7 @@ pub(crate) fn fn_def_datum_query(
485 _krate: CrateId, 517 _krate: CrateId,
486 fn_def_id: FnDefId, 518 fn_def_id: FnDefId,
487) -> Arc<FnDefDatum> { 519) -> Arc<FnDefDatum> {
488 let callable_def: CallableDef = from_chalk(db, fn_def_id); 520 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
489 let generic_params = generics(db.upcast(), callable_def.into()); 521 let generic_params = generics(db.upcast(), callable_def.into());
490 let sig = db.callable_item_signature(callable_def); 522 let sig = db.callable_item_signature(callable_def);
491 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 523 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
@@ -507,47 +539,28 @@ pub(crate) fn fn_def_datum_query(
507 ), 539 ),
508 where_clauses, 540 where_clauses,
509 }; 541 };
510 let datum = 542 let datum = FnDefDatum {
511 FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders), abi: () }; 543 id: fn_def_id,
544 abi: (),
545 safety: chalk_ir::Safety::Safe,
546 variadic: sig.value.is_varargs,
547 binders: make_binders(bound, sig.num_binders),
548 };
512 Arc::new(datum) 549 Arc::new(datum)
513} 550}
514 551
515impl From<AdtId> for crate::TypeCtorId { 552impl From<FnDefId> for crate::db::InternedCallableDefId {
516 fn from(struct_id: AdtId) -> Self {
517 struct_id.0
518 }
519}
520
521impl From<crate::TypeCtorId> for AdtId {
522 fn from(type_ctor_id: crate::TypeCtorId) -> Self {
523 chalk_ir::AdtId(type_ctor_id)
524 }
525}
526
527impl From<FnDefId> for crate::CallableDefId {
528 fn from(fn_def_id: FnDefId) -> Self { 553 fn from(fn_def_id: FnDefId) -> Self {
529 InternKey::from_intern_id(fn_def_id.0) 554 InternKey::from_intern_id(fn_def_id.0)
530 } 555 }
531} 556}
532 557
533impl From<crate::CallableDefId> for FnDefId { 558impl From<crate::db::InternedCallableDefId> for FnDefId {
534 fn from(callable_def_id: crate::CallableDefId) -> Self { 559 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self {
535 chalk_ir::FnDefId(callable_def_id.as_intern_id()) 560 chalk_ir::FnDefId(callable_def_id.as_intern_id())
536 } 561 }
537} 562}
538 563
539impl From<ImplId> for crate::traits::GlobalImplId {
540 fn from(impl_id: ImplId) -> Self {
541 InternKey::from_intern_id(impl_id.0)
542 }
543}
544
545impl From<crate::traits::GlobalImplId> for ImplId {
546 fn from(impl_id: crate::traits::GlobalImplId) -> Self {
547 chalk_ir::ImplId(impl_id.as_intern_id())
548 }
549}
550
551impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId { 564impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
552 fn from(id: OpaqueTyId) -> Self { 565 fn from(id: OpaqueTyId) -> Self {
553 InternKey::from_intern_id(id.0) 566 InternKey::from_intern_id(id.0)
@@ -560,14 +573,14 @@ impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
560 } 573 }
561} 574}
562 575
563impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { 576impl From<chalk_ir::ClosureId<Interner>> for crate::db::ClosureId {
564 fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self { 577 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
565 Self::from_intern_id(id.0) 578 Self::from_intern_id(id.0)
566 } 579 }
567} 580}
568 581
569impl From<crate::traits::AssocTyValueId> for rust_ir::AssociatedTyValueId<Interner> { 582impl From<crate::db::ClosureId> for chalk_ir::ClosureId<Interner> {
570 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { 583 fn from(id: crate::db::ClosureId) -> Self {
571 rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id()) 584 chalk_ir::ClosureId(id.as_intern_id())
572 } 585 }
573} 586}
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 ac82ea831..b3e92993d 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -15,9 +15,9 @@ 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, TypeCtor, 20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
21}; 21};
22 22
23use super::interner::*; 23use super::interner::*;
@@ -29,10 +29,17 @@ 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 } => {
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::FnPointer {
35 .intern(&Interner) 36 num_binders: 0,
37 abi: (),
38 safety: chalk_ir::Safety::Safe,
39 variadic: is_varargs,
40 substitution,
41 })
42 .intern(&Interner)
36 } 43 }
37 _ => { 44 _ => {
38 let name = apply_ty.ctor.to_chalk(db); 45 let name = apply_ty.ctor.to_chalk(db);
@@ -61,13 +68,13 @@ impl ToChalk for Ty {
61 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), 68 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner),
62 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 69 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
63 Ty::Dyn(predicates) => { 70 Ty::Dyn(predicates) => {
64 let where_clauses = chalk_ir::QuantifiedWhereClauses::from( 71 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
65 &Interner, 72 &Interner,
66 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), 73 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
67 ); 74 );
68 let bounded_ty = chalk_ir::DynTy { 75 let bounded_ty = chalk_ir::DynTy {
69 bounds: make_binders(where_clauses, 1), 76 bounds: make_binders(where_clauses, 1),
70 lifetime: LIFETIME_PLACEHOLDER.to_lifetime(&Interner), 77 lifetime: FAKE_PLACEHOLDER.to_lifetime(&Interner),
71 }; 78 };
72 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 79 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
73 } 80 }
@@ -92,6 +99,7 @@ impl ToChalk for Ty {
92 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { 99 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
93 TypeName::Error => Ty::Unknown, 100 TypeName::Error => Ty::Unknown,
94 TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), 101 TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution),
102 TypeName::Array => array_from_chalk(db, apply_ty.substitution),
95 _ => { 103 _ => {
96 let ctor = from_chalk(db, apply_ty.name); 104 let ctor = from_chalk(db, apply_ty.name);
97 let parameters = from_chalk(db, apply_ty.substitution); 105 let parameters = from_chalk(db, apply_ty.substitution);
@@ -115,10 +123,22 @@ impl ToChalk for Ty {
115 let parameters = from_chalk(db, opaque_ty.substitution); 123 let parameters = from_chalk(db, opaque_ty.substitution);
116 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) 124 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
117 } 125 }
118 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { 126 chalk_ir::TyData::Function(chalk_ir::FnPointer {
119 let parameters: Substs = from_chalk(db, substitution); 127 num_binders,
128 variadic,
129 substitution,
130 ..
131 }) => {
132 assert_eq!(num_binders, 0);
133 let parameters: Substs = from_chalk(
134 db,
135 substitution.shifted_out(&Interner).expect("fn ptr should have no binders"),
136 );
120 Ty::Apply(ApplicationTy { 137 Ty::Apply(ApplicationTy {
121 ctor: TypeCtor::FnPtr { num_args: (parameters.len() - 1) as u16 }, 138 ctor: TypeCtor::FnPtr {
139 num_args: (parameters.len() - 1) as u16,
140 is_varargs: variadic,
141 },
122 parameters, 142 parameters,
123 }) 143 })
124 } 144 }
@@ -138,7 +158,7 @@ impl ToChalk for Ty {
138 } 158 }
139} 159}
140 160
141const LIFETIME_PLACEHOLDER: PlaceholderIndex = 161const FAKE_PLACEHOLDER: PlaceholderIndex =
142 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; 162 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX };
143 163
144/// We currently don't model lifetimes, but Chalk does. So, we have to insert a 164/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
@@ -149,10 +169,10 @@ fn ref_to_chalk(
149 subst: Substs, 169 subst: Substs,
150) -> chalk_ir::Ty<Interner> { 170) -> chalk_ir::Ty<Interner> {
151 let arg = subst[0].clone().to_chalk(db); 171 let arg = subst[0].clone().to_chalk(db);
152 let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); 172 let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner);
153 chalk_ir::ApplicationTy { 173 chalk_ir::ApplicationTy {
154 name: TypeName::Ref(mutability.to_chalk(db)), 174 name: TypeName::Ref(mutability.to_chalk(db)),
155 substitution: chalk_ir::Substitution::from( 175 substitution: chalk_ir::Substitution::from_iter(
156 &Interner, 176 &Interner,
157 vec![lifetime.cast(&Interner), arg.cast(&Interner)], 177 vec![lifetime.cast(&Interner), arg.cast(&Interner)],
158 ), 178 ),
@@ -173,11 +193,40 @@ fn ref_from_chalk(
173 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) 193 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys))
174} 194}
175 195
196/// We currently don't model constants, but Chalk does. So, we have to insert a
197/// fake constant here, because Chalks built-in logic may expect it to be there.
198fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
199 let arg = subst[0].clone().to_chalk(db);
200 let usize_ty = chalk_ir::ApplicationTy {
201 name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)),
202 substitution: chalk_ir::Substitution::empty(&Interner),
203 }
204 .intern(&Interner);
205 let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty);
206 chalk_ir::ApplicationTy {
207 name: TypeName::Array,
208 substitution: chalk_ir::Substitution::from_iter(
209 &Interner,
210 vec![arg.cast(&Interner), const_.cast(&Interner)],
211 ),
212 }
213 .intern(&Interner)
214}
215
216/// Here we remove the const from the type we got from Chalk.
217fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty {
218 let tys = subst
219 .iter(&Interner)
220 .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone())))
221 .collect();
222 Ty::apply(TypeCtor::Array, Substs(tys))
223}
224
176impl ToChalk for Substs { 225impl ToChalk for Substs {
177 type Chalk = chalk_ir::Substitution<Interner>; 226 type Chalk = chalk_ir::Substitution<Interner>;
178 227
179 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { 228 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))) 229 chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
181 } 230 }
182 231
183 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { 232 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs {
@@ -263,6 +312,7 @@ impl ToChalk for TypeCtor {
263 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), 312 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()),
264 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), 313 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)),
265 TypeCtor::Slice => TypeName::Slice, 314 TypeCtor::Slice => TypeName::Slice,
315 TypeCtor::Array => TypeName::Array,
266 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), 316 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)),
267 TypeCtor::Str => TypeName::Str, 317 TypeCtor::Str => TypeName::Str,
268 TypeCtor::FnDef(callable_def) => { 318 TypeCtor::FnDef(callable_def) => {
@@ -271,20 +321,24 @@ impl ToChalk for TypeCtor {
271 } 321 }
272 TypeCtor::Never => TypeName::Never, 322 TypeCtor::Never => TypeName::Never,
273 323
274 TypeCtor::Adt(_) 324 TypeCtor::Closure { def, expr } => {
275 | TypeCtor::Array 325 let closure_id = db.intern_closure((def, expr));
276 | TypeCtor::FnPtr { .. } 326 TypeName::Closure(closure_id.into())
277 | TypeCtor::Closure { .. } => { 327 }
278 // other TypeCtors get interned and turned into a chalk StructId 328
279 let struct_id = db.intern_type_ctor(self).into(); 329 TypeCtor::Adt(adt_id) => TypeName::Adt(chalk_ir::AdtId(adt_id)),
280 TypeName::Adt(struct_id) 330
331 TypeCtor::FnPtr { .. } => {
332 // This should not be reached, since Chalk doesn't represent
333 // function pointers with TypeName
334 unreachable!()
281 } 335 }
282 } 336 }
283 } 337 }
284 338
285 fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { 339 fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor {
286 match type_name { 340 match type_name {
287 TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), 341 TypeName::Adt(struct_id) => TypeCtor::Adt(struct_id.0),
288 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), 342 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
289 TypeName::OpaqueType(opaque_type_id) => { 343 TypeName::OpaqueType(opaque_type_id) => {
290 TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) 344 TypeCtor::OpaqueType(from_chalk(db, opaque_type_id))
@@ -317,13 +371,16 @@ impl ToChalk for TypeCtor {
317 let callable_def = from_chalk(db, fn_def_id); 371 let callable_def = from_chalk(db, fn_def_id);
318 TypeCtor::FnDef(callable_def) 372 TypeCtor::FnDef(callable_def)
319 } 373 }
374 TypeName::Array => TypeCtor::Array,
320 375
321 TypeName::Array | TypeName::Error => { 376 TypeName::Closure(id) => {
322 // this should not be reached, since we don't represent TypeName::Error with TypeCtor 377 let id: crate::db::ClosureId = id.into();
323 unreachable!() 378 let (def, expr) = db.lookup_intern_closure(id);
379 TypeCtor::Closure { def, expr }
324 } 380 }
325 TypeName::Closure(_) => { 381
326 // FIXME: implement closure support 382 TypeName::Error => {
383 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
327 unreachable!() 384 unreachable!()
328 } 385 }
329 } 386 }
@@ -395,26 +452,26 @@ impl ToChalk for Mutability {
395 } 452 }
396} 453}
397 454
398impl ToChalk for Impl { 455impl ToChalk for hir_def::ImplId {
399 type Chalk = ImplId; 456 type Chalk = ImplId;
400 457
401 fn to_chalk(self, db: &dyn HirDatabase) -> ImplId { 458 fn to_chalk(self, _db: &dyn HirDatabase) -> ImplId {
402 db.intern_chalk_impl(self).into() 459 chalk_ir::ImplId(self.as_intern_id())
403 } 460 }
404 461
405 fn from_chalk(db: &dyn HirDatabase, impl_id: ImplId) -> Impl { 462 fn from_chalk(_db: &dyn HirDatabase, impl_id: ImplId) -> hir_def::ImplId {
406 db.lookup_intern_chalk_impl(impl_id.into()) 463 InternKey::from_intern_id(impl_id.0)
407 } 464 }
408} 465}
409 466
410impl ToChalk for CallableDef { 467impl ToChalk for CallableDefId {
411 type Chalk = FnDefId; 468 type Chalk = FnDefId;
412 469
413 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId { 470 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
414 db.intern_callable_def(self).into() 471 db.intern_callable_def(self).into()
415 } 472 }
416 473
417 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDef { 474 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
418 db.lookup_intern_callable_def(fn_def_id.into()) 475 db.lookup_intern_callable_def(fn_def_id.into())
419 } 476 }
420} 477}
@@ -431,15 +488,20 @@ impl ToChalk for TypeAliasId {
431 } 488 }
432} 489}
433 490
434impl ToChalk for AssocTyValue { 491pub struct TypeAliasAsValue(pub TypeAliasId);
492
493impl ToChalk for TypeAliasAsValue {
435 type Chalk = AssociatedTyValueId; 494 type Chalk = AssociatedTyValueId;
436 495
437 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValueId { 496 fn to_chalk(self, _db: &dyn HirDatabase) -> AssociatedTyValueId {
438 db.intern_assoc_ty_value(self).into() 497 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
439 } 498 }
440 499
441 fn from_chalk(db: &dyn HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { 500 fn from_chalk(
442 db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) 501 _db: &dyn HirDatabase,
502 assoc_ty_value_id: AssociatedTyValueId,
503 ) -> TypeAliasAsValue {
504 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
443 } 505 }
444} 506}
445 507
@@ -492,6 +554,11 @@ impl ToChalk for GenericPredicate {
492 // we shouldn't get these from Chalk 554 // we shouldn't get these from Chalk
493 panic!("encountered LifetimeOutlives from Chalk") 555 panic!("encountered LifetimeOutlives from Chalk")
494 } 556 }
557
558 chalk_ir::WhereClause::TypeOutlives(_) => {
559 // we shouldn't get these from Chalk
560 panic!("encountered TypeOutlives from Chalk")
561 }
495 } 562 }
496 } 563 }
497} 564}
@@ -555,22 +622,42 @@ where
555 type Chalk = chalk_ir::Canonical<T::Chalk>; 622 type Chalk = chalk_ir::Canonical<T::Chalk>;
556 623
557 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { 624 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
558 let parameter = chalk_ir::CanonicalVarKind::new( 625 let kinds = self
559 chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General), 626 .kinds
560 chalk_ir::UniverseIndex::ROOT, 627 .iter()
561 ); 628 .map(|k| match k {
629 TyKind::General => chalk_ir::TyKind::General,
630 TyKind::Integer => chalk_ir::TyKind::Integer,
631 TyKind::Float => chalk_ir::TyKind::Float,
632 })
633 .map(|tk| {
634 chalk_ir::CanonicalVarKind::new(
635 chalk_ir::VariableKind::Ty(tk),
636 chalk_ir::UniverseIndex::ROOT,
637 )
638 });
562 let value = self.value.to_chalk(db); 639 let value = self.value.to_chalk(db);
563 chalk_ir::Canonical { 640 chalk_ir::Canonical {
564 value, 641 value,
565 binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]), 642 binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
566 } 643 }
567 } 644 }
568 645
569 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 646 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
570 Canonical { 647 let kinds = canonical
571 num_vars: canonical.binders.len(&Interner), 648 .binders
572 value: from_chalk(db, canonical.value), 649 .iter(&Interner)
573 } 650 .map(|k| match k.kind {
651 chalk_ir::VariableKind::Ty(tk) => match tk {
652 chalk_ir::TyKind::General => TyKind::General,
653 chalk_ir::TyKind::Integer => TyKind::Integer,
654 chalk_ir::TyKind::Float => TyKind::Float,
655 },
656 chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"),
657 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
658 })
659 .collect();
660 Canonical { kinds, value: from_chalk(db, canonical.value) }
574 } 661 }
575} 662}
576 663
@@ -623,58 +710,12 @@ where
623 } 710 }
624} 711}
625 712
626impl ToChalk for builtin::BuiltinImplData {
627 type Chalk = ImplDatum;
628
629 fn to_chalk(self, db: &dyn HirDatabase) -> ImplDatum {
630 let impl_type = rust_ir::ImplType::External;
631 let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect();
632
633 let impl_datum_bound =
634 rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses };
635 let associated_ty_value_ids =
636 self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect();
637 rust_ir::ImplDatum {
638 binders: make_binders(impl_datum_bound, self.num_vars),
639 impl_type,
640 polarity: rust_ir::Polarity::Positive,
641 associated_ty_value_ids,
642 }
643 }
644
645 fn from_chalk(_db: &dyn HirDatabase, _data: ImplDatum) -> Self {
646 unimplemented!()
647 }
648}
649
650impl ToChalk for builtin::BuiltinImplAssocTyValueData {
651 type Chalk = AssociatedTyValue;
652
653 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue {
654 let ty = self.value.to_chalk(db);
655 let value_bound = rust_ir::AssociatedTyValueBound { ty };
656
657 rust_ir::AssociatedTyValue {
658 associated_ty_id: self.assoc_ty_id.to_chalk(db),
659 impl_id: self.impl_.to_chalk(db),
660 value: make_binders(value_bound, self.num_vars),
661 }
662 }
663
664 fn from_chalk(
665 _db: &dyn HirDatabase,
666 _data: AssociatedTyValue,
667 ) -> builtin::BuiltinImplAssocTyValueData {
668 unimplemented!()
669 }
670}
671
672pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 713pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
673where 714where
674 T: HasInterner<Interner = Interner>, 715 T: HasInterner<Interner = Interner>,
675{ 716{
676 chalk_ir::Binders::new( 717 chalk_ir::Binders::new(
677 chalk_ir::VariableKinds::from( 718 chalk_ir::VariableKinds::from_iter(
678 &Interner, 719 &Interner,
679 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), 720 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars),
680 ), 721 ),
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 }