|
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