@@ -1064,6 +1064,14 @@ pub fn resolve_indexing_op(
1064
1064
None
1065
1065
}
1066
1066
1067
+ macro_rules! check_that {
1068
+ ( $cond: expr) => {
1069
+ if !$cond {
1070
+ return false ;
1071
+ }
1072
+ } ;
1073
+ }
1074
+
1067
1075
fn is_valid_candidate (
1068
1076
table : & mut InferenceTable < ' _ > ,
1069
1077
name : Option < & Name > ,
@@ -1072,54 +1080,10 @@ fn is_valid_candidate(
1072
1080
self_ty : & Ty ,
1073
1081
visible_from_module : Option < ModuleId > ,
1074
1082
) -> bool {
1075
- macro_rules! check_that {
1076
- ( $cond: expr) => {
1077
- if !$cond {
1078
- return false ;
1079
- }
1080
- } ;
1081
- }
1082
-
1083
1083
let db = table. db ;
1084
1084
match item {
1085
1085
AssocItemId :: FunctionId ( m) => {
1086
- let data = db. function_data ( m) ;
1087
-
1088
- check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
1089
- check_that ! ( visible_from_module. map_or( true , |from_module| {
1090
- let v = db. function_visibility( m) . is_visible_from( db. upcast( ) , from_module) ;
1091
- if !v {
1092
- cov_mark:: hit!( autoderef_candidate_not_visible) ;
1093
- }
1094
- v
1095
- } ) ) ;
1096
-
1097
- table. run_in_snapshot ( |table| {
1098
- let subst = TyBuilder :: subst_for_def ( db, m) . fill_with_inference_vars ( table) . build ( ) ;
1099
- let expect_self_ty = match m. lookup ( db. upcast ( ) ) . container {
1100
- ItemContainerId :: TraitId ( _) => {
1101
- subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( )
1102
- }
1103
- ItemContainerId :: ImplId ( impl_id) => {
1104
- subst. apply ( db. impl_self_ty ( impl_id) . skip_binders ( ) . clone ( ) , Interner )
1105
- }
1106
- // We should only get called for associated items (impl/trait)
1107
- ItemContainerId :: ModuleId ( _) | ItemContainerId :: ExternBlockId ( _) => {
1108
- unreachable ! ( )
1109
- }
1110
- } ;
1111
- check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1112
- if let Some ( receiver_ty) = receiver_ty {
1113
- check_that ! ( data. has_self_param( ) ) ;
1114
-
1115
- let sig = db. callable_item_signature ( m. into ( ) ) ;
1116
- let expected_receiver =
1117
- sig. map ( |s| s. params ( ) [ 0 ] . clone ( ) ) . substitute ( Interner , & subst) ;
1118
-
1119
- check_that ! ( table. unify( & receiver_ty, & expected_receiver) ) ;
1120
- }
1121
- true
1122
- } )
1086
+ is_valid_fn_candidate ( table, m, name, receiver_ty, self_ty, visible_from_module)
1123
1087
}
1124
1088
AssocItemId :: ConstId ( c) => {
1125
1089
let data = db. const_data ( c) ;
@@ -1152,6 +1116,94 @@ fn is_valid_candidate(
1152
1116
}
1153
1117
}
1154
1118
1119
+ fn is_valid_fn_candidate (
1120
+ table : & mut InferenceTable < ' _ > ,
1121
+ fn_id : FunctionId ,
1122
+ name : Option < & Name > ,
1123
+ receiver_ty : Option < & Ty > ,
1124
+ self_ty : & Ty ,
1125
+ visible_from_module : Option < ModuleId > ,
1126
+ ) -> bool {
1127
+ let db = table. db ;
1128
+ let data = db. function_data ( fn_id) ;
1129
+
1130
+ check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
1131
+ check_that ! ( visible_from_module. map_or( true , |from_module| {
1132
+ let v = db. function_visibility( fn_id) . is_visible_from( db. upcast( ) , from_module) ;
1133
+ if !v {
1134
+ cov_mark:: hit!( autoderef_candidate_not_visible) ;
1135
+ }
1136
+ v
1137
+ } ) ) ;
1138
+
1139
+ table. run_in_snapshot ( |table| {
1140
+ let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1141
+ let impl_subst = match container {
1142
+ ItemContainerId :: ImplId ( it) => {
1143
+ TyBuilder :: subst_for_def ( db, it) . fill_with_inference_vars ( table) . build ( )
1144
+ }
1145
+ ItemContainerId :: TraitId ( it) => {
1146
+ TyBuilder :: subst_for_def ( db, it) . fill_with_inference_vars ( table) . build ( )
1147
+ }
1148
+ _ => unreachable ! ( ) ,
1149
+ } ;
1150
+
1151
+ let fn_subst = TyBuilder :: subst_for_def ( db, fn_id)
1152
+ . use_parent_substs ( & impl_subst)
1153
+ . fill_with_inference_vars ( table)
1154
+ . build ( ) ;
1155
+
1156
+ let expect_self_ty = match container {
1157
+ ItemContainerId :: TraitId ( _) => fn_subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( ) ,
1158
+ ItemContainerId :: ImplId ( impl_id) => {
1159
+ fn_subst. apply ( db. impl_self_ty ( impl_id) . skip_binders ( ) . clone ( ) , Interner )
1160
+ }
1161
+ // We should only get called for associated items (impl/trait)
1162
+ ItemContainerId :: ModuleId ( _) | ItemContainerId :: ExternBlockId ( _) => {
1163
+ unreachable ! ( )
1164
+ }
1165
+ } ;
1166
+ check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1167
+
1168
+ if let Some ( receiver_ty) = receiver_ty {
1169
+ check_that ! ( data. has_self_param( ) ) ;
1170
+
1171
+ let sig = db. callable_item_signature ( fn_id. into ( ) ) ;
1172
+ let expected_receiver =
1173
+ sig. map ( |s| s. params ( ) [ 0 ] . clone ( ) ) . substitute ( Interner , & fn_subst) ;
1174
+
1175
+ check_that ! ( table. unify( & receiver_ty, & expected_receiver) ) ;
1176
+ }
1177
+
1178
+ if let ItemContainerId :: ImplId ( impl_id) = container {
1179
+ // We need to consider the bounds on the impl to distinguish functions of the same name
1180
+ // for a type.
1181
+ let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
1182
+ predicates
1183
+ . iter ( )
1184
+ . map ( |predicate| {
1185
+ let ( p, b) = predicate
1186
+ . clone ( )
1187
+ . substitute ( Interner , & impl_subst)
1188
+ // Skipping the inner binders is ok, as we don't handle quantified where
1189
+ // clauses yet.
1190
+ . into_value_and_skipped_binders ( ) ;
1191
+ stdx:: always!( b. len( Interner ) == 0 ) ;
1192
+ p
1193
+ } )
1194
+ // It's ok to get ambiguity here, as we may not have enough information to prove
1195
+ // obligations. We'll check if the user is calling the selected method properly
1196
+ // later anyway.
1197
+ . all ( |p| table. try_obligation ( p. cast ( Interner ) ) . is_some ( ) )
1198
+ } else {
1199
+ // For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in
1200
+ // `iterate_trait_method_candidates()`.
1201
+ // For others, this function shouldn't be called.
1202
+ true
1203
+ }
1204
+ } )
1205
+ }
1206
+
1155
1207
pub fn implements_trait (
1156
1208
ty : & Canonical < Ty > ,
1157
1209
db : & dyn HirDatabase ,
0 commit comments