aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/traits.rs13
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs286
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;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 10use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
11use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait}; 11use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait, TypeAlias};
12 12
13use self::chalk::{from_chalk, ToChalk}; 13use 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)]
308pub 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};
10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_expand::name; 12use hir_expand::name;
13 13
14use ra_db::salsa::{InternId, InternKey}; 14use ra_db::salsa::{InternId, InternKey};
15 15
16use super::{Canonical, ChalkContext, Impl, Obligation}; 16use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
17use crate::{ 17use 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
211impl 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
214impl ToChalk for GenericPredicate { 226impl 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
621fn impl_block_datum( 624fn 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
687fn invalid_impl_datum() -> Arc<ImplDatum> { 680fn 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> {
705fn closure_fn_trait_impl_datum( 695fn 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
752pub(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
768fn 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
794fn 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
768fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 828fn 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
867impl 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
873impl 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}