diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 286 |
2 files changed, 191 insertions, 108 deletions
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 4f1eab150..771525deb 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -8,7 +8,7 @@ use ra_prof::profile; | |||
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::FxHashSet; |
9 | 9 | ||
10 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 10 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
11 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait}; | 11 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait, TypeAlias}; |
12 | 12 | ||
13 | use self::chalk::{from_chalk, ToChalk}; | 13 | use self::chalk::{from_chalk, ToChalk}; |
14 | 14 | ||
@@ -300,3 +300,14 @@ pub enum Impl { | |||
300 | /// Closure types implement the Fn traits synthetically. | 300 | /// Closure types implement the Fn traits synthetically. |
301 | ClosureFnTraitImpl(ClosureFnTraitImplData), | 301 | ClosureFnTraitImpl(ClosureFnTraitImplData), |
302 | } | 302 | } |
303 | |||
304 | /// An associated type value. Usually this comes from a `type` declaration | ||
305 | /// inside an impl block, but for built-in impls we have to synthesize it. | ||
306 | /// (We only need this because Chalk wants a unique ID for each of these.) | ||
307 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
308 | pub enum AssocTyValue { | ||
309 | /// A normal assoc type value from an impl block. | ||
310 | TypeAlias(TypeAlias), | ||
311 | /// The output type of the Fn trait implementation. | ||
312 | ClosureFnTraitImplOutput(ClosureFnTraitImplData), | ||
313 | } | ||
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 68304b950..e39e8aaca 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,29 @@ 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 | // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed |
75 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { | 72 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { |
76 | let parameters = Vec::new(); | 73 | let parameters = Vec::new(); |
77 | let name = TypeName::Error; | 74 | let name = TypeName::Error; |
78 | chalk_ir::ApplicationTy { name, parameters }.cast() | 75 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
79 | } | 76 | } |
80 | } | 77 | } |
81 | } | 78 | } |
82 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { | 79 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { |
83 | match chalk { | 80 | match chalk.data().clone() { |
84 | chalk_ir::Ty::Apply(apply_ty) => { | 81 | chalk_ir::TyData::Apply(apply_ty) => { |
85 | // FIXME this is kind of hacky due to the fact that | 82 | // FIXME this is kind of hacky due to the fact that |
86 | // TypeName::Placeholder is a Ty::Param on our side | 83 | // TypeName::Placeholder is a Ty::Param on our side |
87 | match apply_ty.name { | 84 | match apply_ty.name { |
@@ -104,21 +101,21 @@ impl ToChalk for Ty { | |||
104 | } | 101 | } |
105 | } | 102 | } |
106 | } | 103 | } |
107 | chalk_ir::Ty::Projection(proj) => { | 104 | chalk_ir::TyData::Projection(proj) => { |
108 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 105 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
109 | let parameters = from_chalk(db, proj.parameters); | 106 | let parameters = from_chalk(db, proj.parameters); |
110 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 107 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
111 | } | 108 | } |
112 | chalk_ir::Ty::ForAll(_) => unimplemented!(), | 109 | chalk_ir::TyData::ForAll(_) => unimplemented!(), |
113 | chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), | 110 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), |
114 | chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, | 111 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
115 | chalk_ir::Ty::Dyn(where_clauses) => { | 112 | chalk_ir::TyData::Dyn(where_clauses) => { |
116 | assert_eq!(where_clauses.binders.len(), 1); | 113 | assert_eq!(where_clauses.binders.len(), 1); |
117 | let predicates = | 114 | let predicates = |
118 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 115 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
119 | Ty::Dyn(predicates) | 116 | Ty::Dyn(predicates) |
120 | } | 117 | } |
121 | chalk_ir::Ty::Opaque(where_clauses) => { | 118 | chalk_ir::TyData::Opaque(where_clauses) => { |
122 | assert_eq!(where_clauses.binders.len(), 1); | 119 | assert_eq!(where_clauses.binders.len(), 1); |
123 | let predicates = | 120 | let predicates = |
124 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 121 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
@@ -211,6 +208,21 @@ impl ToChalk for TypeAlias { | |||
211 | } | 208 | } |
212 | } | 209 | } |
213 | 210 | ||
211 | impl ToChalk for AssocTyValue { | ||
212 | type Chalk = chalk_rust_ir::AssociatedTyValueId; | ||
213 | |||
214 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { | ||
215 | db.intern_assoc_ty_value(self).into() | ||
216 | } | ||
217 | |||
218 | fn from_chalk( | ||
219 | db: &impl HirDatabase, | ||
220 | assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, | ||
221 | ) -> AssocTyValue { | ||
222 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
223 | } | ||
224 | } | ||
225 | |||
214 | impl ToChalk for GenericPredicate { | 226 | impl ToChalk for GenericPredicate { |
215 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; | 227 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; |
216 | 228 | ||
@@ -462,13 +474,11 @@ where | |||
462 | fn type_name(&self, _id: TypeKindId) -> Identifier { | 474 | fn type_name(&self, _id: TypeKindId) -> Identifier { |
463 | unimplemented!() | 475 | unimplemented!() |
464 | } | 476 | } |
465 | fn split_projection<'p>( | 477 | fn associated_ty_value( |
466 | &self, | 478 | &self, |
467 | projection: &'p chalk_ir::ProjectionTy<ChalkIr>, | 479 | id: chalk_rust_ir::AssociatedTyValueId, |
468 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) { | 480 | ) -> Arc<AssociatedTyValue> { |
469 | debug!("split_projection {:?}", projection); | 481 | 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 | } | 482 | } |
473 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { | 483 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { |
474 | vec![] | 484 | vec![] |
@@ -493,19 +503,16 @@ pub(crate) fn associated_ty_data_query( | |||
493 | _ => panic!("associated type not in trait"), | 503 | _ => panic!("associated type not in trait"), |
494 | }; | 504 | }; |
495 | let generic_params = type_alias.generic_params(db); | 505 | let generic_params = type_alias.generic_params(db); |
496 | let parameter_kinds = generic_params | 506 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { |
497 | .params_including_parent() | 507 | // FIXME add bounds and where clauses |
498 | .into_iter() | 508 | bounds: vec![], |
499 | .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string()))) | 509 | where_clauses: vec![], |
500 | .collect(); | 510 | }; |
501 | let datum = AssociatedTyDatum { | 511 | let datum = AssociatedTyDatum { |
502 | trait_id: trait_.to_chalk(db), | 512 | trait_id: trait_.to_chalk(db), |
503 | id, | 513 | id, |
504 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), | 514 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), |
505 | parameter_kinds, | 515 | 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 | }; | 516 | }; |
510 | Arc::new(datum) | 517 | Arc::new(datum) |
511 | } | 518 | } |
@@ -517,14 +524,7 @@ pub(crate) fn trait_datum_query( | |||
517 | ) -> Arc<TraitDatum> { | 524 | ) -> Arc<TraitDatum> { |
518 | debug!("trait_datum {:?}", trait_id); | 525 | debug!("trait_datum {:?}", trait_id); |
519 | if trait_id == UNKNOWN_TRAIT { | 526 | if trait_id == UNKNOWN_TRAIT { |
520 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { | 527 | 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 | 528 | ||
529 | let flags = chalk_rust_ir::TraitFlags { | 529 | let flags = chalk_rust_ir::TraitFlags { |
530 | auto: false, | 530 | auto: false, |
@@ -532,18 +532,24 @@ pub(crate) fn trait_datum_query( | |||
532 | upstream: true, | 532 | upstream: true, |
533 | fundamental: false, | 533 | fundamental: false, |
534 | non_enumerable: true, | 534 | non_enumerable: true, |
535 | coinductive: false, | ||
535 | }; | 536 | }; |
536 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1), flags }); | 537 | return Arc::new(TraitDatum { |
538 | id: trait_id, | ||
539 | binders: make_binders(trait_datum_bound, 1), | ||
540 | flags, | ||
541 | associated_ty_ids: vec![], | ||
542 | }); | ||
537 | } | 543 | } |
538 | let trait_: Trait = from_chalk(db, trait_id); | 544 | let trait_: Trait = from_chalk(db, trait_id); |
539 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); | 545 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); |
540 | let generic_params = trait_.generic_params(db); | 546 | let generic_params = trait_.generic_params(db); |
541 | let bound_vars = Substs::bound_vars(&generic_params); | 547 | 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 { | 548 | let flags = chalk_rust_ir::TraitFlags { |
544 | auto: trait_.is_auto(db), | 549 | auto: trait_.is_auto(db), |
545 | upstream: trait_.module(db).krate() != krate, | 550 | upstream: trait_.module(db).krate() != krate, |
546 | non_enumerable: true, | 551 | non_enumerable: true, |
552 | coinductive: false, // only relevant for Chalk testing | ||
547 | // FIXME set these flags correctly | 553 | // FIXME set these flags correctly |
548 | marker: false, | 554 | marker: false, |
549 | fundamental: false, | 555 | fundamental: false, |
@@ -558,10 +564,13 @@ pub(crate) fn trait_datum_query( | |||
558 | }) | 564 | }) |
559 | .map(|type_alias| type_alias.to_chalk(db)) | 565 | .map(|type_alias| type_alias.to_chalk(db)) |
560 | .collect(); | 566 | .collect(); |
561 | let trait_datum_bound = | 567 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; |
562 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, associated_ty_ids }; | 568 | let trait_datum = TraitDatum { |
563 | let trait_datum = | 569 | id: trait_id, |
564 | TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()), flags }; | 570 | binders: make_binders(trait_datum_bound, bound_vars.len()), |
571 | flags, | ||
572 | associated_ty_ids, | ||
573 | }; | ||
565 | Arc::new(trait_datum) | 574 | Arc::new(trait_datum) |
566 | } | 575 | } |
567 | 576 | ||
@@ -588,17 +597,12 @@ pub(crate) fn struct_datum_query( | |||
588 | // FIXME set fundamental flag correctly | 597 | // FIXME set fundamental flag correctly |
589 | fundamental: false, | 598 | fundamental: false, |
590 | }; | 599 | }; |
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 { | 600 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { |
596 | self_ty, | ||
597 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 601 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) |
598 | where_clauses, | 602 | where_clauses, |
599 | flags, | ||
600 | }; | 603 | }; |
601 | let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) }; | 604 | let struct_datum = |
605 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
602 | Arc::new(struct_datum) | 606 | Arc::new(struct_datum) |
603 | } | 607 | } |
604 | 608 | ||
@@ -612,10 +616,9 @@ pub(crate) fn impl_datum_query( | |||
612 | let impl_: Impl = from_chalk(db, impl_id); | 616 | let impl_: Impl = from_chalk(db, impl_id); |
613 | match impl_ { | 617 | match impl_ { |
614 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 618 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
615 | Impl::ClosureFnTraitImpl(data) => { | 619 | 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 | } | 620 | } |
621 | .unwrap_or_else(invalid_impl_datum) | ||
619 | } | 622 | } |
620 | 623 | ||
621 | fn impl_block_datum( | 624 | fn impl_block_datum( |
@@ -623,13 +626,11 @@ fn impl_block_datum( | |||
623 | krate: Crate, | 626 | krate: Crate, |
624 | impl_id: ImplId, | 627 | impl_id: ImplId, |
625 | impl_block: ImplBlock, | 628 | impl_block: ImplBlock, |
626 | ) -> Arc<ImplDatum> { | 629 | ) -> Option<Arc<ImplDatum>> { |
627 | let generic_params = impl_block.generic_params(db); | 630 | let generic_params = impl_block.generic_params(db); |
628 | let bound_vars = Substs::bound_vars(&generic_params); | 631 | let bound_vars = Substs::bound_vars(&generic_params); |
629 | let trait_ref = impl_block | 632 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); |
630 | .target_trait_ref(db) | 633 | 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 { | 634 | let impl_type = if impl_block.krate(db) == krate { |
634 | chalk_rust_ir::ImplType::Local | 635 | chalk_rust_ir::ImplType::Local |
635 | } else { | 636 | } else { |
@@ -644,28 +645,7 @@ fn impl_block_datum( | |||
644 | trait_ref.display(db), | 645 | trait_ref.display(db), |
645 | where_clauses | 646 | where_clauses |
646 | ); | 647 | ); |
647 | let trait_ = trait_ref.trait_; | ||
648 | let trait_ref = trait_ref.to_chalk(db); | 648 | 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 | 649 | ||
670 | let polarity = if negative { | 650 | let polarity = if negative { |
671 | chalk_rust_ir::Polarity::Negative | 651 | chalk_rust_ir::Polarity::Negative |
@@ -673,31 +653,41 @@ fn impl_block_datum( | |||
673 | chalk_rust_ir::Polarity::Positive | 653 | chalk_rust_ir::Polarity::Positive |
674 | }; | 654 | }; |
675 | 655 | ||
676 | let impl_datum_bound = | 656 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; |
677 | chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses, associated_ty_values }; | 657 | let associated_ty_value_ids = impl_block |
658 | .items(db) | ||
659 | .into_iter() | ||
660 | .filter_map(|item| match item { | ||
661 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), | ||
662 | _ => None, | ||
663 | }) | ||
664 | .filter(|type_alias| { | ||
665 | // don't include associated types that don't exist in the trait | ||
666 | trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() | ||
667 | }) | ||
668 | .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) | ||
669 | .collect(); | ||
678 | debug!("impl_datum: {:?}", impl_datum_bound); | 670 | debug!("impl_datum: {:?}", impl_datum_bound); |
679 | let impl_datum = ImplDatum { | 671 | let impl_datum = ImplDatum { |
680 | binders: make_binders(impl_datum_bound, bound_vars.len()), | 672 | binders: make_binders(impl_datum_bound, bound_vars.len()), |
681 | impl_type, | 673 | impl_type, |
682 | polarity, | 674 | polarity, |
675 | associated_ty_value_ids, | ||
683 | }; | 676 | }; |
684 | Arc::new(impl_datum) | 677 | Some(Arc::new(impl_datum)) |
685 | } | 678 | } |
686 | 679 | ||
687 | fn invalid_impl_datum() -> Arc<ImplDatum> { | 680 | fn invalid_impl_datum() -> Arc<ImplDatum> { |
688 | let trait_ref = chalk_ir::TraitRef { | 681 | let trait_ref = chalk_ir::TraitRef { |
689 | trait_id: UNKNOWN_TRAIT, | 682 | trait_id: UNKNOWN_TRAIT, |
690 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | 683 | 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 | }; | 684 | }; |
685 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
697 | let impl_datum = ImplDatum { | 686 | let impl_datum = ImplDatum { |
698 | binders: make_binders(impl_datum_bound, 1), | 687 | binders: make_binders(impl_datum_bound, 1), |
699 | impl_type: chalk_rust_ir::ImplType::External, | 688 | impl_type: chalk_rust_ir::ImplType::External, |
700 | polarity: chalk_rust_ir::Polarity::Positive, | 689 | polarity: chalk_rust_ir::Polarity::Positive, |
690 | associated_ty_value_ids: Vec::new(), | ||
701 | }; | 691 | }; |
702 | Arc::new(impl_datum) | 692 | Arc::new(impl_datum) |
703 | } | 693 | } |
@@ -705,15 +695,19 @@ fn invalid_impl_datum() -> Arc<ImplDatum> { | |||
705 | fn closure_fn_trait_impl_datum( | 695 | fn closure_fn_trait_impl_datum( |
706 | db: &impl HirDatabase, | 696 | db: &impl HirDatabase, |
707 | krate: Crate, | 697 | krate: Crate, |
708 | impl_id: ImplId, | ||
709 | data: super::ClosureFnTraitImplData, | 698 | data: super::ClosureFnTraitImplData, |
710 | ) -> Option<Arc<ImplDatum>> { | 699 | ) -> Option<Arc<ImplDatum>> { |
711 | // for some closure |X, Y| -> Z: | 700 | // for some closure |X, Y| -> Z: |
712 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | 701 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } |
713 | 702 | ||
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 | 703 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait |
716 | 704 | ||
705 | // validate FnOnce trait, since we need it in the assoc ty value definition | ||
706 | // and don't want to return a valid value only to find out later that FnOnce | ||
707 | // is broken | ||
708 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
709 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | ||
710 | |||
717 | let num_args: u16 = match &data.def.body(db)[data.expr] { | 711 | let num_args: u16 = match &data.def.body(db)[data.expr] { |
718 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | 712 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, |
719 | _ => { | 713 | _ => { |
@@ -726,7 +720,6 @@ fn closure_fn_trait_impl_datum( | |||
726 | TypeCtor::Tuple { cardinality: num_args }, | 720 | TypeCtor::Tuple { cardinality: num_args }, |
727 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), | 721 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), |
728 | ); | 722 | ); |
729 | let output_ty = Ty::Bound(num_args.into()); | ||
730 | let sig_ty = Ty::apply( | 723 | let sig_ty = Ty::apply( |
731 | TypeCtor::FnPtr { num_args }, | 724 | TypeCtor::FnPtr { num_args }, |
732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), | 725 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), |
@@ -739,32 +732,99 @@ fn closure_fn_trait_impl_datum( | |||
739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | 732 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), |
740 | }; | 733 | }; |
741 | 734 | ||
742 | let output_ty_id = fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | 735 | 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 | 736 | ||
753 | let impl_type = chalk_rust_ir::ImplType::External; | 737 | let impl_type = chalk_rust_ir::ImplType::External; |
754 | 738 | ||
755 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 739 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
756 | trait_ref: trait_ref.to_chalk(db), | 740 | trait_ref: trait_ref.to_chalk(db), |
757 | where_clauses: Vec::new(), | 741 | where_clauses: Vec::new(), |
758 | associated_ty_values: vec![output_ty_value], | ||
759 | }; | 742 | }; |
760 | let impl_datum = ImplDatum { | 743 | let impl_datum = ImplDatum { |
761 | binders: make_binders(impl_datum_bound, num_args as usize + 1), | 744 | binders: make_binders(impl_datum_bound, num_args as usize + 1), |
762 | impl_type, | 745 | impl_type, |
763 | polarity: chalk_rust_ir::Polarity::Positive, | 746 | polarity: chalk_rust_ir::Polarity::Positive, |
747 | associated_ty_value_ids: vec![output_ty_id], | ||
764 | }; | 748 | }; |
765 | Some(Arc::new(impl_datum)) | 749 | Some(Arc::new(impl_datum)) |
766 | } | 750 | } |
767 | 751 | ||
752 | pub(crate) fn associated_ty_value_query( | ||
753 | db: &impl HirDatabase, | ||
754 | krate: Crate, | ||
755 | id: chalk_rust_ir::AssociatedTyValueId, | ||
756 | ) -> Arc<chalk_rust_ir::AssociatedTyValue> { | ||
757 | let data: AssocTyValue = from_chalk(db, id); | ||
758 | match data { | ||
759 | AssocTyValue::TypeAlias(type_alias) => { | ||
760 | type_alias_associated_ty_value(db, krate, type_alias) | ||
761 | } | ||
762 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | ||
763 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
764 | } | ||
765 | } | ||
766 | } | ||
767 | |||
768 | fn type_alias_associated_ty_value( | ||
769 | db: &impl HirDatabase, | ||
770 | _krate: Crate, | ||
771 | type_alias: TypeAlias, | ||
772 | ) -> Arc<AssociatedTyValue> { | ||
773 | let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl"); | ||
774 | let impl_id = Impl::ImplBlock(impl_block).to_chalk(db); | ||
775 | let trait_ = impl_block | ||
776 | .target_trait_ref(db) | ||
777 | .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved | ||
778 | .trait_; | ||
779 | let assoc_ty = trait_ | ||
780 | .associated_type_by_name(db, &type_alias.name(db)) | ||
781 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | ||
782 | let generic_params = impl_block.generic_params(db); | ||
783 | let bound_vars = Substs::bound_vars(&generic_params); | ||
784 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); | ||
785 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | ||
786 | let value = chalk_rust_ir::AssociatedTyValue { | ||
787 | impl_id, | ||
788 | associated_ty_id: assoc_ty.to_chalk(db), | ||
789 | value: make_binders(value_bound, bound_vars.len()), | ||
790 | }; | ||
791 | Arc::new(value) | ||
792 | } | ||
793 | |||
794 | fn closure_fn_trait_output_assoc_ty_value( | ||
795 | db: &impl HirDatabase, | ||
796 | krate: Crate, | ||
797 | data: super::ClosureFnTraitImplData, | ||
798 | ) -> Arc<AssociatedTyValue> { | ||
799 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | ||
800 | |||
801 | let num_args: u16 = match &data.def.body(db)[data.expr] { | ||
802 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | ||
803 | _ => { | ||
804 | log::warn!("closure for closure type {:?} not found", data); | ||
805 | 0 | ||
806 | } | ||
807 | }; | ||
808 | |||
809 | let output_ty = Ty::Bound(num_args.into()); | ||
810 | |||
811 | let fn_once_trait = | ||
812 | get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); | ||
813 | |||
814 | let output_ty_id = fn_once_trait | ||
815 | .associated_type_by_name(db, &name::OUTPUT_TYPE) | ||
816 | .expect("assoc ty value should not exist"); | ||
817 | |||
818 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; | ||
819 | |||
820 | let value = chalk_rust_ir::AssociatedTyValue { | ||
821 | associated_ty_id: output_ty_id.to_chalk(db), | ||
822 | impl_id, | ||
823 | value: make_binders(value_bound, num_args as usize + 1), | ||
824 | }; | ||
825 | Arc::new(value) | ||
826 | } | ||
827 | |||
768 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 828 | 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())?; | 829 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; |
770 | match target { | 830 | match target { |
@@ -803,3 +863,15 @@ impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { | |||
803 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 863 | chalk_ir::ImplId(id_to_chalk(impl_id)) |
804 | } | 864 | } |
805 | } | 865 | } |
866 | |||
867 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { | ||
868 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { | ||
869 | id_from_chalk(id.0) | ||
870 | } | ||
871 | } | ||
872 | |||
873 | impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | ||
874 | fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { | ||
875 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) | ||
876 | } | ||
877 | } | ||