@@ -576,30 +576,57 @@ pub(crate) fn iterate_method_candidates<T>(
576
576
slot
577
577
}
578
578
579
- pub fn lookup_trait_m_for_self_ty (
579
+ pub fn lookup_impl_method (
580
580
self_ty : & Ty ,
581
581
db : & dyn HirDatabase ,
582
582
env : Arc < TraitEnvironment > ,
583
- implied_trait : TraitId ,
583
+ trait_ : TraitId ,
584
584
name : & Name ,
585
585
) -> Option < FunctionId > {
586
- let self_ty_tp = TyFingerprint :: for_trait_impl ( self_ty) ?;
586
+ let self_ty_fp = TyFingerprint :: for_trait_impl ( self_ty) ?;
587
587
let trait_impls = TraitImpls :: trait_impls_in_deps_query ( db, env. krate ) ;
588
- let impls = trait_impls. for_trait_and_self_ty ( implied_trait , self_ty_tp ) ;
588
+ let impls = trait_impls. for_trait_and_self_ty ( trait_ , self_ty_fp ) ;
589
589
let mut table = InferenceTable :: new ( db, env. clone ( ) ) ;
590
- if let Some ( data) = Valid :: valid_impl ( impls, & mut table, & self_ty) {
591
- for & impl_item in data. items . iter ( ) {
592
- if Valid :: is_valid_item ( & mut table, Some ( name) , None , impl_item, self_ty, None ) {
593
- match impl_item {
594
- AssocItemId :: FunctionId ( f) => {
595
- return Some ( f) ;
596
- }
597
- _ => ( ) ,
598
- }
599
- }
590
+ find_matching_impl ( impls, & mut table, & self_ty) . and_then ( |data| {
591
+ data. items . iter ( ) . find_map ( |it| match it {
592
+ AssocItemId :: FunctionId ( f) => ( db. function_data ( * f) . name == * name) . then_some ( * f) ,
593
+ _ => None ,
594
+ } )
595
+ } )
596
+ }
597
+
598
+ fn find_matching_impl (
599
+ mut impls : impl Iterator < Item = ImplId > ,
600
+ table : & mut InferenceTable ,
601
+ self_ty : & Ty ,
602
+ ) -> Option < Arc < ImplData > > {
603
+ let db = table. db ;
604
+ loop {
605
+ let impl_ = impls. next ( ) ?;
606
+ let r = table. run_in_snapshot ( |table| {
607
+ let impl_data = db. impl_data ( impl_) ;
608
+ let substs =
609
+ TyBuilder :: subst_for_def ( db, impl_) . fill_with_inference_vars ( table) . build ( ) ;
610
+ let impl_ty = db. impl_self_ty ( impl_) . substitute ( Interner , & substs) ;
611
+
612
+ table
613
+ . unify ( self_ty, & impl_ty)
614
+ . then ( || {
615
+ let wh_goals =
616
+ crate :: chalk_db:: convert_where_clauses ( db, impl_. into ( ) , & substs)
617
+ . into_iter ( )
618
+ . map ( |b| b. into_well_formed_goal ( Interner ) . cast ( Interner ) ) ;
619
+
620
+ let goal = crate :: Goal :: all ( Interner , wh_goals) ;
621
+
622
+ table. try_obligation ( goal) . map ( |_| impl_data)
623
+ } )
624
+ . flatten ( )
625
+ } ) ;
626
+ if r. is_some ( ) {
627
+ break r;
600
628
}
601
629
}
602
- None
603
630
}
604
631
605
632
pub fn iterate_path_candidates (
@@ -877,7 +904,7 @@ fn iterate_trait_method_candidates(
877
904
for & ( _, item) in data. items . iter ( ) {
878
905
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
879
906
// since only inherent methods should be included into visibility checking.
880
- if !Valid :: is_valid_item ( table, name, receiver_ty, item, self_ty, None ) {
907
+ if !is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
881
908
continue ;
882
909
}
883
910
if !known_implemented {
@@ -959,14 +986,8 @@ fn iterate_inherent_methods(
959
986
let impls_for_self_ty = impls. for_self_ty ( self_ty) ;
960
987
for & impl_def in impls_for_self_ty {
961
988
for & item in & db. impl_data ( impl_def) . items {
962
- if !Valid :: is_valid_item (
963
- table,
964
- name,
965
- receiver_ty,
966
- item,
967
- self_ty,
968
- visible_from_module,
969
- ) {
989
+ if !is_valid_candidate ( table, name, receiver_ty, item, self_ty, visible_from_module)
990
+ {
970
991
continue ;
971
992
}
972
993
callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item) ?;
@@ -994,130 +1015,92 @@ pub fn resolve_indexing_op(
994
1015
}
995
1016
None
996
1017
}
997
- struct Valid ;
998
- impl Valid {
999
- fn valid_impl (
1000
- mut impls : impl Iterator < Item = ImplId > ,
1001
- table : & mut InferenceTable ,
1002
- self_ty : & Ty ,
1003
- ) -> Option < Arc < ImplData > > {
1004
- let db = table. db ;
1005
- loop {
1006
- let impl_ = impls. next ( ) ?;
1007
- let r = table. run_in_snapshot ( |table| {
1008
- let impl_data = db. impl_data ( impl_) ;
1009
- let substs =
1010
- TyBuilder :: subst_for_def ( db, impl_) . fill_with_inference_vars ( table) . build ( ) ;
1011
- let impl_ty = substs
1012
- . apply ( db. impl_self_ty ( impl_) . into_value_and_skipped_binders ( ) . 0 , Interner ) ;
1013
-
1014
- table
1015
- . unify ( self_ty, & impl_ty)
1016
- . then ( || {
1017
- let wh_goals =
1018
- crate :: chalk_db:: convert_where_clauses ( db, impl_. into ( ) , & substs)
1019
- . into_iter ( )
1020
- . map ( |b| b. into_well_formed_goal ( Interner ) . cast ( Interner ) ) ;
1021
-
1022
- let goal = crate :: Goal :: all ( Interner , wh_goals) ;
1023
-
1024
- table. try_obligation ( goal) . map ( |_| impl_data)
1025
- } )
1026
- . flatten ( )
1027
- } ) ;
1028
- if r. is_some ( ) {
1029
- break r;
1018
+
1019
+ fn is_valid_candidate (
1020
+ table : & mut InferenceTable ,
1021
+ name : Option < & Name > ,
1022
+ receiver_ty : Option < & Ty > ,
1023
+ item : AssocItemId ,
1024
+ self_ty : & Ty ,
1025
+ visible_from_module : Option < ModuleId > ,
1026
+ ) -> bool {
1027
+ macro_rules! check_that {
1028
+ ( $cond: expr) => {
1029
+ if !$cond {
1030
+ return false ;
1030
1031
}
1031
- }
1032
+ } ;
1032
1033
}
1033
1034
1034
- fn is_valid_item (
1035
- table : & mut InferenceTable ,
1036
- name : Option < & Name > ,
1037
- receiver_ty : Option < & Ty > ,
1038
- item : AssocItemId ,
1039
- self_ty : & Ty ,
1040
- visible_from_module : Option < ModuleId > ,
1041
- ) -> bool {
1042
- macro_rules! assert {
1043
- ( $cond: expr) => {
1044
- if !$cond {
1045
- return false ;
1035
+ let db = table. db ;
1036
+ match item {
1037
+ AssocItemId :: FunctionId ( m) => {
1038
+ let data = db. function_data ( m) ;
1039
+
1040
+ check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
1041
+ check_that ! ( visible_from_module. map_or( true , |from_module| {
1042
+ let v = db. function_visibility( m) . is_visible_from( db. upcast( ) , from_module) ;
1043
+ if !v {
1044
+ cov_mark:: hit!( autoderef_candidate_not_visible) ;
1046
1045
}
1047
- } ;
1048
- }
1049
-
1050
- let db = table. db ;
1051
- match item {
1052
- AssocItemId :: FunctionId ( m) => {
1053
- let data = db. function_data ( m) ;
1054
-
1055
- assert ! ( name. map_or( true , |n| n == & data. name) ) ;
1056
- assert ! ( visible_from_module. map_or( true , |from_module| {
1057
- let v = db. function_visibility( m) . is_visible_from( db. upcast( ) , from_module) ;
1058
- if !v {
1059
- cov_mark:: hit!( autoderef_candidate_not_visible) ;
1060
- }
1061
- v
1062
- } ) ) ;
1063
-
1064
- table. run_in_snapshot ( |table| {
1065
- let subst =
1066
- TyBuilder :: subst_for_def ( db, m) . fill_with_inference_vars ( table) . build ( ) ;
1067
- let expect_self_ty = match m. lookup ( db. upcast ( ) ) . container {
1068
- ItemContainerId :: TraitId ( _) => {
1069
- subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( )
1070
- }
1071
- ItemContainerId :: ImplId ( impl_id) => {
1072
- subst. apply ( db. impl_self_ty ( impl_id) . skip_binders ( ) . clone ( ) , Interner )
1073
- }
1074
- // We should only get called for associated items (impl/trait)
1075
- ItemContainerId :: ModuleId ( _) | ItemContainerId :: ExternBlockId ( _) => {
1076
- unreachable ! ( )
1077
- }
1078
- } ;
1079
- assert ! ( table. unify( & expect_self_ty, self_ty) ) ;
1080
- if let Some ( receiver_ty) = receiver_ty {
1081
- assert ! ( data. has_self_param( ) ) ;
1082
-
1083
- let sig = db. callable_item_signature ( m. into ( ) ) ;
1084
- let expected_receiver =
1085
- sig. map ( |s| s. params ( ) [ 0 ] . clone ( ) ) . substitute ( Interner , & subst) ;
1086
-
1087
- assert ! ( table. unify( & receiver_ty, & expected_receiver) ) ;
1046
+ v
1047
+ } ) ) ;
1048
+
1049
+ table. run_in_snapshot ( |table| {
1050
+ let subst = TyBuilder :: subst_for_def ( db, m) . fill_with_inference_vars ( table) . build ( ) ;
1051
+ let expect_self_ty = match m. lookup ( db. upcast ( ) ) . container {
1052
+ ItemContainerId :: TraitId ( _) => {
1053
+ subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( )
1088
1054
}
1089
- true
1090
- } )
1091
- }
1092
- AssocItemId :: ConstId ( c) => {
1093
- let data = db. const_data ( c) ;
1094
- assert ! ( receiver_ty. is_none( ) ) ;
1095
-
1096
- assert ! ( name. map_or( true , |n| data. name. as_ref( ) == Some ( n) ) ) ;
1097
- assert ! ( visible_from_module. map_or( true , |from_module| {
1098
- let v = db. const_visibility( c) . is_visible_from( db. upcast( ) , from_module) ;
1099
- if !v {
1100
- cov_mark:: hit!( const_candidate_not_visible) ;
1055
+ ItemContainerId :: ImplId ( impl_id) => {
1056
+ subst. apply ( db. impl_self_ty ( impl_id) . skip_binders ( ) . clone ( ) , Interner )
1101
1057
}
1102
- v
1103
- } ) ) ;
1104
- if let ItemContainerId :: ImplId ( impl_id) = c. lookup ( db. upcast ( ) ) . container {
1105
- let self_ty_matches = table. run_in_snapshot ( |table| {
1106
- let subst =
1107
- TyBuilder :: subst_for_def ( db, c) . fill_with_inference_vars ( table) . build ( ) ;
1108
- let expected_self_ty =
1109
- subst. apply ( db. impl_self_ty ( impl_id) . skip_binders ( ) . clone ( ) , Interner ) ;
1110
- table. unify ( & expected_self_ty, & self_ty)
1111
- } ) ;
1112
- if !self_ty_matches {
1113
- cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1114
- return false ;
1058
+ // We should only get called for associated items (impl/trait)
1059
+ ItemContainerId :: ModuleId ( _) | ItemContainerId :: ExternBlockId ( _) => {
1060
+ unreachable ! ( )
1115
1061
}
1062
+ } ;
1063
+ check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1064
+ if let Some ( receiver_ty) = receiver_ty {
1065
+ check_that ! ( data. has_self_param( ) ) ;
1066
+
1067
+ let sig = db. callable_item_signature ( m. into ( ) ) ;
1068
+ let expected_receiver =
1069
+ sig. map ( |s| s. params ( ) [ 0 ] . clone ( ) ) . substitute ( Interner , & subst) ;
1070
+
1071
+ check_that ! ( table. unify( & receiver_ty, & expected_receiver) ) ;
1116
1072
}
1117
1073
true
1074
+ } )
1075
+ }
1076
+ AssocItemId :: ConstId ( c) => {
1077
+ let data = db. const_data ( c) ;
1078
+ check_that ! ( receiver_ty. is_none( ) ) ;
1079
+
1080
+ check_that ! ( name. map_or( true , |n| data. name. as_ref( ) == Some ( n) ) ) ;
1081
+ check_that ! ( visible_from_module. map_or( true , |from_module| {
1082
+ let v = db. const_visibility( c) . is_visible_from( db. upcast( ) , from_module) ;
1083
+ if !v {
1084
+ cov_mark:: hit!( const_candidate_not_visible) ;
1085
+ }
1086
+ v
1087
+ } ) ) ;
1088
+ if let ItemContainerId :: ImplId ( impl_id) = c. lookup ( db. upcast ( ) ) . container {
1089
+ let self_ty_matches = table. run_in_snapshot ( |table| {
1090
+ let subst =
1091
+ TyBuilder :: subst_for_def ( db, c) . fill_with_inference_vars ( table) . build ( ) ;
1092
+ let expected_self_ty =
1093
+ subst. apply ( db. impl_self_ty ( impl_id) . skip_binders ( ) . clone ( ) , Interner ) ;
1094
+ table. unify ( & expected_self_ty, & self_ty)
1095
+ } ) ;
1096
+ if !self_ty_matches {
1097
+ cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1098
+ return false ;
1099
+ }
1118
1100
}
1119
- _ => false ,
1101
+ true
1120
1102
}
1103
+ _ => false ,
1121
1104
}
1122
1105
}
1123
1106
0 commit comments