aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/chalk_db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/chalk_db.rs')
-rw-r--r--crates/hir_ty/src/chalk_db.rs714
1 files changed, 714 insertions, 0 deletions
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs
new file mode 100644
index 000000000..566e4f406
--- /dev/null
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -0,0 +1,714 @@
1//! Conversion code from/to Chalk.
2use std::sync::Arc;
3
4use log::debug;
5
6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8
9use base_db::{salsa::InternKey, CrateId};
10use hir_def::{
11 lang_item::{lang_attr, LangItemTarget},
12 AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId,
13};
14use hir_expand::name::name;
15
16use crate::{AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, traits::ChalkContext, db::HirDatabase, display::HirDisplay, from_assoc_type_id, make_only_type_binders, mapping::{convert_where_clauses, generic_predicate_to_inline_bound, TypeAliasAsValue}, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, utils::generics};
17
18pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
19pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
20pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
21pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
22pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
23
24pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
25pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
26pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
27pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
28pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
29pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
30pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
31pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
32pub(crate) type Variances = chalk_ir::Variances<Interner>;
33
34pub(crate) trait ToChalk {
35 type Chalk;
36 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
37 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
38}
39
40pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
41where
42 T: ToChalk<Chalk = ChalkT>,
43{
44 T::from_chalk(db, chalk)
45}
46
47impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
48 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
49 self.db.associated_ty_data(id)
50 }
51 fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> {
52 self.db.trait_datum(self.krate, trait_id)
53 }
54 fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> {
55 self.db.struct_datum(self.krate, struct_id)
56 }
57 fn adt_repr(&self, _struct_id: AdtId) -> Arc<rust_ir::AdtRepr<Interner>> {
58 // FIXME: keep track of these
59 Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
60 }
61 fn discriminant_type(&self, _ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
62 // FIXME: keep track of this
63 chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(&Interner)
64 }
65 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
66 self.db.impl_datum(self.krate, impl_id)
67 }
68
69 fn fn_def_datum(
70 &self,
71 fn_def_id: chalk_ir::FnDefId<Interner>,
72 ) -> Arc<rust_ir::FnDefDatum<Interner>> {
73 self.db.fn_def_datum(self.krate, fn_def_id)
74 }
75
76 fn impls_for_trait(
77 &self,
78 trait_id: TraitId,
79 parameters: &[chalk_ir::GenericArg<Interner>],
80 binders: &CanonicalVarKinds<Interner>,
81 ) -> Vec<ImplId> {
82 debug!("impls_for_trait {:?}", trait_id);
83 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
84
85 let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
86
87 fn binder_kind(
88 ty: &Ty,
89 binders: &CanonicalVarKinds<Interner>,
90 ) -> Option<chalk_ir::TyVariableKind> {
91 if let TyKind::BoundVar(bv) = ty.kind(&Interner) {
92 let binders = binders.as_slice(&Interner);
93 if bv.debruijn == DebruijnIndex::INNERMOST {
94 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
95 return Some(tk);
96 }
97 }
98 }
99 None
100 }
101
102 let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
103 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
104 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
105 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
106 _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
107 };
108
109 // Note: Since we're using impls_for_trait, only impls where the trait
110 // can be resolved should ever reach Chalk. Symbol’s value as variable is void: impl_datum relies on that
111 // and will panic if the trait can't be resolved.
112 let in_deps = self.db.trait_impls_in_deps(self.krate);
113 let in_self = self.db.trait_impls_in_crate(self.krate);
114 let impl_maps = [in_deps, in_self];
115
116 let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
117
118 let result: Vec<_> = if fps.is_empty() {
119 debug!("Unrestricted search for {:?} impls...", trait_);
120 impl_maps
121 .iter()
122 .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk))
123 .collect()
124 } else {
125 impl_maps
126 .iter()
127 .flat_map(|crate_impl_defs| {
128 fps.iter().flat_map(move |fp| {
129 crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
130 })
131 })
132 .collect()
133 };
134
135 debug!("impls_for_trait returned {} impls", result.len());
136 result
137 }
138 fn impl_provided_for(&self, auto_trait_id: TraitId, kind: &chalk_ir::TyKind<Interner>) -> bool {
139 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, kind);
140 false // FIXME
141 }
142 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> {
143 self.db.associated_ty_value(self.krate, id)
144 }
145
146 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<Interner>> {
147 vec![]
148 }
149 fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec<ImplId> {
150 // We don't do coherence checking (yet)
151 unimplemented!()
152 }
153 fn interner(&self) -> &Interner {
154 &Interner
155 }
156 fn well_known_trait_id(
157 &self,
158 well_known_trait: rust_ir::WellKnownTrait,
159 ) -> Option<chalk_ir::TraitId<Interner>> {
160 let lang_attr = lang_attr_from_well_known_trait(well_known_trait);
161 let trait_ = match self.db.lang_item(self.krate, lang_attr.into()) {
162 Some(LangItemTarget::TraitId(trait_)) => trait_,
163 _ => return None,
164 };
165 Some(trait_.to_chalk(self.db))
166 }
167
168 fn program_clauses_for_env(
169 &self,
170 environment: &chalk_ir::Environment<Interner>,
171 ) -> chalk_ir::ProgramClauses<Interner> {
172 self.db.program_clauses_for_chalk_env(self.krate, environment.clone())
173 }
174
175 fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> {
176 let full_id = self.db.lookup_intern_impl_trait_id(id.into());
177 let bound = match full_id {
178 crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
179 let datas = self
180 .db
181 .return_type_impl_traits(func)
182 .expect("impl trait id without impl traits");
183 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
184 let data = &datas.impl_traits[idx as usize];
185 let bound = OpaqueTyDatumBound {
186 bounds: make_only_type_binders(
187 1,
188 data.bounds.skip_binders().iter().cloned().collect(),
189 ),
190 where_clauses: make_only_type_binders(0, vec![]),
191 };
192 chalk_ir::Binders::new(binders, bound)
193 }
194 crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
195 if let Some((future_trait, future_output)) = self
196 .db
197 .lang_item(self.krate, "future_trait".into())
198 .and_then(|item| item.as_trait())
199 .and_then(|trait_| {
200 let alias =
201 self.db.trait_data(trait_).associated_type_by_name(&name![Output])?;
202 Some((trait_, alias))
203 })
204 {
205 // Making up Symbol’s value as variable is void: AsyncBlock<T>:
206 //
207 // |--------------------OpaqueTyDatum-------------------|
208 // |-------------OpaqueTyDatumBound--------------|
209 // for<T> <Self> [Future<Self>, Future::Output<Self> = T]
210 // ^1 ^0 ^0 ^0 ^1
211 let impl_bound = WhereClause::Implemented(TraitRef {
212 trait_id: to_chalk_trait_id(future_trait),
213 // Self type as the first parameter.
214 substitution: Substitution::from1(
215 &Interner,
216 TyKind::BoundVar(BoundVar {
217 debruijn: DebruijnIndex::INNERMOST,
218 index: 0,
219 })
220 .intern(&Interner),
221 ),
222 });
223 let proj_bound = WhereClause::AliasEq(AliasEq {
224 alias: AliasTy::Projection(ProjectionTy {
225 associated_ty_id: to_assoc_type_id(future_output),
226 // Self type as the first parameter.
227 substitution: Substitution::from1(
228 &Interner,
229 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
230 .intern(&Interner),
231 ),
232 }),
233 // The parameter of the opaque type.
234 ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
235 .intern(&Interner),
236 });
237 let bound = OpaqueTyDatumBound {
238 bounds: make_only_type_binders(
239 1,
240 vec![
241 crate::wrap_empty_binders(impl_bound),
242 crate::wrap_empty_binders(proj_bound),
243 ],
244 ),
245 where_clauses: make_only_type_binders(0, vec![]),
246 };
247 // The opaque type has 1 parameter.
248 make_only_type_binders(1, bound)
249 } else {
250 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
251 let bound = OpaqueTyDatumBound {
252 bounds: make_only_type_binders(0, vec![]),
253 where_clauses: make_only_type_binders(0, vec![]),
254 };
255 // The opaque type has 1 parameter.
256 make_only_type_binders(1, bound)
257 }
258 }
259 };
260
261 Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound })
262 }
263
264 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
265 // FIXME: actually provide the hidden type; it is relevant for auto traits
266 TyKind::Error.intern(&Interner)
267 }
268
269 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
270 // FIXME: implement actual object safety
271 true
272 }
273
274 fn closure_kind(
275 &self,
276 _closure_id: chalk_ir::ClosureId<Interner>,
277 _substs: &chalk_ir::Substitution<Interner>,
278 ) -> rust_ir::ClosureKind {
279 // Fn is the closure kind that implements all three traits
280 rust_ir::ClosureKind::Fn
281 }
282 fn closure_inputs_and_output(
283 &self,
284 _closure_id: chalk_ir::ClosureId<Interner>,
285 substs: &chalk_ir::Substitution<Interner>,
286 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
287 let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
288 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
289 let io = rust_ir::FnDefInputsAndOutputDatum {
290 argument_types: sig.params().iter().cloned().collect(),
291 return_type: sig.ret().clone(),
292 };
293 make_only_type_binders(0, io.shifted_in(&Interner))
294 }
295 fn closure_upvars(
296 &self,
297 _closure_id: chalk_ir::ClosureId<Interner>,
298 _substs: &chalk_ir::Substitution<Interner>,
299 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
300 let ty = TyBuilder::unit();
301 make_only_type_binders(0, ty)
302 }
303 fn closure_fn_substitution(
304 &self,
305 _closure_id: chalk_ir::ClosureId<Interner>,
306 _substs: &chalk_ir::Substitution<Interner>,
307 ) -> chalk_ir::Substitution<Interner> {
308 Substitution::empty(&Interner)
309 }
310
311 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
312 let id = from_chalk(self.db, trait_id);
313 self.db.trait_data(id).name.to_string()
314 }
315 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
316 match adt_id {
317 hir_def::AdtId::StructId(id) => self.db.struct_data(id).name.to_string(),
318 hir_def::AdtId::EnumId(id) => self.db.enum_data(id).name.to_string(),
319 hir_def::AdtId::UnionId(id) => self.db.union_data(id).name.to_string(),
320 }
321 }
322 fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String {
323 let id = self.db.associated_ty_data(assoc_ty_id).name;
324 self.db.type_alias_data(id).name.to_string()
325 }
326 fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String {
327 format!("Opaque_{}", opaque_ty_id.0)
328 }
329 fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId<Interner>) -> String {
330 format!("fn_{}", fn_def_id.0)
331 }
332 fn generator_datum(
333 &self,
334 _: chalk_ir::GeneratorId<Interner>,
335 ) -> std::sync::Arc<chalk_solve::rust_ir::GeneratorDatum<Interner>> {
336 // FIXME
337 unimplemented!()
338 }
339 fn generator_witness_datum(
340 &self,
341 _: chalk_ir::GeneratorId<Interner>,
342 ) -> std::sync::Arc<chalk_solve::rust_ir::GeneratorWitnessDatum<Interner>> {
343 // FIXME
344 unimplemented!()
345 }
346
347 fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
348 self
349 }
350}
351
352impl<'a> chalk_ir::UnificationDatabase<Interner> for ChalkContext<'a> {
353 fn fn_def_variance(
354 &self,
355 fn_def_id: chalk_ir::FnDefId<Interner>,
356 ) -> chalk_ir::Variances<Interner> {
357 self.db.fn_def_variance(self.krate, fn_def_id)
358 }
359
360 fn adt_variance(&self, adt_id: chalk_ir::AdtId<Interner>) -> chalk_ir::Variances<Interner> {
361 self.db.adt_variance(self.krate, adt_id)
362 }
363}
364
365pub(crate) fn program_clauses_for_chalk_env_query(
366 db: &dyn HirDatabase,
367 krate: CrateId,
368 environment: chalk_ir::Environment<Interner>,
369) -> chalk_ir::ProgramClauses<Interner> {
370 chalk_solve::program_clauses_for_env(&ChalkContext { db, krate }, &environment)
371}
372
373pub(crate) fn associated_ty_data_query(
374 db: &dyn HirDatabase,
375 id: AssocTypeId,
376) -> Arc<AssociatedTyDatum> {
377 debug!("associated_ty_data {:?}", id);
378 let type_alias: TypeAliasId = from_assoc_type_id(id);
379 let trait_ = match type_alias.lookup(db.upcast()).container {
380 AssocContainerId::TraitId(t) => t,
381 _ => panic!("associated type not in trait"),
382 };
383
384 // Lower bounds -- we could/should maybe move this to a separate query in `lower`
385 let type_alias_data = db.type_alias_data(type_alias);
386 let generic_params = generics(db.upcast(), type_alias.into());
387 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
388 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
389 let ctx = crate::TyLoweringContext::new(db, &resolver)
390 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
391 let self_ty =
392 TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
393 let bounds = type_alias_data
394 .bounds
395 .iter()
396 .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
397 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
398 .collect();
399
400 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
401 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
402 let datum = AssociatedTyDatum {
403 trait_id: to_chalk_trait_id(trait_),
404 id,
405 name: type_alias,
406 binders: make_only_type_binders(generic_params.len(), bound_data),
407 };
408 Arc::new(datum)
409}
410
411pub(crate) fn trait_datum_query(
412 db: &dyn HirDatabase,
413 krate: CrateId,
414 trait_id: TraitId,
415) -> Arc<TraitDatum> {
416 debug!("trait_datum {:?}", trait_id);
417 let trait_: hir_def::TraitId = from_chalk(db, trait_id);
418 let trait_data = db.trait_data(trait_);
419 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
420 let generic_params = generics(db.upcast(), trait_.into());
421 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
422 let flags = rust_ir::TraitFlags {
423 auto: trait_data.is_auto,
424 upstream: trait_.lookup(db.upcast()).container.krate() != krate,
425 non_enumerable: true,
426 coinductive: false, // only relevant for Chalk testing
427 // FIXME: set these flags correctly
428 marker: false,
429 fundamental: false,
430 };
431 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
432 let associated_ty_ids =
433 trait_data.associated_types().map(|type_alias| to_assoc_type_id(type_alias)).collect();
434 let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
435 let well_known =
436 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
437 let trait_datum = TraitDatum {
438 id: trait_id,
439 binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound),
440 flags,
441 associated_ty_ids,
442 well_known,
443 };
444 Arc::new(trait_datum)
445}
446
447fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> {
448 Some(match name {
449 "sized" => WellKnownTrait::Sized,
450 "copy" => WellKnownTrait::Copy,
451 "clone" => WellKnownTrait::Clone,
452 "drop" => WellKnownTrait::Drop,
453 "fn_once" => WellKnownTrait::FnOnce,
454 "fn_mut" => WellKnownTrait::FnMut,
455 "fn" => WellKnownTrait::Fn,
456 "unsize" => WellKnownTrait::Unsize,
457 "coerce_unsized" => WellKnownTrait::CoerceUnsized,
458 "discriminant_kind" => WellKnownTrait::DiscriminantKind,
459 _ => return None,
460 })
461}
462
463fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str {
464 match attr {
465 WellKnownTrait::Sized => "sized",
466 WellKnownTrait::Copy => "copy",
467 WellKnownTrait::Clone => "clone",
468 WellKnownTrait::Drop => "drop",
469 WellKnownTrait::FnOnce => "fn_once",
470 WellKnownTrait::FnMut => "fn_mut",
471 WellKnownTrait::Fn => "fn",
472 WellKnownTrait::Unsize => "unsize",
473 WellKnownTrait::Unpin => "unpin",
474 WellKnownTrait::CoerceUnsized => "coerce_unsized",
475 WellKnownTrait::DiscriminantKind => "discriminant_kind",
476 }
477}
478
479pub(crate) fn struct_datum_query(
480 db: &dyn HirDatabase,
481 krate: CrateId,
482 struct_id: AdtId,
483) -> Arc<StructDatum> {
484 debug!("struct_datum {:?}", struct_id);
485 let chalk_ir::AdtId(adt_id) = struct_id;
486 let num_params = generics(db.upcast(), adt_id.into()).len();
487 let upstream = adt_id.module(db.upcast()).krate() != krate;
488 let where_clauses = {
489 let generic_params = generics(db.upcast(), adt_id.into());
490 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
491 convert_where_clauses(db, adt_id.into(), &bound_vars)
492 };
493 let flags = rust_ir::AdtFlags {
494 upstream,
495 // FIXME set fundamental and phantom_data flags correctly
496 fundamental: false,
497 phantom_data: false,
498 };
499 // FIXME provide enum variants properly (for auto traits)
500 let variant = rust_ir::AdtVariantDatum {
501 fields: Vec::new(), // FIXME add fields (only relevant for auto traits),
502 };
503 let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses };
504 let struct_datum = StructDatum {
505 // FIXME set ADT kind
506 kind: rust_ir::AdtKind::Struct,
507 id: struct_id,
508 binders: make_only_type_binders(num_params, struct_datum_bound),
509 flags,
510 };
511 Arc::new(struct_datum)
512}
513
514pub(crate) fn impl_datum_query(
515 db: &dyn HirDatabase,
516 krate: CrateId,
517 impl_id: ImplId,
518) -> Arc<ImplDatum> {
519 let _p = profile::span("impl_datum");
520 debug!("impl_datum {:?}", impl_id);
521 let impl_: hir_def::ImplId = from_chalk(db, impl_id);
522 impl_def_datum(db, krate, impl_id, impl_)
523}
524
525fn impl_def_datum(
526 db: &dyn HirDatabase,
527 krate: CrateId,
528 chalk_id: ImplId,
529 impl_id: hir_def::ImplId,
530) -> Arc<ImplDatum> {
531 let trait_ref = db
532 .impl_trait(impl_id)
533 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
534 .expect("invalid impl passed to Chalk")
535 .into_value_and_skipped_binders()
536 .0;
537 let impl_data = db.impl_data(impl_id);
538
539 let generic_params = generics(db.upcast(), impl_id.into());
540 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
541 let trait_ = trait_ref.hir_trait_id();
542 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate {
543 rust_ir::ImplType::Local
544 } else {
545 rust_ir::ImplType::External
546 };
547 let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars);
548 let negative = impl_data.is_negative;
549 debug!(
550 "impl {:?}: {}{} where {:?}",
551 chalk_id,
552 if negative { "!" } else { "" },
553 trait_ref.display(db),
554 where_clauses
555 );
556
557 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
558
559 let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
560 let trait_data = db.trait_data(trait_);
561 let associated_ty_value_ids = impl_data
562 .items
563 .iter()
564 .filter_map(|item| match item {
565 AssocItemId::TypeAliasId(type_alias) => Some(*type_alias),
566 _ => None,
567 })
568 .filter(|&type_alias| {
569 // don't include associated types that don't exist in the trait
570 let name = &db.type_alias_data(type_alias).name;
571 trait_data.associated_type_by_name(name).is_some()
572 })
573 .map(|type_alias| TypeAliasAsValue(type_alias).to_chalk(db))
574 .collect();
575 debug!("impl_datum: {:?}", impl_datum_bound);
576 let impl_datum = ImplDatum {
577 binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound),
578 impl_type,
579 polarity,
580 associated_ty_value_ids,
581 };
582 Arc::new(impl_datum)
583}
584
585pub(crate) fn associated_ty_value_query(
586 db: &dyn HirDatabase,
587 krate: CrateId,
588 id: AssociatedTyValueId,
589) -> Arc<AssociatedTyValue> {
590 let type_alias: TypeAliasAsValue = from_chalk(db, id);
591 type_alias_associated_ty_value(db, krate, type_alias.0)
592}
593
594fn type_alias_associated_ty_value(
595 db: &dyn HirDatabase,
596 _krate: CrateId,
597 type_alias: TypeAliasId,
598) -> Arc<AssociatedTyValue> {
599 let type_alias_data = db.type_alias_data(type_alias);
600 let impl_id = match type_alias.lookup(db.upcast()).container {
601 AssocContainerId::ImplId(it) => it,
602 _ => panic!("assoc ty value should be in impl"),
603 };
604
605 let trait_ref = db
606 .impl_trait(impl_id)
607 .expect("assoc ty value should not exist")
608 .into_value_and_skipped_binders()
609 .0; // we don't return any assoc ty values if the impl'd trait can't be resolved
610
611 let assoc_ty = db
612 .trait_data(trait_ref.hir_trait_id())
613 .associated_type_by_name(&type_alias_data.name)
614 .expect("assoc ty value should not exist"); // validated when building the impl data as well
615 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
616 let value_bound = rust_ir::AssociatedTyValueBound { ty };
617 let value = rust_ir::AssociatedTyValue {
618 impl_id: impl_id.to_chalk(db),
619 associated_ty_id: to_assoc_type_id(assoc_ty),
620 value: chalk_ir::Binders::new(binders, value_bound),
621 };
622 Arc::new(value)
623}
624
625pub(crate) fn fn_def_datum_query(
626 db: &dyn HirDatabase,
627 _krate: CrateId,
628 fn_def_id: FnDefId,
629) -> Arc<FnDefDatum> {
630 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
631 let generic_params = generics(db.upcast(), callable_def.into());
632 let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
633 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
634 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
635 let bound = rust_ir::FnDefDatumBound {
636 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
637 inputs_and_output: make_only_type_binders(
638 0,
639 rust_ir::FnDefInputsAndOutputDatum {
640 argument_types: sig.params().iter().cloned().collect(),
641 return_type: sig.ret().clone(),
642 }
643 .shifted_in(&Interner),
644 ),
645 where_clauses,
646 };
647 let datum = FnDefDatum {
648 id: fn_def_id,
649 sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs },
650 binders: chalk_ir::Binders::new(binders, bound),
651 };
652 Arc::new(datum)
653}
654
655pub(crate) fn fn_def_variance_query(
656 db: &dyn HirDatabase,
657 _krate: CrateId,
658 fn_def_id: FnDefId,
659) -> Variances {
660 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
661 let generic_params = generics(db.upcast(), callable_def.into());
662 Variances::from_iter(
663 &Interner,
664 std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
665 )
666}
667
668pub(crate) fn adt_variance_query(
669 db: &dyn HirDatabase,
670 _krate: CrateId,
671 chalk_ir::AdtId(adt_id): AdtId,
672) -> Variances {
673 let generic_params = generics(db.upcast(), adt_id.into());
674 Variances::from_iter(
675 &Interner,
676 std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
677 )
678}
679
680impl From<FnDefId> for crate::db::InternedCallableDefId {
681 fn from(fn_def_id: FnDefId) -> Self {
682 InternKey::from_intern_id(fn_def_id.0)
683 }
684}
685
686impl From<crate::db::InternedCallableDefId> for FnDefId {
687 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self {
688 chalk_ir::FnDefId(callable_def_id.as_intern_id())
689 }
690}
691
692impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
693 fn from(id: OpaqueTyId) -> Self {
694 InternKey::from_intern_id(id.0)
695 }
696}
697
698impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
699 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
700 chalk_ir::OpaqueTyId(id.as_intern_id())
701 }
702}
703
704impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
705 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
706 Self::from_intern_id(id.0)
707 }
708}
709
710impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
711 fn from(id: crate::db::InternedClosureId) -> Self {
712 chalk_ir::ClosureId(id.as_intern_id())
713 }
714}