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