diff options
author | Florian Diebold <[email protected]> | 2019-12-21 14:00:44 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-12-22 23:08:03 +0000 |
commit | 4053fcfca0e33f133c53fa755c1b1bcc0b4c11bb (patch) | |
tree | 6a77ae7692757830e4c0f5966824b6cd6979d4a2 /crates/ra_hir_ty/src/traits/chalk.rs | |
parent | 6b5efe5bdab160278469417734f4bb619c7bac61 (diff) |
Introduce our own Chalk TypeFamily, instead of using ChalkIr
It's not very different, except we can directly use Salsa IDs instead of casting
them. This means we need to refactor the handling of errors to get rid of
UNKNOWN_TRAIT though.
Diffstat (limited to 'crates/ra_hir_ty/src/traits/chalk.rs')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 156 |
1 files changed, 89 insertions, 67 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index d53d3fdeb..9e38337e5 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! Conversion code from/to Chalk. | 1 | //! Conversion code from/to Chalk. |
2 | use std::sync::Arc; | 2 | use std::{fmt, sync::Arc}; |
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
@@ -17,7 +17,73 @@ use crate::{ | |||
17 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 17 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | pub type TypeFamily = chalk_ir::family::ChalkIr; | 20 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] |
21 | pub struct TypeFamily {} | ||
22 | |||
23 | impl chalk_ir::family::TypeFamily for TypeFamily { | ||
24 | type InternedType = Box<chalk_ir::TyData<Self>>; | ||
25 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | ||
26 | type InternedParameter = chalk_ir::ParameterData<Self>; | ||
27 | type DefId = InternId; | ||
28 | |||
29 | // FIXME: implement these | ||
30 | fn debug_struct_id( | ||
31 | _type_kind_id: chalk_ir::StructId<Self>, | ||
32 | _fmt: &mut fmt::Formatter<'_>, | ||
33 | ) -> Option<fmt::Result> { | ||
34 | None | ||
35 | } | ||
36 | |||
37 | fn debug_trait_id( | ||
38 | _type_kind_id: chalk_ir::TraitId<Self>, | ||
39 | _fmt: &mut fmt::Formatter<'_>, | ||
40 | ) -> Option<fmt::Result> { | ||
41 | None | ||
42 | } | ||
43 | |||
44 | fn debug_assoc_type_id( | ||
45 | _id: chalk_ir::AssocTypeId<Self>, | ||
46 | _fmt: &mut fmt::Formatter<'_>, | ||
47 | ) -> Option<fmt::Result> { | ||
48 | None | ||
49 | } | ||
50 | |||
51 | fn debug_projection( | ||
52 | _projection: &chalk_ir::ProjectionTy<Self>, | ||
53 | _fmt: &mut fmt::Formatter<'_>, | ||
54 | ) -> Option<fmt::Result> { | ||
55 | None | ||
56 | } | ||
57 | |||
58 | fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | ||
59 | Box::new(ty) | ||
60 | } | ||
61 | |||
62 | fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> { | ||
63 | ty | ||
64 | } | ||
65 | |||
66 | fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> { | ||
67 | lifetime | ||
68 | } | ||
69 | |||
70 | fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> { | ||
71 | lifetime | ||
72 | } | ||
73 | |||
74 | fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> { | ||
75 | parameter | ||
76 | } | ||
77 | |||
78 | fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> { | ||
79 | parameter | ||
80 | } | ||
81 | } | ||
82 | |||
83 | impl chalk_ir::family::HasTypeFamily for TypeFamily { | ||
84 | type TypeFamily = Self; | ||
85 | } | ||
86 | |||
21 | pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>; | 87 | pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>; |
22 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>; | 88 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>; |
23 | pub type TraitId = chalk_ir::TraitId<TypeFamily>; | 89 | pub type TraitId = chalk_ir::TraitId<TypeFamily>; |
@@ -29,9 +95,6 @@ pub type ImplDatum = chalk_rust_ir::ImplDatum<TypeFamily>; | |||
29 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; | 95 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; |
30 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>; | 96 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>; |
31 | 97 | ||
32 | /// This represents a trait whose name we could not resolve. | ||
33 | const UNKNOWN_TRAIT: TraitId = chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); | ||
34 | |||
35 | pub(super) trait ToChalk { | 98 | pub(super) trait ToChalk { |
36 | type Chalk; | 99 | type Chalk; |
37 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; | 100 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; |
@@ -162,11 +225,11 @@ impl ToChalk for hir_def::TraitId { | |||
162 | type Chalk = TraitId; | 225 | type Chalk = TraitId; |
163 | 226 | ||
164 | fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { | 227 | fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { |
165 | chalk_ir::TraitId(id_to_chalk(self)) | 228 | chalk_ir::TraitId(self.as_intern_id()) |
166 | } | 229 | } |
167 | 230 | ||
168 | fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { | 231 | fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { |
169 | id_from_chalk(trait_id.0) | 232 | InternKey::from_intern_id(trait_id.0) |
170 | } | 233 | } |
171 | } | 234 | } |
172 | 235 | ||
@@ -215,11 +278,11 @@ impl ToChalk for TypeAliasId { | |||
215 | type Chalk = AssocTypeId; | 278 | type Chalk = AssocTypeId; |
216 | 279 | ||
217 | fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { | 280 | fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { |
218 | chalk_ir::AssocTypeId(id_to_chalk(self)) | 281 | chalk_ir::AssocTypeId(self.as_intern_id()) |
219 | } | 282 | } |
220 | 283 | ||
221 | fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { | 284 | fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { |
222 | id_from_chalk(type_alias_id.0) | 285 | InternKey::from_intern_id(type_alias_id.0) |
223 | } | 286 | } |
224 | } | 287 | } |
225 | 288 | ||
@@ -250,13 +313,7 @@ impl ToChalk for GenericPredicate { | |||
250 | }), | 313 | }), |
251 | 0, | 314 | 0, |
252 | ), | 315 | ), |
253 | GenericPredicate::Error => { | 316 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), |
254 | let impossible_trait_ref = chalk_ir::TraitRef { | ||
255 | trait_id: UNKNOWN_TRAIT, | ||
256 | parameters: vec![Ty::Unknown.to_chalk(db).cast()], | ||
257 | }; | ||
258 | make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) | ||
259 | } | ||
260 | } | 317 | } |
261 | } | 318 | } |
262 | 319 | ||
@@ -266,10 +323,6 @@ impl ToChalk for GenericPredicate { | |||
266 | ) -> GenericPredicate { | 323 | ) -> GenericPredicate { |
267 | match where_clause.value { | 324 | match where_clause.value { |
268 | chalk_ir::WhereClause::Implemented(tr) => { | 325 | chalk_ir::WhereClause::Implemented(tr) => { |
269 | if tr.trait_id == UNKNOWN_TRAIT { | ||
270 | // FIXME we need an Error enum on the Chalk side to avoid this | ||
271 | return GenericPredicate::Error; | ||
272 | } | ||
273 | GenericPredicate::Implemented(from_chalk(db, tr)) | 326 | GenericPredicate::Implemented(from_chalk(db, tr)) |
274 | } | 327 | } |
275 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { | 328 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { |
@@ -460,9 +513,8 @@ fn convert_where_clauses( | |||
460 | let mut result = Vec::with_capacity(generic_predicates.len()); | 513 | let mut result = Vec::with_capacity(generic_predicates.len()); |
461 | for pred in generic_predicates.iter() { | 514 | for pred in generic_predicates.iter() { |
462 | if pred.is_error() { | 515 | if pred.is_error() { |
463 | // HACK: Return just the single predicate (which is always false | 516 | // skip errored predicates completely |
464 | // anyway), otherwise Chalk can easily get into slow situations | 517 | continue; |
465 | return vec![pred.clone().subst(substs).to_chalk(db)]; | ||
466 | } | 518 | } |
467 | result.push(pred.clone().subst(substs).to_chalk(db)); | 519 | result.push(pred.clone().subst(substs).to_chalk(db)); |
468 | } | 520 | } |
@@ -491,10 +543,11 @@ where | |||
491 | parameters: &[Parameter<TypeFamily>], | 543 | parameters: &[Parameter<TypeFamily>], |
492 | ) -> Vec<ImplId> { | 544 | ) -> Vec<ImplId> { |
493 | debug!("impls_for_trait {:?}", trait_id); | 545 | debug!("impls_for_trait {:?}", trait_id); |
494 | if trait_id == UNKNOWN_TRAIT { | ||
495 | return Vec::new(); | ||
496 | } | ||
497 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); | 546 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
547 | |||
548 | // Note: Since we're using impls_for_trait, only impls where the trait | ||
549 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | ||
550 | // and will panic if the trait can't be resolved. | ||
498 | let mut result: Vec<_> = self | 551 | let mut result: Vec<_> = self |
499 | .db | 552 | .db |
500 | .impls_for_trait(self.krate, trait_.into()) | 553 | .impls_for_trait(self.krate, trait_.into()) |
@@ -566,24 +619,6 @@ pub(crate) fn trait_datum_query( | |||
566 | trait_id: TraitId, | 619 | trait_id: TraitId, |
567 | ) -> Arc<TraitDatum> { | 620 | ) -> Arc<TraitDatum> { |
568 | debug!("trait_datum {:?}", trait_id); | 621 | debug!("trait_datum {:?}", trait_id); |
569 | if trait_id == UNKNOWN_TRAIT { | ||
570 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; | ||
571 | |||
572 | let flags = chalk_rust_ir::TraitFlags { | ||
573 | auto: false, | ||
574 | marker: false, | ||
575 | upstream: true, | ||
576 | fundamental: false, | ||
577 | non_enumerable: true, | ||
578 | coinductive: false, | ||
579 | }; | ||
580 | return Arc::new(TraitDatum { | ||
581 | id: trait_id, | ||
582 | binders: make_binders(trait_datum_bound, 1), | ||
583 | flags, | ||
584 | associated_ty_ids: vec![], | ||
585 | }); | ||
586 | } | ||
587 | let trait_: hir_def::TraitId = from_chalk(db, trait_id); | 622 | let trait_: hir_def::TraitId = from_chalk(db, trait_id); |
588 | let trait_data = db.trait_data(trait_); | 623 | let trait_data = db.trait_data(trait_); |
589 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); | 624 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); |
@@ -653,9 +688,8 @@ pub(crate) fn impl_datum_query( | |||
653 | let impl_: Impl = from_chalk(db, impl_id); | 688 | let impl_: Impl = from_chalk(db, impl_id); |
654 | match impl_ { | 689 | match impl_ { |
655 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 690 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
656 | _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), | 691 | _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)), |
657 | } | 692 | } |
658 | .unwrap_or_else(invalid_impl_datum) | ||
659 | } | 693 | } |
660 | 694 | ||
661 | fn impl_block_datum( | 695 | fn impl_block_datum( |
@@ -663,8 +697,11 @@ fn impl_block_datum( | |||
663 | krate: CrateId, | 697 | krate: CrateId, |
664 | chalk_id: ImplId, | 698 | chalk_id: ImplId, |
665 | impl_id: hir_def::ImplId, | 699 | impl_id: hir_def::ImplId, |
666 | ) -> Option<Arc<ImplDatum>> { | 700 | ) -> Arc<ImplDatum> { |
667 | let trait_ref = db.impl_trait(impl_id)?; | 701 | let trait_ref = db |
702 | .impl_trait(impl_id) | ||
703 | // ImplIds for impls where the trait ref can't be resolved should never reach Chalk | ||
704 | .expect("invalid impl passed to Chalk"); | ||
668 | let impl_data = db.impl_data(impl_id); | 705 | let impl_data = db.impl_data(impl_id); |
669 | 706 | ||
670 | let generic_params = generics(db, impl_id.into()); | 707 | let generic_params = generics(db, impl_id.into()); |
@@ -716,21 +753,6 @@ fn impl_block_datum( | |||
716 | polarity, | 753 | polarity, |
717 | associated_ty_value_ids, | 754 | associated_ty_value_ids, |
718 | }; | 755 | }; |
719 | Some(Arc::new(impl_datum)) | ||
720 | } | ||
721 | |||
722 | fn invalid_impl_datum() -> Arc<ImplDatum> { | ||
723 | let trait_ref = chalk_ir::TraitRef { | ||
724 | trait_id: UNKNOWN_TRAIT, | ||
725 | parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], | ||
726 | }; | ||
727 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
728 | let impl_datum = ImplDatum { | ||
729 | binders: make_binders(impl_datum_bound, 1), | ||
730 | impl_type: chalk_rust_ir::ImplType::External, | ||
731 | polarity: chalk_rust_ir::Polarity::Positive, | ||
732 | associated_ty_value_ids: Vec::new(), | ||
733 | }; | ||
734 | Arc::new(impl_datum) | 756 | Arc::new(impl_datum) |
735 | } | 757 | } |
736 | 758 | ||
@@ -786,25 +808,25 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId { | |||
786 | 808 | ||
787 | impl From<StructId> for crate::TypeCtorId { | 809 | impl From<StructId> for crate::TypeCtorId { |
788 | fn from(struct_id: StructId) -> Self { | 810 | fn from(struct_id: StructId) -> Self { |
789 | id_from_chalk(struct_id.0) | 811 | InternKey::from_intern_id(struct_id.0) |
790 | } | 812 | } |
791 | } | 813 | } |
792 | 814 | ||
793 | impl From<crate::TypeCtorId> for StructId { | 815 | impl From<crate::TypeCtorId> for StructId { |
794 | fn from(type_ctor_id: crate::TypeCtorId) -> Self { | 816 | fn from(type_ctor_id: crate::TypeCtorId) -> Self { |
795 | chalk_ir::StructId(id_to_chalk(type_ctor_id)) | 817 | chalk_ir::StructId(type_ctor_id.as_intern_id()) |
796 | } | 818 | } |
797 | } | 819 | } |
798 | 820 | ||
799 | impl From<ImplId> for crate::traits::GlobalImplId { | 821 | impl From<ImplId> for crate::traits::GlobalImplId { |
800 | fn from(impl_id: ImplId) -> Self { | 822 | fn from(impl_id: ImplId) -> Self { |
801 | id_from_chalk(impl_id.0) | 823 | InternKey::from_intern_id(impl_id.0) |
802 | } | 824 | } |
803 | } | 825 | } |
804 | 826 | ||
805 | impl From<crate::traits::GlobalImplId> for ImplId { | 827 | impl From<crate::traits::GlobalImplId> for ImplId { |
806 | fn from(impl_id: crate::traits::GlobalImplId) -> Self { | 828 | fn from(impl_id: crate::traits::GlobalImplId) -> Self { |
807 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 829 | chalk_ir::ImplId(impl_id.as_intern_id()) |
808 | } | 830 | } |
809 | } | 831 | } |
810 | 832 | ||