|
1 |
| -//! Conversion code from/to Chalk. |
| 1 | +//! The implementation of `RustIrDatabase` for Chalk, which provides information |
| 2 | +//! about the code that Chalk needs. |
2 | 3 | use std::sync::Arc;
|
3 | 4 |
|
4 | 5 | use log::debug;
|
5 | 6 |
|
6 |
| -use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; |
| 7 | +use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; |
7 | 8 | use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
|
8 | 9 |
|
9 |
| -use base_db::{salsa::InternKey, CrateId}; |
| 10 | +use base_db::CrateId; |
10 | 11 | use hir_def::{
|
11 | 12 | lang_item::{lang_attr, LangItemTarget},
|
12 |
| - AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, |
| 13 | + AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId, |
13 | 14 | };
|
14 | 15 | use hir_expand::name::name;
|
15 | 16 |
|
16 |
| -use super::ChalkContext; |
17 | 17 | use crate::{
|
18 | 18 | db::HirDatabase,
|
19 | 19 | display::HirDisplay,
|
20 |
| - from_assoc_type_id, make_only_type_binders, |
| 20 | + from_assoc_type_id, from_chalk_trait_id, make_only_type_binders, |
| 21 | + mapping::{from_chalk, ToChalk, TypeAliasAsValue}, |
21 | 22 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
22 | 23 | to_assoc_type_id, to_chalk_trait_id,
|
| 24 | + traits::ChalkContext, |
23 | 25 | utils::generics,
|
24 |
| - AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, |
25 |
| - TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause, |
| 26 | + AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy, |
| 27 | + ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, |
| 28 | + TyExt, TyKind, WhereClause, |
26 | 29 | };
|
27 |
| -use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, TypeAliasAsValue}; |
28 | 30 |
|
29 |
| -pub use self::interner::Interner; |
30 |
| -pub(crate) use self::interner::*; |
31 |
| - |
32 |
| -pub(super) mod tls; |
33 |
| -mod interner; |
34 |
| -mod mapping; |
35 |
| - |
36 |
| -pub(crate) trait ToChalk { |
37 |
| - type Chalk; |
38 |
| - fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; |
39 |
| - fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; |
40 |
| -} |
41 |
| - |
42 |
| -pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T |
43 |
| -where |
44 |
| - T: ToChalk<Chalk = ChalkT>, |
45 |
| -{ |
46 |
| - T::from_chalk(db, chalk) |
47 |
| -} |
| 31 | +pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; |
| 32 | +pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; |
| 33 | +pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>; |
| 34 | +pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; |
| 35 | +pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; |
| 36 | + |
| 37 | +pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; |
| 38 | +pub(crate) type TraitId = chalk_ir::TraitId<Interner>; |
| 39 | +pub(crate) type AdtId = chalk_ir::AdtId<Interner>; |
| 40 | +pub(crate) type ImplId = chalk_ir::ImplId<Interner>; |
| 41 | +pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; |
| 42 | +pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; |
| 43 | +pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; |
| 44 | +pub(crate) type Variances = chalk_ir::Variances<Interner>; |
48 | 45 |
|
49 | 46 | impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
50 | 47 | fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
|
@@ -82,7 +79,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
82 | 79 | binders: &CanonicalVarKinds<Interner>,
|
83 | 80 | ) -> Vec<ImplId> {
|
84 | 81 | debug!("impls_for_trait {:?}", trait_id);
|
85 |
| - let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
| 82 | + let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id); |
86 | 83 |
|
87 | 84 | let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
|
88 | 85 |
|
@@ -164,7 +161,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
164 | 161 | Some(LangItemTarget::TraitId(trait_)) => trait_,
|
165 | 162 | _ => return None,
|
166 | 163 | };
|
167 |
| - Some(trait_.to_chalk(self.db)) |
| 164 | + Some(to_chalk_trait_id(trait_)) |
168 | 165 | }
|
169 | 166 |
|
170 | 167 | fn program_clauses_for_env(
|
@@ -311,7 +308,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
311 | 308 | }
|
312 | 309 |
|
313 | 310 | fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
|
314 |
| - let id = from_chalk(self.db, trait_id); |
| 311 | + let id = from_chalk_trait_id(trait_id); |
315 | 312 | self.db.trait_data(id).name.to_string()
|
316 | 313 | }
|
317 | 314 | fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
|
@@ -416,7 +413,7 @@ pub(crate) fn trait_datum_query(
|
416 | 413 | trait_id: TraitId,
|
417 | 414 | ) -> Arc<TraitDatum> {
|
418 | 415 | debug!("trait_datum {:?}", trait_id);
|
419 |
| - let trait_: hir_def::TraitId = from_chalk(db, trait_id); |
| 416 | + let trait_ = from_chalk_trait_id(trait_id); |
420 | 417 | let trait_data = db.trait_data(trait_);
|
421 | 418 | debug!("trait {:?} = {:?}", trait_id, trait_data.name);
|
422 | 419 | let generic_params = generics(db.upcast(), trait_.into());
|
@@ -679,38 +676,65 @@ pub(crate) fn adt_variance_query(
|
679 | 676 | )
|
680 | 677 | }
|
681 | 678 |
|
682 |
| -impl From<FnDefId> for crate::db::InternedCallableDefId { |
683 |
| - fn from(fn_def_id: FnDefId) -> Self { |
684 |
| - InternKey::from_intern_id(fn_def_id.0) |
685 |
| - } |
686 |
| -} |
687 |
| - |
688 |
| -impl From<crate::db::InternedCallableDefId> for FnDefId { |
689 |
| - fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { |
690 |
| - chalk_ir::FnDefId(callable_def_id.as_intern_id()) |
691 |
| - } |
692 |
| -} |
693 |
| - |
694 |
| -impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId { |
695 |
| - fn from(id: OpaqueTyId) -> Self { |
696 |
| - InternKey::from_intern_id(id.0) |
697 |
| - } |
698 |
| -} |
699 |
| - |
700 |
| -impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId { |
701 |
| - fn from(id: crate::db::InternedOpaqueTyId) -> Self { |
702 |
| - chalk_ir::OpaqueTyId(id.as_intern_id()) |
703 |
| - } |
704 |
| -} |
705 |
| - |
706 |
| -impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId { |
707 |
| - fn from(id: chalk_ir::ClosureId<Interner>) -> Self { |
708 |
| - Self::from_intern_id(id.0) |
709 |
| - } |
| 679 | +pub(super) fn convert_where_clauses( |
| 680 | + db: &dyn HirDatabase, |
| 681 | + def: GenericDefId, |
| 682 | + substs: &Substitution, |
| 683 | +) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> { |
| 684 | + let generic_predicates = db.generic_predicates(def); |
| 685 | + let mut result = Vec::with_capacity(generic_predicates.len()); |
| 686 | + for pred in generic_predicates.iter() { |
| 687 | + result.push(pred.clone().substitute(&Interner, substs)); |
| 688 | + } |
| 689 | + result |
710 | 690 | }
|
711 | 691 |
|
712 |
| -impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { |
713 |
| - fn from(id: crate::db::InternedClosureId) -> Self { |
714 |
| - chalk_ir::ClosureId(id.as_intern_id()) |
| 692 | +pub(super) fn generic_predicate_to_inline_bound( |
| 693 | + db: &dyn HirDatabase, |
| 694 | + pred: &QuantifiedWhereClause, |
| 695 | + self_ty: &Ty, |
| 696 | +) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
| 697 | + // An InlineBound is like a GenericPredicate, except the self type is left out. |
| 698 | + // We don't have a special type for this, but Chalk does. |
| 699 | + let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE); |
| 700 | + let (pred, binders) = pred.as_ref().into_value_and_skipped_binders(); |
| 701 | + match pred { |
| 702 | + WhereClause::Implemented(trait_ref) => { |
| 703 | + if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in { |
| 704 | + // we can only convert predicates back to type bounds if they |
| 705 | + // have the expected self type |
| 706 | + return None; |
| 707 | + } |
| 708 | + let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..] |
| 709 | + .iter() |
| 710 | + .map(|ty| ty.clone().cast(&Interner)) |
| 711 | + .collect(); |
| 712 | + let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
| 713 | + Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound))) |
| 714 | + } |
| 715 | + WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
| 716 | + if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in { |
| 717 | + return None; |
| 718 | + } |
| 719 | + let trait_ = projection_ty.trait_(db); |
| 720 | + let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..] |
| 721 | + .iter() |
| 722 | + .map(|ty| ty.clone().cast(&Interner)) |
| 723 | + .collect(); |
| 724 | + let alias_eq_bound = rust_ir::AliasEqBound { |
| 725 | + value: ty.clone(), |
| 726 | + trait_bound: rust_ir::TraitBound { |
| 727 | + trait_id: to_chalk_trait_id(trait_), |
| 728 | + args_no_self, |
| 729 | + }, |
| 730 | + associated_ty_id: projection_ty.associated_ty_id, |
| 731 | + parameters: Vec::new(), // FIXME we don't support generic associated types yet |
| 732 | + }; |
| 733 | + Some(chalk_ir::Binders::new( |
| 734 | + binders, |
| 735 | + rust_ir::InlineBound::AliasEqBound(alias_eq_bound), |
| 736 | + )) |
| 737 | + } |
| 738 | + _ => None, |
715 | 739 | }
|
716 | 740 | }
|
0 commit comments