diff options
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 48bbcfd9f..08e385a42 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -577,6 +577,7 @@ fn iterate_method_candidates_by_receiver( | |||
577 | if iterate_inherent_methods( | 577 | if iterate_inherent_methods( |
578 | self_ty, | 578 | self_ty, |
579 | db, | 579 | db, |
580 | env.clone(), | ||
580 | name, | 581 | name, |
581 | Some(receiver_ty), | 582 | Some(receiver_ty), |
582 | krate, | 583 | krate, |
@@ -613,8 +614,16 @@ fn iterate_method_candidates_for_self_ty( | |||
613 | name: Option<&Name>, | 614 | name: Option<&Name>, |
614 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 615 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
615 | ) -> bool { | 616 | ) -> bool { |
616 | if iterate_inherent_methods(self_ty, db, name, None, krate, visible_from_module, &mut callback) | 617 | if iterate_inherent_methods( |
617 | { | 618 | self_ty, |
619 | db, | ||
620 | env.clone(), | ||
621 | name, | ||
622 | None, | ||
623 | krate, | ||
624 | visible_from_module, | ||
625 | &mut callback, | ||
626 | ) { | ||
618 | return true; | 627 | return true; |
619 | } | 628 | } |
620 | iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) | 629 | iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) |
@@ -653,12 +662,12 @@ fn iterate_trait_method_candidates( | |||
653 | for (_name, item) in data.items.iter() { | 662 | for (_name, item) in data.items.iter() { |
654 | // Don't pass a `visible_from_module` down to `is_valid_candidate`, | 663 | // Don't pass a `visible_from_module` down to `is_valid_candidate`, |
655 | // since only inherent methods should be included into visibility checking. | 664 | // since only inherent methods should be included into visibility checking. |
656 | if !is_valid_candidate(db, name, receiver_ty, *item, self_ty, None) { | 665 | if !is_valid_candidate(db, env.clone(), name, receiver_ty, *item, self_ty, None) { |
657 | continue; | 666 | continue; |
658 | } | 667 | } |
659 | if !known_implemented { | 668 | if !known_implemented { |
660 | let goal = generic_implements_goal(db, env.clone(), t, self_ty.clone()); | 669 | let goal = generic_implements_goal(db, env.clone(), t, self_ty.clone()); |
661 | if db.trait_solve(krate, goal).is_none() { | 670 | if db.trait_solve(krate, goal.cast(&Interner)).is_none() { |
662 | continue 'traits; | 671 | continue 'traits; |
663 | } | 672 | } |
664 | } | 673 | } |
@@ -675,6 +684,7 @@ fn iterate_trait_method_candidates( | |||
675 | fn iterate_inherent_methods( | 684 | fn iterate_inherent_methods( |
676 | self_ty: &Canonical<Ty>, | 685 | self_ty: &Canonical<Ty>, |
677 | db: &dyn HirDatabase, | 686 | db: &dyn HirDatabase, |
687 | env: Arc<TraitEnvironment>, | ||
678 | name: Option<&Name>, | 688 | name: Option<&Name>, |
679 | receiver_ty: Option<&Canonical<Ty>>, | 689 | receiver_ty: Option<&Canonical<Ty>>, |
680 | krate: CrateId, | 690 | krate: CrateId, |
@@ -690,14 +700,24 @@ fn iterate_inherent_methods( | |||
690 | 700 | ||
691 | for &impl_def in impls.for_self_ty(&self_ty.value) { | 701 | for &impl_def in impls.for_self_ty(&self_ty.value) { |
692 | for &item in db.impl_data(impl_def).items.iter() { | 702 | for &item in db.impl_data(impl_def).items.iter() { |
693 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty, visible_from_module) { | 703 | if !is_valid_candidate( |
704 | db, | ||
705 | env.clone(), | ||
706 | name, | ||
707 | receiver_ty, | ||
708 | item, | ||
709 | self_ty, | ||
710 | visible_from_module, | ||
711 | ) { | ||
694 | continue; | 712 | continue; |
695 | } | 713 | } |
696 | // we have to check whether the self type unifies with the type | 714 | // we have to check whether the self type unifies with the type |
697 | // that the impl is for. If we have a receiver type, this | 715 | // that the impl is for. If we have a receiver type, this |
698 | // already happens in `is_valid_candidate` above; if not, we | 716 | // already happens in `is_valid_candidate` above; if not, we |
699 | // check it here | 717 | // check it here |
700 | if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() { | 718 | if receiver_ty.is_none() |
719 | && inherent_impl_substs(db, env.clone(), impl_def, self_ty).is_none() | ||
720 | { | ||
701 | cov_mark::hit!(impl_self_type_match_without_receiver); | 721 | cov_mark::hit!(impl_self_type_match_without_receiver); |
702 | continue; | 722 | continue; |
703 | } | 723 | } |
@@ -722,7 +742,7 @@ pub fn resolve_indexing_op( | |||
722 | let deref_chain = autoderef_method_receiver(db, krate, ty); | 742 | let deref_chain = autoderef_method_receiver(db, krate, ty); |
723 | for ty in deref_chain { | 743 | for ty in deref_chain { |
724 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); | 744 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); |
725 | if db.trait_solve(krate, goal).is_some() { | 745 | if db.trait_solve(krate, goal.cast(&Interner)).is_some() { |
726 | return Some(ty); | 746 | return Some(ty); |
727 | } | 747 | } |
728 | } | 748 | } |
@@ -731,6 +751,7 @@ pub fn resolve_indexing_op( | |||
731 | 751 | ||
732 | fn is_valid_candidate( | 752 | fn is_valid_candidate( |
733 | db: &dyn HirDatabase, | 753 | db: &dyn HirDatabase, |
754 | env: Arc<TraitEnvironment>, | ||
734 | name: Option<&Name>, | 755 | name: Option<&Name>, |
735 | receiver_ty: Option<&Canonical<Ty>>, | 756 | receiver_ty: Option<&Canonical<Ty>>, |
736 | item: AssocItemId, | 757 | item: AssocItemId, |
@@ -749,7 +770,7 @@ fn is_valid_candidate( | |||
749 | if !data.has_self_param() { | 770 | if !data.has_self_param() { |
750 | return false; | 771 | return false; |
751 | } | 772 | } |
752 | let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { | 773 | let transformed_receiver_ty = match transform_receiver_ty(db, env, m, self_ty) { |
753 | Some(ty) => ty, | 774 | Some(ty) => ty, |
754 | None => return false, | 775 | None => return false, |
755 | }; | 776 | }; |
@@ -776,6 +797,7 @@ fn is_valid_candidate( | |||
776 | 797 | ||
777 | pub(crate) fn inherent_impl_substs( | 798 | pub(crate) fn inherent_impl_substs( |
778 | db: &dyn HirDatabase, | 799 | db: &dyn HirDatabase, |
800 | env: Arc<TraitEnvironment>, | ||
779 | impl_id: ImplId, | 801 | impl_id: ImplId, |
780 | self_ty: &Canonical<Ty>, | 802 | self_ty: &Canonical<Ty>, |
781 | ) -> Option<Substitution> { | 803 | ) -> Option<Substitution> { |
@@ -798,7 +820,7 @@ pub(crate) fn inherent_impl_substs( | |||
798 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | 820 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), |
799 | value: (self_ty_with_vars, self_ty.value.clone()), | 821 | value: (self_ty_with_vars, self_ty.value.clone()), |
800 | }; | 822 | }; |
801 | let substs = super::infer::unify(&tys)?; | 823 | let substs = super::infer::unify(db, env, &tys)?; |
802 | // We only want the substs for the vars we added, not the ones from self_ty. | 824 | // We only want the substs for the vars we added, not the ones from self_ty. |
803 | // Also, if any of the vars we added are still in there, we replace them by | 825 | // Also, if any of the vars we added are still in there, we replace them by |
804 | // Unknown. I think this can only really happen if self_ty contained | 826 | // Unknown. I think this can only really happen if self_ty contained |
@@ -823,6 +845,7 @@ fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution | |||
823 | 845 | ||
824 | fn transform_receiver_ty( | 846 | fn transform_receiver_ty( |
825 | db: &dyn HirDatabase, | 847 | db: &dyn HirDatabase, |
848 | env: Arc<TraitEnvironment>, | ||
826 | function_id: FunctionId, | 849 | function_id: FunctionId, |
827 | self_ty: &Canonical<Ty>, | 850 | self_ty: &Canonical<Ty>, |
828 | ) -> Option<Ty> { | 851 | ) -> Option<Ty> { |
@@ -832,7 +855,7 @@ fn transform_receiver_ty( | |||
832 | .fill_with_unknown() | 855 | .fill_with_unknown() |
833 | .build(), | 856 | .build(), |
834 | AssocContainerId::ImplId(impl_id) => { | 857 | AssocContainerId::ImplId(impl_id) => { |
835 | let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?; | 858 | let impl_substs = inherent_impl_substs(db, env, impl_id, &self_ty)?; |
836 | TyBuilder::subst_for_def(db, function_id) | 859 | TyBuilder::subst_for_def(db, function_id) |
837 | .use_parent_substs(&impl_substs) | 860 | .use_parent_substs(&impl_substs) |
838 | .fill_with_unknown() | 861 | .fill_with_unknown() |
@@ -852,7 +875,7 @@ pub fn implements_trait( | |||
852 | trait_: TraitId, | 875 | trait_: TraitId, |
853 | ) -> bool { | 876 | ) -> bool { |
854 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 877 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
855 | let solution = db.trait_solve(krate, goal); | 878 | let solution = db.trait_solve(krate, goal.cast(&Interner)); |
856 | 879 | ||
857 | solution.is_some() | 880 | solution.is_some() |
858 | } | 881 | } |
@@ -865,7 +888,7 @@ pub fn implements_trait_unique( | |||
865 | trait_: TraitId, | 888 | trait_: TraitId, |
866 | ) -> bool { | 889 | ) -> bool { |
867 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 890 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
868 | let solution = db.trait_solve(krate, goal); | 891 | let solution = db.trait_solve(krate, goal.cast(&Interner)); |
869 | 892 | ||
870 | matches!(solution, Some(crate::Solution::Unique(_))) | 893 | matches!(solution, Some(crate::Solution::Unique(_))) |
871 | } | 894 | } |