aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/traits/chalk.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-04-18 12:36:35 +0100
committerFlorian Diebold <[email protected]>2020-04-20 18:16:01 +0100
commit0be68a482581861f4218e0a759e2da71ee19fce6 (patch)
treeef72ed32a71a9473f4c65c6f78e978473ced6075 /crates/ra_hir_ty/src/traits/chalk.rs
parent2e0b7b0159ed922693db48f3f94ed95b1827494a (diff)
Update Chalk, and cache Chalk env elaboration through a query
This should fix some of the worst performance problems.
Diffstat (limited to 'crates/ra_hir_ty/src/traits/chalk.rs')
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs145
1 files changed, 123 insertions, 22 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index e00a82db2..1ccb7c3b4 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -4,8 +4,8 @@ use std::{fmt, sync::Arc};
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{ 6use chalk_ir::{
7 cast::Cast, fold::shift::Shift, Goal, GoalData, Parameter, PlaceholderIndex, TypeName, 7 cast::Cast, fold::shift::Shift, interner::HasInterner, Goal, GoalData, Parameter,
8 UniverseIndex, 8 PlaceholderIndex, TypeName, UniverseIndex,
9}; 9};
10 10
11use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; 11use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
@@ -33,8 +33,10 @@ impl chalk_ir::interner::Interner for Interner {
33 type InternedGoals = Vec<Goal<Self>>; 33 type InternedGoals = Vec<Goal<Self>>;
34 type InternedSubstitution = Vec<Parameter<Self>>; 34 type InternedSubstitution = Vec<Parameter<Self>>;
35 type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; 35 type InternedProgramClause = chalk_ir::ProgramClauseData<Self>;
36 type InternedProgramClauses = Vec<chalk_ir::ProgramClause<Self>>; 36 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
37 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; 37 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
38 type InternedParameterKinds = Vec<chalk_ir::ParameterKind<()>>;
39 type InternedCanonicalVarKinds = Vec<chalk_ir::ParameterKind<UniverseIndex>>;
38 type Identifier = TypeAliasId; 40 type Identifier = TypeAliasId;
39 type DefId = InternId; 41 type DefId = InternId;
40 42
@@ -60,6 +62,27 @@ impl chalk_ir::interner::Interner for Interner {
60 tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) 62 tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt)))
61 } 63 }
62 64
65 fn debug_projection_ty(
66 proj: &chalk_ir::ProjectionTy<Interner>,
67 fmt: &mut fmt::Formatter<'_>,
68 ) -> Option<fmt::Result> {
69 tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt)))
70 }
71
72 fn debug_opaque_ty(
73 opaque_ty: &chalk_ir::OpaqueTy<Interner>,
74 fmt: &mut fmt::Formatter<'_>,
75 ) -> Option<fmt::Result> {
76 tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt)))
77 }
78
79 fn debug_opaque_ty_id(
80 opaque_ty_id: chalk_ir::OpaqueTyId<Self>,
81 fmt: &mut fmt::Formatter<'_>,
82 ) -> Option<fmt::Result> {
83 tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt)))
84 }
85
63 fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 86 fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
64 tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) 87 tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt)))
65 } 88 }
@@ -202,15 +225,15 @@ impl chalk_ir::interner::Interner for Interner {
202 fn intern_program_clauses( 225 fn intern_program_clauses(
203 &self, 226 &self,
204 data: impl IntoIterator<Item = chalk_ir::ProgramClause<Self>>, 227 data: impl IntoIterator<Item = chalk_ir::ProgramClause<Self>>,
205 ) -> Vec<chalk_ir::ProgramClause<Self>> { 228 ) -> Arc<[chalk_ir::ProgramClause<Self>]> {
206 data.into_iter().collect() 229 data.into_iter().collect()
207 } 230 }
208 231
209 fn program_clauses_data<'a>( 232 fn program_clauses_data<'a>(
210 &self, 233 &self,
211 clauses: &'a Vec<chalk_ir::ProgramClause<Self>>, 234 clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>,
212 ) -> &'a [chalk_ir::ProgramClause<Self>] { 235 ) -> &'a [chalk_ir::ProgramClause<Self>] {
213 clauses 236 &clauses
214 } 237 }
215 238
216 fn intern_quantified_where_clauses( 239 fn intern_quantified_where_clauses(
@@ -226,6 +249,34 @@ impl chalk_ir::interner::Interner for Interner {
226 ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { 249 ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] {
227 clauses 250 clauses
228 } 251 }
252
253 fn intern_parameter_kinds(
254 &self,
255 data: impl IntoIterator<Item = chalk_ir::ParameterKind<()>>,
256 ) -> Self::InternedParameterKinds {
257 data.into_iter().collect()
258 }
259
260 fn parameter_kinds_data<'a>(
261 &self,
262 parameter_kinds: &'a Self::InternedParameterKinds,
263 ) -> &'a [chalk_ir::ParameterKind<()>] {
264 &parameter_kinds
265 }
266
267 fn intern_canonical_var_kinds(
268 &self,
269 data: impl IntoIterator<Item = chalk_ir::ParameterKind<UniverseIndex>>,
270 ) -> Self::InternedCanonicalVarKinds {
271 data.into_iter().collect()
272 }
273
274 fn canonical_var_kinds_data<'a>(
275 &self,
276 canonical_var_kinds: &'a Self::InternedCanonicalVarKinds,
277 ) -> &'a [chalk_ir::ParameterKind<UniverseIndex>] {
278 &canonical_var_kinds
279 }
229} 280}
230 281
231impl chalk_ir::interner::HasInterner for Interner { 282impl chalk_ir::interner::HasInterner for Interner {
@@ -268,9 +319,12 @@ impl ToChalk for Ty {
268 Ty::Projection(proj_ty) => { 319 Ty::Projection(proj_ty) => {
269 let associated_ty_id = proj_ty.associated_ty.to_chalk(db); 320 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
270 let substitution = proj_ty.parameters.to_chalk(db); 321 let substitution = proj_ty.parameters.to_chalk(db);
271 chalk_ir::AliasTy { associated_ty_id, substitution } 322 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
272 .cast(&Interner) 323 associated_ty_id,
273 .intern(&Interner) 324 substitution,
325 })
326 .cast(&Interner)
327 .intern(&Interner)
274 } 328 }
275 Ty::Placeholder(id) => { 329 Ty::Placeholder(id) => {
276 let interned_id = db.intern_type_param_id(id); 330 let interned_id = db.intern_type_param_id(id);
@@ -314,16 +368,17 @@ impl ToChalk for Ty {
314 ); 368 );
315 Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) 369 Ty::Placeholder(db.lookup_intern_type_param_id(interned_id))
316 } 370 }
317 chalk_ir::TyData::Alias(proj) => { 371 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => {
318 let associated_ty = from_chalk(db, proj.associated_ty_id); 372 let associated_ty = from_chalk(db, proj.associated_ty_id);
319 let parameters = from_chalk(db, proj.substitution); 373 let parameters = from_chalk(db, proj.substitution);
320 Ty::Projection(ProjectionTy { associated_ty, parameters }) 374 Ty::Projection(ProjectionTy { associated_ty, parameters })
321 } 375 }
376 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(),
322 chalk_ir::TyData::Function(_) => unimplemented!(), 377 chalk_ir::TyData::Function(_) => unimplemented!(),
323 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), 378 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx),
324 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, 379 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
325 chalk_ir::TyData::Dyn(where_clauses) => { 380 chalk_ir::TyData::Dyn(where_clauses) => {
326 assert_eq!(where_clauses.bounds.binders.len(), 1); 381 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
327 let predicates = where_clauses 382 let predicates = where_clauses
328 .bounds 383 .bounds
329 .skip_binders() 384 .skip_binders()
@@ -404,6 +459,7 @@ impl ToChalk for TypeCtor {
404 match type_name { 459 match type_name {
405 TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), 460 TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()),
406 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), 461 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
462 TypeName::OpaqueType(_) => unreachable!(),
407 TypeName::Error => { 463 TypeName::Error => {
408 // this should not be reached, since we don't represent TypeName::Error with TypeCtor 464 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
409 unreachable!() 465 unreachable!()
@@ -460,7 +516,8 @@ impl ToChalk for GenericPredicate {
460 } 516 }
461 GenericPredicate::Projection(projection_pred) => { 517 GenericPredicate::Projection(projection_pred) => {
462 let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); 518 let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner);
463 let alias = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); 519 let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner);
520 let alias = chalk_ir::AliasTy::Projection(projection);
464 make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) 521 make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
465 } 522 }
466 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), 523 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
@@ -481,7 +538,13 @@ impl ToChalk for GenericPredicate {
481 GenericPredicate::Implemented(from_chalk(db, tr)) 538 GenericPredicate::Implemented(from_chalk(db, tr))
482 } 539 }
483 chalk_ir::WhereClause::AliasEq(projection_eq) => { 540 chalk_ir::WhereClause::AliasEq(projection_eq) => {
484 let projection_ty = from_chalk(db, projection_eq.alias); 541 let projection_ty = from_chalk(
542 db,
543 match projection_eq.alias {
544 chalk_ir::AliasTy::Projection(p) => p,
545 _ => unimplemented!(),
546 },
547 );
485 let ty = from_chalk(db, projection_eq.ty); 548 let ty = from_chalk(db, projection_eq.ty);
486 GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) 549 GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty })
487 } 550 }
@@ -490,10 +553,10 @@ impl ToChalk for GenericPredicate {
490} 553}
491 554
492impl ToChalk for ProjectionTy { 555impl ToChalk for ProjectionTy {
493 type Chalk = chalk_ir::AliasTy<Interner>; 556 type Chalk = chalk_ir::ProjectionTy<Interner>;
494 557
495 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasTy<Interner> { 558 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> {
496 chalk_ir::AliasTy { 559 chalk_ir::ProjectionTy {
497 associated_ty_id: self.associated_ty.to_chalk(db), 560 associated_ty_id: self.associated_ty.to_chalk(db),
498 substitution: self.parameters.to_chalk(db), 561 substitution: self.parameters.to_chalk(db),
499 } 562 }
@@ -501,7 +564,7 @@ impl ToChalk for ProjectionTy {
501 564
502 fn from_chalk( 565 fn from_chalk(
503 db: &dyn HirDatabase, 566 db: &dyn HirDatabase,
504 projection_ty: chalk_ir::AliasTy<Interner>, 567 projection_ty: chalk_ir::ProjectionTy<Interner>,
505 ) -> ProjectionTy { 568 ) -> ProjectionTy {
506 ProjectionTy { 569 ProjectionTy {
507 associated_ty: from_chalk(db, projection_ty.associated_ty_id), 570 associated_ty: from_chalk(db, projection_ty.associated_ty_id),
@@ -514,7 +577,10 @@ impl ToChalk for super::ProjectionPredicate {
514 type Chalk = chalk_ir::AliasEq<Interner>; 577 type Chalk = chalk_ir::AliasEq<Interner>;
515 578
516 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { 579 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
517 chalk_ir::AliasEq { alias: self.projection_ty.to_chalk(db), ty: self.ty.to_chalk(db) } 580 chalk_ir::AliasEq {
581 alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)),
582 ty: self.ty.to_chalk(db),
583 }
518 } 584 }
519 585
520 fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { 586 fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self {
@@ -540,17 +606,24 @@ impl ToChalk for Obligation {
540impl<T> ToChalk for Canonical<T> 606impl<T> ToChalk for Canonical<T>
541where 607where
542 T: ToChalk, 608 T: ToChalk,
609 T::Chalk: HasInterner<Interner = Interner>,
543{ 610{
544 type Chalk = chalk_ir::Canonical<T::Chalk>; 611 type Chalk = chalk_ir::Canonical<T::Chalk>;
545 612
546 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { 613 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
547 let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); 614 let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT);
548 let value = self.value.to_chalk(db); 615 let value = self.value.to_chalk(db);
549 chalk_ir::Canonical { value, binders: vec![parameter; self.num_vars] } 616 chalk_ir::Canonical {
617 value,
618 binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]),
619 }
550 } 620 }
551 621
552 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 622 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
553 Canonical { num_vars: canonical.binders.len(), value: from_chalk(db, canonical.value) } 623 Canonical {
624 num_vars: canonical.binders.len(&Interner),
625 value: from_chalk(db, canonical.value),
626 }
554 } 627 }
555} 628}
556 629
@@ -649,9 +722,15 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData {
649 } 722 }
650} 723}
651 724
652fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { 725fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
726where
727 T: HasInterner<Interner = Interner>,
728{
653 chalk_ir::Binders::new( 729 chalk_ir::Binders::new(
654 std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars).collect(), 730 chalk_ir::ParameterKinds::from(
731 &Interner,
732 std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars),
733 ),
655 value, 734 value,
656 ) 735 )
657} 736}
@@ -799,6 +878,28 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
799 // FIXME tell Chalk about well-known traits (here and in trait_datum) 878 // FIXME tell Chalk about well-known traits (here and in trait_datum)
800 None 879 None
801 } 880 }
881
882 fn program_clauses_for_env(
883 &self,
884 environment: &chalk_ir::Environment<Interner>,
885 ) -> chalk_ir::ProgramClauses<Interner> {
886 self.db.program_clauses_for_chalk_env(self.krate, environment.clone())
887 }
888
889 fn opaque_ty_data(
890 &self,
891 _id: chalk_ir::OpaqueTyId<Interner>,
892 ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> {
893 unimplemented!()
894 }
895}
896
897pub(crate) fn program_clauses_for_chalk_env_query(
898 db: &dyn HirDatabase,
899 krate: CrateId,
900 environment: chalk_ir::Environment<Interner>,
901) -> chalk_ir::ProgramClauses<Interner> {
902 chalk_solve::program_clauses_for_env(&ChalkContext { db, krate }, &environment)
802} 903}
803 904
804pub(crate) fn associated_ty_data_query( 905pub(crate) fn associated_ty_data_query(