diff options
author | Florian Diebold <[email protected]> | 2021-05-16 14:50:28 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-05-21 16:48:34 +0100 |
commit | 1250ddc5cf58ff0a6bbf7c07e5bd9f7cc7db5a09 (patch) | |
tree | 51c6ed040c2b1ec6b33321501ced866d87701c71 /crates/hir_ty/src/method_resolution.rs | |
parent | a3d9cac69057db700c4f6e01b84dc59529ea6dfd (diff) |
Rework obligation handling
We can't do the easy hack that we did before anymore, where we kept
track of whether any inference variables changed since the last time we
rechecked obligations. Instead, we store the obligations in
canonicalized form; that way we can easily check the inference variables
to see whether they have changed since the goal was canonicalized.
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 37e1f89d8..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,8 +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 trait_env = Arc::new(TraitEnvironment::default()); // FIXME | 823 | let substs = super::infer::unify(db, env, &tys)?; |
802 | let substs = super::infer::unify(db, trait_env, &tys)?; | ||
803 | // 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. |
804 | // 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 |
805 | // 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 |
@@ -824,6 +845,7 @@ fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution | |||
824 | 845 | ||
825 | fn transform_receiver_ty( | 846 | fn transform_receiver_ty( |
826 | db: &dyn HirDatabase, | 847 | db: &dyn HirDatabase, |
848 | env: Arc<TraitEnvironment>, | ||
827 | function_id: FunctionId, | 849 | function_id: FunctionId, |
828 | self_ty: &Canonical<Ty>, | 850 | self_ty: &Canonical<Ty>, |
829 | ) -> Option<Ty> { | 851 | ) -> Option<Ty> { |
@@ -833,7 +855,7 @@ fn transform_receiver_ty( | |||
833 | .fill_with_unknown() | 855 | .fill_with_unknown() |
834 | .build(), | 856 | .build(), |
835 | AssocContainerId::ImplId(impl_id) => { | 857 | AssocContainerId::ImplId(impl_id) => { |
836 | let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?; | 858 | let impl_substs = inherent_impl_substs(db, env, impl_id, &self_ty)?; |
837 | TyBuilder::subst_for_def(db, function_id) | 859 | TyBuilder::subst_for_def(db, function_id) |
838 | .use_parent_substs(&impl_substs) | 860 | .use_parent_substs(&impl_substs) |
839 | .fill_with_unknown() | 861 | .fill_with_unknown() |
@@ -853,7 +875,7 @@ pub fn implements_trait( | |||
853 | trait_: TraitId, | 875 | trait_: TraitId, |
854 | ) -> bool { | 876 | ) -> bool { |
855 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 877 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
856 | let solution = db.trait_solve(krate, goal); | 878 | let solution = db.trait_solve(krate, goal.cast(&Interner)); |
857 | 879 | ||
858 | solution.is_some() | 880 | solution.is_some() |
859 | } | 881 | } |
@@ -866,7 +888,7 @@ pub fn implements_trait_unique( | |||
866 | trait_: TraitId, | 888 | trait_: TraitId, |
867 | ) -> bool { | 889 | ) -> bool { |
868 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 890 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
869 | let solution = db.trait_solve(krate, goal); | 891 | let solution = db.trait_solve(krate, goal.cast(&Interner)); |
870 | 892 | ||
871 | matches!(solution, Some(crate::Solution::Unique(_))) | 893 | matches!(solution, Some(crate::Solution::Unique(_))) |
872 | } | 894 | } |