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