diff options
Diffstat (limited to 'crates/ra_hir/src/ty/traits/chalk.rs')
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 319 |
1 files changed, 199 insertions, 120 deletions
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 68304b950..9bf93981a 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -7,22 +7,19 @@ use chalk_ir::{ | |||
7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, | 7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, |
8 | TypeKindId, TypeName, UniverseIndex, | 8 | TypeKindId, TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_expand::name; | 12 | use hir_expand::name; |
13 | 13 | ||
14 | use ra_db::salsa::{InternId, InternKey}; | 14 | use ra_db::salsa::{InternId, InternKey}; |
15 | 15 | ||
16 | use super::{Canonical, ChalkContext, Impl, Obligation}; | 16 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
17 | use crate::{ | 17 | use crate::{ |
18 | db::HirDatabase, | 18 | db::HirDatabase, |
19 | generics::{GenericDef, HasGenericParams}, | 19 | generics::{GenericDef, HasGenericParams}, |
20 | ty::display::HirDisplay, | 20 | ty::display::HirDisplay, |
21 | ty::{ | 21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, |
22 | ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 22 | Crate, HasBody, ImplBlock, Trait, TypeAlias, |
23 | TypeWalk, | ||
24 | }, | ||
25 | AssocItem, Crate, HasBody, ImplBlock, Trait, TypeAlias, | ||
26 | }; | 23 | }; |
27 | 24 | ||
28 | /// This represents a trait whose name we could not resolve. | 25 | /// This represents a trait whose name we could not resolve. |
@@ -59,29 +56,36 @@ impl ToChalk for Ty { | |||
59 | } | 56 | } |
60 | }; | 57 | }; |
61 | let parameters = apply_ty.parameters.to_chalk(db); | 58 | let parameters = apply_ty.parameters.to_chalk(db); |
62 | chalk_ir::ApplicationTy { name, parameters }.cast() | 59 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
63 | } | 60 | } |
64 | Ty::Projection(proj_ty) => { | 61 | Ty::Projection(proj_ty) => { |
65 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | 62 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); |
66 | let parameters = proj_ty.parameters.to_chalk(db); | 63 | let parameters = proj_ty.parameters.to_chalk(db); |
67 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() | 64 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() |
68 | } | 65 | } |
69 | Ty::Param { idx, .. } => { | 66 | Ty::Param { idx, .. } => { |
70 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() | 67 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() |
71 | } | 68 | } |
72 | Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize), | 69 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), |
73 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 70 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
74 | // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed | 71 | Ty::Dyn(predicates) => { |
75 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { | 72 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); |
73 | chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() | ||
74 | } | ||
75 | Ty::Opaque(predicates) => { | ||
76 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | ||
77 | chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() | ||
78 | } | ||
79 | Ty::Unknown => { | ||
76 | let parameters = Vec::new(); | 80 | let parameters = Vec::new(); |
77 | let name = TypeName::Error; | 81 | let name = TypeName::Error; |
78 | chalk_ir::ApplicationTy { name, parameters }.cast() | 82 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
79 | } | 83 | } |
80 | } | 84 | } |
81 | } | 85 | } |
82 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { | 86 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { |
83 | match chalk { | 87 | match chalk.data().clone() { |
84 | chalk_ir::Ty::Apply(apply_ty) => { | 88 | chalk_ir::TyData::Apply(apply_ty) => { |
85 | // FIXME this is kind of hacky due to the fact that | 89 | // FIXME this is kind of hacky due to the fact that |
86 | // TypeName::Placeholder is a Ty::Param on our side | 90 | // TypeName::Placeholder is a Ty::Param on our side |
87 | match apply_ty.name { | 91 | match apply_ty.name { |
@@ -104,21 +108,21 @@ impl ToChalk for Ty { | |||
104 | } | 108 | } |
105 | } | 109 | } |
106 | } | 110 | } |
107 | chalk_ir::Ty::Projection(proj) => { | 111 | chalk_ir::TyData::Projection(proj) => { |
108 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 112 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
109 | let parameters = from_chalk(db, proj.parameters); | 113 | let parameters = from_chalk(db, proj.parameters); |
110 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 114 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
111 | } | 115 | } |
112 | chalk_ir::Ty::ForAll(_) => unimplemented!(), | 116 | chalk_ir::TyData::ForAll(_) => unimplemented!(), |
113 | chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), | 117 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), |
114 | chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, | 118 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
115 | chalk_ir::Ty::Dyn(where_clauses) => { | 119 | chalk_ir::TyData::Dyn(where_clauses) => { |
116 | assert_eq!(where_clauses.binders.len(), 1); | 120 | assert_eq!(where_clauses.binders.len(), 1); |
117 | let predicates = | 121 | let predicates = |
118 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 122 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
119 | Ty::Dyn(predicates) | 123 | Ty::Dyn(predicates) |
120 | } | 124 | } |
121 | chalk_ir::Ty::Opaque(where_clauses) => { | 125 | chalk_ir::TyData::Opaque(where_clauses) => { |
122 | assert_eq!(where_clauses.binders.len(), 1); | 126 | assert_eq!(where_clauses.binders.len(), 1); |
123 | let predicates = | 127 | let predicates = |
124 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 128 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
@@ -211,6 +215,21 @@ impl ToChalk for TypeAlias { | |||
211 | } | 215 | } |
212 | } | 216 | } |
213 | 217 | ||
218 | impl ToChalk for AssocTyValue { | ||
219 | type Chalk = chalk_rust_ir::AssociatedTyValueId; | ||
220 | |||
221 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { | ||
222 | db.intern_assoc_ty_value(self).into() | ||
223 | } | ||
224 | |||
225 | fn from_chalk( | ||
226 | db: &impl HirDatabase, | ||
227 | assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, | ||
228 | ) -> AssocTyValue { | ||
229 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
230 | } | ||
231 | } | ||
232 | |||
214 | impl ToChalk for GenericPredicate { | 233 | impl ToChalk for GenericPredicate { |
215 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; | 234 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; |
216 | 235 | ||
@@ -399,20 +418,20 @@ fn convert_where_clauses( | |||
399 | result | 418 | result |
400 | } | 419 | } |
401 | 420 | ||
402 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | 421 | impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> |
403 | where | 422 | where |
404 | DB: HirDatabase, | 423 | DB: HirDatabase, |
405 | { | 424 | { |
406 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> { | 425 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { |
407 | self.db.associated_ty_data(id) | 426 | self.db.associated_ty_data(id) |
408 | } | 427 | } |
409 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { | 428 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { |
410 | self.db.trait_datum(self.krate, trait_id) | 429 | self.db.trait_datum(self.krate, trait_id) |
411 | } | 430 | } |
412 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { | 431 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { |
413 | self.db.struct_datum(self.krate, struct_id) | 432 | self.db.struct_datum(self.krate, struct_id) |
414 | } | 433 | } |
415 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { | 434 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum<ChalkIr>> { |
416 | self.db.impl_datum(self.krate, impl_id) | 435 | self.db.impl_datum(self.krate, impl_id) |
417 | } | 436 | } |
418 | fn impls_for_trait( | 437 | fn impls_for_trait( |
@@ -462,13 +481,11 @@ where | |||
462 | fn type_name(&self, _id: TypeKindId) -> Identifier { | 481 | fn type_name(&self, _id: TypeKindId) -> Identifier { |
463 | unimplemented!() | 482 | unimplemented!() |
464 | } | 483 | } |
465 | fn split_projection<'p>( | 484 | fn associated_ty_value( |
466 | &self, | 485 | &self, |
467 | projection: &'p chalk_ir::ProjectionTy<ChalkIr>, | 486 | id: chalk_rust_ir::AssociatedTyValueId, |
468 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) { | 487 | ) -> Arc<AssociatedTyValue<ChalkIr>> { |
469 | debug!("split_projection {:?}", projection); | 488 | self.db.associated_ty_value(self.krate, id) |
470 | // we don't support GATs, so I think this should always be correct currently | ||
471 | (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) | ||
472 | } | 489 | } |
473 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { | 490 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { |
474 | vec![] | 491 | vec![] |
@@ -485,7 +502,7 @@ where | |||
485 | pub(crate) fn associated_ty_data_query( | 502 | pub(crate) fn associated_ty_data_query( |
486 | db: &impl HirDatabase, | 503 | db: &impl HirDatabase, |
487 | id: TypeId, | 504 | id: TypeId, |
488 | ) -> Arc<AssociatedTyDatum> { | 505 | ) -> Arc<AssociatedTyDatum<ChalkIr>> { |
489 | debug!("associated_ty_data {:?}", id); | 506 | debug!("associated_ty_data {:?}", id); |
490 | let type_alias: TypeAlias = from_chalk(db, id); | 507 | let type_alias: TypeAlias = from_chalk(db, id); |
491 | let trait_ = match type_alias.container(db) { | 508 | let trait_ = match type_alias.container(db) { |
@@ -493,19 +510,16 @@ pub(crate) fn associated_ty_data_query( | |||
493 | _ => panic!("associated type not in trait"), | 510 | _ => panic!("associated type not in trait"), |
494 | }; | 511 | }; |
495 | let generic_params = type_alias.generic_params(db); | 512 | let generic_params = type_alias.generic_params(db); |
496 | let parameter_kinds = generic_params | 513 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { |
497 | .params_including_parent() | 514 | // FIXME add bounds and where clauses |
498 | .into_iter() | 515 | bounds: vec![], |
499 | .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string()))) | 516 | where_clauses: vec![], |
500 | .collect(); | 517 | }; |
501 | let datum = AssociatedTyDatum { | 518 | let datum = AssociatedTyDatum { |
502 | trait_id: trait_.to_chalk(db), | 519 | trait_id: trait_.to_chalk(db), |
503 | id, | 520 | id, |
504 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), | 521 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), |
505 | parameter_kinds, | 522 | binders: make_binders(bound_data, generic_params.count_params_including_parent()), |
506 | // FIXME add bounds and where clauses | ||
507 | bounds: vec![], | ||
508 | where_clauses: vec![], | ||
509 | }; | 523 | }; |
510 | Arc::new(datum) | 524 | Arc::new(datum) |
511 | } | 525 | } |
@@ -514,17 +528,10 @@ pub(crate) fn trait_datum_query( | |||
514 | db: &impl HirDatabase, | 528 | db: &impl HirDatabase, |
515 | krate: Crate, | 529 | krate: Crate, |
516 | trait_id: chalk_ir::TraitId, | 530 | trait_id: chalk_ir::TraitId, |
517 | ) -> Arc<TraitDatum> { | 531 | ) -> Arc<TraitDatum<ChalkIr>> { |
518 | debug!("trait_datum {:?}", trait_id); | 532 | debug!("trait_datum {:?}", trait_id); |
519 | if trait_id == UNKNOWN_TRAIT { | 533 | if trait_id == UNKNOWN_TRAIT { |
520 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { | 534 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; |
521 | trait_ref: chalk_ir::TraitRef { | ||
522 | trait_id: UNKNOWN_TRAIT, | ||
523 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | ||
524 | }, | ||
525 | associated_ty_ids: Vec::new(), | ||
526 | where_clauses: Vec::new(), | ||
527 | }; | ||
528 | 535 | ||
529 | let flags = chalk_rust_ir::TraitFlags { | 536 | let flags = chalk_rust_ir::TraitFlags { |
530 | auto: false, | 537 | auto: false, |
@@ -532,18 +539,24 @@ pub(crate) fn trait_datum_query( | |||
532 | upstream: true, | 539 | upstream: true, |
533 | fundamental: false, | 540 | fundamental: false, |
534 | non_enumerable: true, | 541 | non_enumerable: true, |
542 | coinductive: false, | ||
535 | }; | 543 | }; |
536 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1), flags }); | 544 | return Arc::new(TraitDatum { |
545 | id: trait_id, | ||
546 | binders: make_binders(trait_datum_bound, 1), | ||
547 | flags, | ||
548 | associated_ty_ids: vec![], | ||
549 | }); | ||
537 | } | 550 | } |
538 | let trait_: Trait = from_chalk(db, trait_id); | 551 | let trait_: Trait = from_chalk(db, trait_id); |
539 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); | 552 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); |
540 | let generic_params = trait_.generic_params(db); | 553 | let generic_params = trait_.generic_params(db); |
541 | let bound_vars = Substs::bound_vars(&generic_params); | 554 | let bound_vars = Substs::bound_vars(&generic_params); |
542 | let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db); | ||
543 | let flags = chalk_rust_ir::TraitFlags { | 555 | let flags = chalk_rust_ir::TraitFlags { |
544 | auto: trait_.is_auto(db), | 556 | auto: trait_.is_auto(db), |
545 | upstream: trait_.module(db).krate() != krate, | 557 | upstream: trait_.module(db).krate() != krate, |
546 | non_enumerable: true, | 558 | non_enumerable: true, |
559 | coinductive: false, // only relevant for Chalk testing | ||
547 | // FIXME set these flags correctly | 560 | // FIXME set these flags correctly |
548 | marker: false, | 561 | marker: false, |
549 | fundamental: false, | 562 | fundamental: false, |
@@ -558,10 +571,13 @@ pub(crate) fn trait_datum_query( | |||
558 | }) | 571 | }) |
559 | .map(|type_alias| type_alias.to_chalk(db)) | 572 | .map(|type_alias| type_alias.to_chalk(db)) |
560 | .collect(); | 573 | .collect(); |
561 | let trait_datum_bound = | 574 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; |
562 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, associated_ty_ids }; | 575 | let trait_datum = TraitDatum { |
563 | let trait_datum = | 576 | id: trait_id, |
564 | TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()), flags }; | 577 | binders: make_binders(trait_datum_bound, bound_vars.len()), |
578 | flags, | ||
579 | associated_ty_ids, | ||
580 | }; | ||
565 | Arc::new(trait_datum) | 581 | Arc::new(trait_datum) |
566 | } | 582 | } |
567 | 583 | ||
@@ -569,7 +585,7 @@ pub(crate) fn struct_datum_query( | |||
569 | db: &impl HirDatabase, | 585 | db: &impl HirDatabase, |
570 | krate: Crate, | 586 | krate: Crate, |
571 | struct_id: chalk_ir::StructId, | 587 | struct_id: chalk_ir::StructId, |
572 | ) -> Arc<StructDatum> { | 588 | ) -> Arc<StructDatum<ChalkIr>> { |
573 | debug!("struct_datum {:?}", struct_id); | 589 | debug!("struct_datum {:?}", struct_id); |
574 | let type_ctor: TypeCtor = from_chalk(db, struct_id); | 590 | let type_ctor: TypeCtor = from_chalk(db, struct_id); |
575 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 591 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
@@ -588,17 +604,12 @@ pub(crate) fn struct_datum_query( | |||
588 | // FIXME set fundamental flag correctly | 604 | // FIXME set fundamental flag correctly |
589 | fundamental: false, | 605 | fundamental: false, |
590 | }; | 606 | }; |
591 | let self_ty = chalk_ir::ApplicationTy { | ||
592 | name: TypeName::TypeKindId(type_ctor.to_chalk(db).into()), | ||
593 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), | ||
594 | }; | ||
595 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { | 607 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { |
596 | self_ty, | ||
597 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 608 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) |
598 | where_clauses, | 609 | where_clauses, |
599 | flags, | ||
600 | }; | 610 | }; |
601 | let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) }; | 611 | let struct_datum = |
612 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
602 | Arc::new(struct_datum) | 613 | Arc::new(struct_datum) |
603 | } | 614 | } |
604 | 615 | ||
@@ -606,16 +617,15 @@ pub(crate) fn impl_datum_query( | |||
606 | db: &impl HirDatabase, | 617 | db: &impl HirDatabase, |
607 | krate: Crate, | 618 | krate: Crate, |
608 | impl_id: ImplId, | 619 | impl_id: ImplId, |
609 | ) -> Arc<ImplDatum> { | 620 | ) -> Arc<ImplDatum<ChalkIr>> { |
610 | let _p = ra_prof::profile("impl_datum"); | 621 | let _p = ra_prof::profile("impl_datum"); |
611 | debug!("impl_datum {:?}", impl_id); | 622 | debug!("impl_datum {:?}", impl_id); |
612 | let impl_: Impl = from_chalk(db, impl_id); | 623 | let impl_: Impl = from_chalk(db, impl_id); |
613 | match impl_ { | 624 | match impl_ { |
614 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 625 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
615 | Impl::ClosureFnTraitImpl(data) => { | 626 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), |
616 | closure_fn_trait_impl_datum(db, krate, impl_id, data).unwrap_or_else(invalid_impl_datum) | ||
617 | } | ||
618 | } | 627 | } |
628 | .unwrap_or_else(invalid_impl_datum) | ||
619 | } | 629 | } |
620 | 630 | ||
621 | fn impl_block_datum( | 631 | fn impl_block_datum( |
@@ -623,13 +633,11 @@ fn impl_block_datum( | |||
623 | krate: Crate, | 633 | krate: Crate, |
624 | impl_id: ImplId, | 634 | impl_id: ImplId, |
625 | impl_block: ImplBlock, | 635 | impl_block: ImplBlock, |
626 | ) -> Arc<ImplDatum> { | 636 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
627 | let generic_params = impl_block.generic_params(db); | 637 | let generic_params = impl_block.generic_params(db); |
628 | let bound_vars = Substs::bound_vars(&generic_params); | 638 | let bound_vars = Substs::bound_vars(&generic_params); |
629 | let trait_ref = impl_block | 639 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); |
630 | .target_trait_ref(db) | 640 | let trait_ = trait_ref.trait_; |
631 | .expect("FIXME handle unresolved impl block trait ref") | ||
632 | .subst(&bound_vars); | ||
633 | let impl_type = if impl_block.krate(db) == krate { | 641 | let impl_type = if impl_block.krate(db) == krate { |
634 | chalk_rust_ir::ImplType::Local | 642 | chalk_rust_ir::ImplType::Local |
635 | } else { | 643 | } else { |
@@ -644,28 +652,7 @@ fn impl_block_datum( | |||
644 | trait_ref.display(db), | 652 | trait_ref.display(db), |
645 | where_clauses | 653 | where_clauses |
646 | ); | 654 | ); |
647 | let trait_ = trait_ref.trait_; | ||
648 | let trait_ref = trait_ref.to_chalk(db); | 655 | let trait_ref = trait_ref.to_chalk(db); |
649 | let associated_ty_values = impl_block | ||
650 | .items(db) | ||
651 | .into_iter() | ||
652 | .filter_map(|item| match item { | ||
653 | AssocItem::TypeAlias(t) => Some(t), | ||
654 | _ => None, | ||
655 | }) | ||
656 | .filter_map(|t| { | ||
657 | let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; | ||
658 | let ty = db.type_for_def(t.into(), Namespace::Types).subst(&bound_vars); | ||
659 | Some(chalk_rust_ir::AssociatedTyValue { | ||
660 | impl_id, | ||
661 | associated_ty_id: assoc_ty.to_chalk(db), | ||
662 | value: chalk_ir::Binders { | ||
663 | value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }, | ||
664 | binders: vec![], // we don't support GATs yet | ||
665 | }, | ||
666 | }) | ||
667 | }) | ||
668 | .collect(); | ||
669 | 656 | ||
670 | let polarity = if negative { | 657 | let polarity = if negative { |
671 | chalk_rust_ir::Polarity::Negative | 658 | chalk_rust_ir::Polarity::Negative |
@@ -673,31 +660,41 @@ fn impl_block_datum( | |||
673 | chalk_rust_ir::Polarity::Positive | 660 | chalk_rust_ir::Polarity::Positive |
674 | }; | 661 | }; |
675 | 662 | ||
676 | let impl_datum_bound = | 663 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; |
677 | chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses, associated_ty_values }; | 664 | let associated_ty_value_ids = impl_block |
665 | .items(db) | ||
666 | .into_iter() | ||
667 | .filter_map(|item| match item { | ||
668 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), | ||
669 | _ => None, | ||
670 | }) | ||
671 | .filter(|type_alias| { | ||
672 | // don't include associated types that don't exist in the trait | ||
673 | trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() | ||
674 | }) | ||
675 | .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) | ||
676 | .collect(); | ||
678 | debug!("impl_datum: {:?}", impl_datum_bound); | 677 | debug!("impl_datum: {:?}", impl_datum_bound); |
679 | let impl_datum = ImplDatum { | 678 | let impl_datum = ImplDatum { |
680 | binders: make_binders(impl_datum_bound, bound_vars.len()), | 679 | binders: make_binders(impl_datum_bound, bound_vars.len()), |
681 | impl_type, | 680 | impl_type, |
682 | polarity, | 681 | polarity, |
682 | associated_ty_value_ids, | ||
683 | }; | 683 | }; |
684 | Arc::new(impl_datum) | 684 | Some(Arc::new(impl_datum)) |
685 | } | 685 | } |
686 | 686 | ||
687 | fn invalid_impl_datum() -> Arc<ImplDatum> { | 687 | fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> { |
688 | let trait_ref = chalk_ir::TraitRef { | 688 | let trait_ref = chalk_ir::TraitRef { |
689 | trait_id: UNKNOWN_TRAIT, | 689 | trait_id: UNKNOWN_TRAIT, |
690 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | 690 | parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], |
691 | }; | ||
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | ||
693 | trait_ref, | ||
694 | where_clauses: Vec::new(), | ||
695 | associated_ty_values: Vec::new(), | ||
696 | }; | 691 | }; |
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
697 | let impl_datum = ImplDatum { | 693 | let impl_datum = ImplDatum { |
698 | binders: make_binders(impl_datum_bound, 1), | 694 | binders: make_binders(impl_datum_bound, 1), |
699 | impl_type: chalk_rust_ir::ImplType::External, | 695 | impl_type: chalk_rust_ir::ImplType::External, |
700 | polarity: chalk_rust_ir::Polarity::Positive, | 696 | polarity: chalk_rust_ir::Polarity::Positive, |
697 | associated_ty_value_ids: Vec::new(), | ||
701 | }; | 698 | }; |
702 | Arc::new(impl_datum) | 699 | Arc::new(impl_datum) |
703 | } | 700 | } |
@@ -705,15 +702,19 @@ fn invalid_impl_datum() -> Arc<ImplDatum> { | |||
705 | fn closure_fn_trait_impl_datum( | 702 | fn closure_fn_trait_impl_datum( |
706 | db: &impl HirDatabase, | 703 | db: &impl HirDatabase, |
707 | krate: Crate, | 704 | krate: Crate, |
708 | impl_id: ImplId, | ||
709 | data: super::ClosureFnTraitImplData, | 705 | data: super::ClosureFnTraitImplData, |
710 | ) -> Option<Arc<ImplDatum>> { | 706 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
711 | // for some closure |X, Y| -> Z: | 707 | // for some closure |X, Y| -> Z: |
712 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | 708 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } |
713 | 709 | ||
714 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
715 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait | 710 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait |
716 | 711 | ||
712 | // validate FnOnce trait, since we need it in the assoc ty value definition | ||
713 | // and don't want to return a valid value only to find out later that FnOnce | ||
714 | // is broken | ||
715 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
716 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | ||
717 | |||
717 | let num_args: u16 = match &data.def.body(db)[data.expr] { | 718 | let num_args: u16 = match &data.def.body(db)[data.expr] { |
718 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | 719 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, |
719 | _ => { | 720 | _ => { |
@@ -726,7 +727,6 @@ fn closure_fn_trait_impl_datum( | |||
726 | TypeCtor::Tuple { cardinality: num_args }, | 727 | TypeCtor::Tuple { cardinality: num_args }, |
727 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), | 728 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), |
728 | ); | 729 | ); |
729 | let output_ty = Ty::Bound(num_args.into()); | ||
730 | let sig_ty = Ty::apply( | 730 | let sig_ty = Ty::apply( |
731 | TypeCtor::FnPtr { num_args }, | 731 | TypeCtor::FnPtr { num_args }, |
732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), | 732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), |
@@ -739,32 +739,99 @@ fn closure_fn_trait_impl_datum( | |||
739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | 739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), |
740 | }; | 740 | }; |
741 | 741 | ||
742 | let output_ty_id = fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | 742 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); |
743 | |||
744 | let output_ty_value = chalk_rust_ir::AssociatedTyValue { | ||
745 | associated_ty_id: output_ty_id.to_chalk(db), | ||
746 | impl_id, | ||
747 | value: make_binders( | ||
748 | chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }, | ||
749 | 0, | ||
750 | ), | ||
751 | }; | ||
752 | 743 | ||
753 | let impl_type = chalk_rust_ir::ImplType::External; | 744 | let impl_type = chalk_rust_ir::ImplType::External; |
754 | 745 | ||
755 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 746 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
756 | trait_ref: trait_ref.to_chalk(db), | 747 | trait_ref: trait_ref.to_chalk(db), |
757 | where_clauses: Vec::new(), | 748 | where_clauses: Vec::new(), |
758 | associated_ty_values: vec![output_ty_value], | ||
759 | }; | 749 | }; |
760 | let impl_datum = ImplDatum { | 750 | let impl_datum = ImplDatum { |
761 | binders: make_binders(impl_datum_bound, num_args as usize + 1), | 751 | binders: make_binders(impl_datum_bound, num_args as usize + 1), |
762 | impl_type, | 752 | impl_type, |
763 | polarity: chalk_rust_ir::Polarity::Positive, | 753 | polarity: chalk_rust_ir::Polarity::Positive, |
754 | associated_ty_value_ids: vec![output_ty_id], | ||
764 | }; | 755 | }; |
765 | Some(Arc::new(impl_datum)) | 756 | Some(Arc::new(impl_datum)) |
766 | } | 757 | } |
767 | 758 | ||
759 | pub(crate) fn associated_ty_value_query( | ||
760 | db: &impl HirDatabase, | ||
761 | krate: Crate, | ||
762 | id: chalk_rust_ir::AssociatedTyValueId, | ||
763 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { | ||
764 | let data: AssocTyValue = from_chalk(db, id); | ||
765 | match data { | ||
766 | AssocTyValue::TypeAlias(type_alias) => { | ||
767 | type_alias_associated_ty_value(db, krate, type_alias) | ||
768 | } | ||
769 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | ||
770 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
775 | fn type_alias_associated_ty_value( | ||
776 | db: &impl HirDatabase, | ||
777 | _krate: Crate, | ||
778 | type_alias: TypeAlias, | ||
779 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
780 | let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl"); | ||
781 | let impl_id = Impl::ImplBlock(impl_block).to_chalk(db); | ||
782 | let trait_ = impl_block | ||
783 | .target_trait_ref(db) | ||
784 | .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved | ||
785 | .trait_; | ||
786 | let assoc_ty = trait_ | ||
787 | .associated_type_by_name(db, &type_alias.name(db)) | ||
788 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | ||
789 | let generic_params = impl_block.generic_params(db); | ||
790 | let bound_vars = Substs::bound_vars(&generic_params); | ||
791 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); | ||
792 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | ||
793 | let value = chalk_rust_ir::AssociatedTyValue { | ||
794 | impl_id, | ||
795 | associated_ty_id: assoc_ty.to_chalk(db), | ||
796 | value: make_binders(value_bound, bound_vars.len()), | ||
797 | }; | ||
798 | Arc::new(value) | ||
799 | } | ||
800 | |||
801 | fn closure_fn_trait_output_assoc_ty_value( | ||
802 | db: &impl HirDatabase, | ||
803 | krate: Crate, | ||
804 | data: super::ClosureFnTraitImplData, | ||
805 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
806 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | ||
807 | |||
808 | let num_args: u16 = match &data.def.body(db)[data.expr] { | ||
809 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | ||
810 | _ => { | ||
811 | log::warn!("closure for closure type {:?} not found", data); | ||
812 | 0 | ||
813 | } | ||
814 | }; | ||
815 | |||
816 | let output_ty = Ty::Bound(num_args.into()); | ||
817 | |||
818 | let fn_once_trait = | ||
819 | get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); | ||
820 | |||
821 | let output_ty_id = fn_once_trait | ||
822 | .associated_type_by_name(db, &name::OUTPUT_TYPE) | ||
823 | .expect("assoc ty value should not exist"); | ||
824 | |||
825 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; | ||
826 | |||
827 | let value = chalk_rust_ir::AssociatedTyValue { | ||
828 | associated_ty_id: output_ty_id.to_chalk(db), | ||
829 | impl_id, | ||
830 | value: make_binders(value_bound, num_args as usize + 1), | ||
831 | }; | ||
832 | Arc::new(value) | ||
833 | } | ||
834 | |||
768 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { |
769 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; | 836 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; |
770 | match target { | 837 | match target { |
@@ -803,3 +870,15 @@ impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { | |||
803 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 870 | chalk_ir::ImplId(id_to_chalk(impl_id)) |
804 | } | 871 | } |
805 | } | 872 | } |
873 | |||
874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { | ||
875 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { | ||
876 | id_from_chalk(id.0) | ||
877 | } | ||
878 | } | ||
879 | |||
880 | impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | ||
881 | fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { | ||
882 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) | ||
883 | } | ||
884 | } | ||