diff options
Diffstat (limited to 'crates/ra_hir_ty/src/traits/chalk.rs')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 184 |
1 files changed, 57 insertions, 127 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 104346ada..e3f02fa15 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -8,17 +8,16 @@ use chalk_ir::{ | |||
8 | TypeName, UniverseIndex, | 8 | TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | use ra_db::CrateId; | ||
12 | 11 | ||
13 | use hir_def::{ | 12 | use hir_def::{ |
14 | expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId, | 13 | AssocItemId, AstItemDef, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, |
15 | ImplId, Lookup, TraitId, TypeAliasId, | 14 | }; |
15 | use ra_db::{ | ||
16 | salsa::{InternId, InternKey}, | ||
17 | CrateId, | ||
16 | }; | 18 | }; |
17 | use hir_expand::name; | ||
18 | |||
19 | use ra_db::salsa::{InternId, InternKey}; | ||
20 | 19 | ||
21 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 20 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
22 | use crate::{ | 21 | use crate::{ |
23 | db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, | 22 | db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, |
24 | TraitRef, Ty, TypeCtor, TypeWalk, | 23 | TraitRef, Ty, TypeCtor, TypeWalk, |
@@ -395,6 +394,51 @@ where | |||
395 | } | 394 | } |
396 | } | 395 | } |
397 | 396 | ||
397 | impl ToChalk for builtin::BuiltinImplData { | ||
398 | type Chalk = chalk_rust_ir::ImplDatum<ChalkIr>; | ||
399 | |||
400 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum<ChalkIr> { | ||
401 | let impl_type = chalk_rust_ir::ImplType::External; | ||
402 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); | ||
403 | |||
404 | let impl_datum_bound = | ||
405 | chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; | ||
406 | let associated_ty_value_ids = | ||
407 | self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); | ||
408 | chalk_rust_ir::ImplDatum { | ||
409 | binders: make_binders(impl_datum_bound, self.num_vars), | ||
410 | impl_type, | ||
411 | polarity: chalk_rust_ir::Polarity::Positive, | ||
412 | associated_ty_value_ids, | ||
413 | } | ||
414 | } | ||
415 | |||
416 | fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum<ChalkIr>) -> Self { | ||
417 | unimplemented!() | ||
418 | } | ||
419 | } | ||
420 | |||
421 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { | ||
422 | type Chalk = chalk_rust_ir::AssociatedTyValue<ChalkIr>; | ||
423 | |||
424 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue<ChalkIr> { | ||
425 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; | ||
426 | |||
427 | chalk_rust_ir::AssociatedTyValue { | ||
428 | associated_ty_id: self.assoc_ty_id.to_chalk(db), | ||
429 | impl_id: self.impl_.to_chalk(db), | ||
430 | value: make_binders(value_bound, self.num_vars), | ||
431 | } | ||
432 | } | ||
433 | |||
434 | fn from_chalk( | ||
435 | _db: &impl HirDatabase, | ||
436 | _data: chalk_rust_ir::AssociatedTyValue<ChalkIr>, | ||
437 | ) -> builtin::BuiltinImplAssocTyValueData { | ||
438 | unimplemented!() | ||
439 | } | ||
440 | } | ||
441 | |||
398 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 442 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { |
399 | chalk_ir::Binders { | 443 | chalk_ir::Binders { |
400 | value, | 444 | value, |
@@ -456,18 +500,10 @@ where | |||
456 | .collect(); | 500 | .collect(); |
457 | 501 | ||
458 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); | 502 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); |
459 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { | 503 | |
460 | for &fn_trait in | 504 | builtin::get_builtin_impls(self.db, self.krate, &ty, trait_, |i| { |
461 | [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() | 505 | result.push(i.to_chalk(self.db)) |
462 | { | 506 | }); |
463 | if let Some(actual_trait) = get_fn_trait(self.db, self.krate, fn_trait) { | ||
464 | if trait_ == actual_trait { | ||
465 | let impl_ = super::ClosureFnTraitImplData { def, expr, fn_trait }; | ||
466 | result.push(Impl::ClosureFnTraitImpl(impl_).to_chalk(self.db)); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | 507 | ||
472 | debug!("impls_for_trait returned {} impls", result.len()); | 508 | debug!("impls_for_trait returned {} impls", result.len()); |
473 | result | 509 | result |
@@ -619,7 +655,7 @@ pub(crate) fn impl_datum_query( | |||
619 | let impl_: Impl = from_chalk(db, impl_id); | 655 | let impl_: Impl = from_chalk(db, impl_id); |
620 | match impl_ { | 656 | match impl_ { |
621 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 657 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
622 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), | 658 | _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), |
623 | } | 659 | } |
624 | .unwrap_or_else(invalid_impl_datum) | 660 | .unwrap_or_else(invalid_impl_datum) |
625 | } | 661 | } |
@@ -700,63 +736,6 @@ fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> { | |||
700 | Arc::new(impl_datum) | 736 | Arc::new(impl_datum) |
701 | } | 737 | } |
702 | 738 | ||
703 | fn closure_fn_trait_impl_datum( | ||
704 | db: &impl HirDatabase, | ||
705 | krate: CrateId, | ||
706 | data: super::ClosureFnTraitImplData, | ||
707 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { | ||
708 | // for some closure |X, Y| -> Z: | ||
709 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | ||
710 | |||
711 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait | ||
712 | |||
713 | // validate FnOnce trait, since we need it in the assoc ty value definition | ||
714 | // and don't want to return a valid value only to find out later that FnOnce | ||
715 | // is broken | ||
716 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
717 | let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; | ||
718 | |||
719 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { | ||
720 | Expr::Lambda { args, .. } => args.len() as u16, | ||
721 | _ => { | ||
722 | log::warn!("closure for closure type {:?} not found", data); | ||
723 | 0 | ||
724 | } | ||
725 | }; | ||
726 | |||
727 | let arg_ty = Ty::apply( | ||
728 | TypeCtor::Tuple { cardinality: num_args }, | ||
729 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), | ||
730 | ); | ||
731 | let sig_ty = Ty::apply( | ||
732 | TypeCtor::FnPtr { num_args }, | ||
733 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), | ||
734 | ); | ||
735 | |||
736 | let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); | ||
737 | |||
738 | let trait_ref = TraitRef { | ||
739 | trait_: trait_.into(), | ||
740 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | ||
741 | }; | ||
742 | |||
743 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); | ||
744 | |||
745 | let impl_type = chalk_rust_ir::ImplType::External; | ||
746 | |||
747 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | ||
748 | trait_ref: trait_ref.to_chalk(db), | ||
749 | where_clauses: Vec::new(), | ||
750 | }; | ||
751 | let impl_datum = ImplDatum { | ||
752 | binders: make_binders(impl_datum_bound, num_args as usize + 1), | ||
753 | impl_type, | ||
754 | polarity: chalk_rust_ir::Polarity::Positive, | ||
755 | associated_ty_value_ids: vec![output_ty_id], | ||
756 | }; | ||
757 | Some(Arc::new(impl_datum)) | ||
758 | } | ||
759 | |||
760 | pub(crate) fn associated_ty_value_query( | 739 | pub(crate) fn associated_ty_value_query( |
761 | db: &impl HirDatabase, | 740 | db: &impl HirDatabase, |
762 | krate: CrateId, | 741 | krate: CrateId, |
@@ -767,9 +746,7 @@ pub(crate) fn associated_ty_value_query( | |||
767 | AssocTyValue::TypeAlias(type_alias) => { | 746 | AssocTyValue::TypeAlias(type_alias) => { |
768 | type_alias_associated_ty_value(db, krate, type_alias) | 747 | type_alias_associated_ty_value(db, krate, type_alias) |
769 | } | 748 | } |
770 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | 749 | _ => Arc::new(builtin::associated_ty_value(db, krate, data).to_chalk(db)), |
771 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
772 | } | ||
773 | } | 750 | } |
774 | } | 751 | } |
775 | 752 | ||
@@ -802,53 +779,6 @@ fn type_alias_associated_ty_value( | |||
802 | Arc::new(value) | 779 | Arc::new(value) |
803 | } | 780 | } |
804 | 781 | ||
805 | fn closure_fn_trait_output_assoc_ty_value( | ||
806 | db: &impl HirDatabase, | ||
807 | krate: CrateId, | ||
808 | data: super::ClosureFnTraitImplData, | ||
809 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
810 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | ||
811 | |||
812 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { | ||
813 | Expr::Lambda { args, .. } => args.len() as u16, | ||
814 | _ => { | ||
815 | log::warn!("closure for closure type {:?} not found", data); | ||
816 | 0 | ||
817 | } | ||
818 | }; | ||
819 | |||
820 | let output_ty = Ty::Bound(num_args.into()); | ||
821 | |||
822 | let fn_once_trait = | ||
823 | get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); | ||
824 | |||
825 | let output_ty_id = db | ||
826 | .trait_data(fn_once_trait) | ||
827 | .associated_type_by_name(&name::OUTPUT_TYPE) | ||
828 | .expect("assoc ty value should not exist"); | ||
829 | |||
830 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; | ||
831 | |||
832 | let value = chalk_rust_ir::AssociatedTyValue { | ||
833 | associated_ty_id: output_ty_id.to_chalk(db), | ||
834 | impl_id, | ||
835 | value: make_binders(value_bound, num_args as usize + 1), | ||
836 | }; | ||
837 | Arc::new(value) | ||
838 | } | ||
839 | |||
840 | fn get_fn_trait( | ||
841 | db: &impl HirDatabase, | ||
842 | krate: CrateId, | ||
843 | fn_trait: super::FnTrait, | ||
844 | ) -> Option<TraitId> { | ||
845 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; | ||
846 | match target { | ||
847 | LangItemTarget::TraitId(t) => Some(t), | ||
848 | _ => None, | ||
849 | } | ||
850 | } | ||
851 | |||
852 | fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T { | 782 | fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T { |
853 | T::from_intern_id(InternId::from(chalk_id.index)) | 783 | T::from_intern_id(InternId::from(chalk_id.index)) |
854 | } | 784 | } |