@@ -495,19 +495,25 @@ pub(crate) fn lookup_method(
495
495
visible_from_module : VisibleFromModule ,
496
496
name : & Name ,
497
497
) -> Option < ( ReceiverAdjustments , FunctionId ) > {
498
- iterate_method_candidates (
498
+ let mut not_visible = None ;
499
+ let res = iterate_method_candidates (
499
500
ty,
500
501
db,
501
502
env,
502
503
traits_in_scope,
503
504
visible_from_module,
504
505
Some ( name) ,
505
506
LookupMode :: MethodCall ,
506
- |adjustments, f| match f {
507
- AssocItemId :: FunctionId ( f) => Some ( ( adjustments, f) ) ,
507
+ |adjustments, f, visible| match f {
508
+ AssocItemId :: FunctionId ( f) if visible => Some ( ( adjustments, f) ) ,
509
+ AssocItemId :: FunctionId ( f) if not_visible. is_none ( ) => {
510
+ not_visible = Some ( ( adjustments, f) ) ;
511
+ None
512
+ }
508
513
_ => None ,
509
514
} ,
510
- )
515
+ ) ;
516
+ res. or ( not_visible)
511
517
}
512
518
513
519
/// Whether we're looking up a dotted method call (like `v.len()`) or a path
@@ -619,7 +625,7 @@ pub(crate) fn iterate_method_candidates<T>(
619
625
visible_from_module : VisibleFromModule ,
620
626
name : Option < & Name > ,
621
627
mode : LookupMode ,
622
- mut callback : impl FnMut ( ReceiverAdjustments , AssocItemId ) -> Option < T > ,
628
+ mut callback : impl FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> Option < T > ,
623
629
) -> Option < T > {
624
630
let mut slot = None ;
625
631
iterate_method_candidates_dyn (
@@ -630,9 +636,9 @@ pub(crate) fn iterate_method_candidates<T>(
630
636
visible_from_module,
631
637
name,
632
638
mode,
633
- & mut |adj, item| {
639
+ & mut |adj, item, visible | {
634
640
assert ! ( slot. is_none( ) ) ;
635
- if let Some ( it) = callback ( adj, item) {
641
+ if let Some ( it) = callback ( adj, item, visible ) {
636
642
slot = Some ( it) ;
637
643
return ControlFlow :: Break ( ( ) ) ;
638
644
}
@@ -771,7 +777,7 @@ pub fn iterate_path_candidates(
771
777
name,
772
778
LookupMode :: Path ,
773
779
// the adjustments are not relevant for path lookup
774
- & mut |_, id| callback ( id) ,
780
+ & mut |_, id, _ | callback ( id) ,
775
781
)
776
782
}
777
783
@@ -783,7 +789,7 @@ pub fn iterate_method_candidates_dyn(
783
789
visible_from_module : VisibleFromModule ,
784
790
name : Option < & Name > ,
785
791
mode : LookupMode ,
786
- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
792
+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
787
793
) -> ControlFlow < ( ) > {
788
794
match mode {
789
795
LookupMode :: MethodCall => {
@@ -847,7 +853,7 @@ fn iterate_method_candidates_with_autoref(
847
853
traits_in_scope : & FxHashSet < TraitId > ,
848
854
visible_from_module : VisibleFromModule ,
849
855
name : Option < & Name > ,
850
- mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
856
+ mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
851
857
) -> ControlFlow < ( ) > {
852
858
if receiver_ty. value . is_general_var ( Interner , & receiver_ty. binders ) {
853
859
// don't try to resolve methods on unknown types
@@ -908,7 +914,7 @@ fn iterate_method_candidates_by_receiver(
908
914
traits_in_scope : & FxHashSet < TraitId > ,
909
915
visible_from_module : VisibleFromModule ,
910
916
name : Option < & Name > ,
911
- mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
917
+ mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
912
918
) -> ControlFlow < ( ) > {
913
919
let mut table = InferenceTable :: new ( db, env) ;
914
920
let receiver_ty = table. instantiate_canonical ( receiver_ty. clone ( ) ) ;
@@ -954,7 +960,7 @@ fn iterate_method_candidates_for_self_ty(
954
960
traits_in_scope : & FxHashSet < TraitId > ,
955
961
visible_from_module : VisibleFromModule ,
956
962
name : Option < & Name > ,
957
- mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
963
+ mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
958
964
) -> ControlFlow < ( ) > {
959
965
let mut table = InferenceTable :: new ( db, env) ;
960
966
let self_ty = table. instantiate_canonical ( self_ty. clone ( ) ) ;
@@ -985,7 +991,7 @@ fn iterate_trait_method_candidates(
985
991
name : Option < & Name > ,
986
992
receiver_ty : Option < & Ty > ,
987
993
receiver_adjustments : Option < ReceiverAdjustments > ,
988
- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
994
+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
989
995
) -> ControlFlow < ( ) > {
990
996
let db = table. db ;
991
997
let env = table. trait_env . clone ( ) ;
@@ -1016,17 +1022,19 @@ fn iterate_trait_method_candidates(
1016
1022
for & ( _, item) in data. items . iter ( ) {
1017
1023
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
1018
1024
// since only inherent methods should be included into visibility checking.
1019
- if !is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
1020
- continue ;
1021
- }
1025
+ let visible = match is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
1026
+ IsValidCandidate :: Yes => true ,
1027
+ IsValidCandidate :: NotVisible => false ,
1028
+ IsValidCandidate :: No => continue ,
1029
+ } ;
1022
1030
if !known_implemented {
1023
1031
let goal = generic_implements_goal ( db, env. clone ( ) , t, & canonical_self_ty) ;
1024
1032
if db. trait_solve ( env. krate , goal. cast ( Interner ) ) . is_none ( ) {
1025
1033
continue ' traits;
1026
1034
}
1027
1035
}
1028
1036
known_implemented = true ;
1029
- callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item) ?;
1037
+ callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item, visible ) ?;
1030
1038
}
1031
1039
}
1032
1040
ControlFlow :: Continue ( ( ) )
@@ -1039,7 +1047,7 @@ fn iterate_inherent_methods(
1039
1047
receiver_ty : Option < & Ty > ,
1040
1048
receiver_adjustments : Option < ReceiverAdjustments > ,
1041
1049
visible_from_module : VisibleFromModule ,
1042
- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
1050
+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
1043
1051
) -> ControlFlow < ( ) > {
1044
1052
let db = table. db ;
1045
1053
let env = table. trait_env . clone ( ) ;
@@ -1128,17 +1136,21 @@ fn iterate_inherent_methods(
1128
1136
name : Option < & Name > ,
1129
1137
receiver_ty : Option < & Ty > ,
1130
1138
receiver_adjustments : Option < ReceiverAdjustments > ,
1131
- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
1139
+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
1132
1140
traits : impl Iterator < Item = TraitId > ,
1133
1141
) -> ControlFlow < ( ) > {
1134
1142
let db = table. db ;
1135
1143
for t in traits {
1136
1144
let data = db. trait_data ( t) ;
1137
1145
for & ( _, item) in data. items . iter ( ) {
1138
1146
// We don't pass `visible_from_module` as all trait items should be visible.
1139
- if is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
1140
- callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item) ?;
1141
- }
1147
+ let visible =
1148
+ match is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
1149
+ IsValidCandidate :: Yes => true ,
1150
+ IsValidCandidate :: NotVisible => false ,
1151
+ IsValidCandidate :: No => continue ,
1152
+ } ;
1153
+ callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item, visible) ?;
1142
1154
}
1143
1155
}
1144
1156
ControlFlow :: Continue ( ( ) )
@@ -1152,17 +1164,25 @@ fn iterate_inherent_methods(
1152
1164
receiver_ty : Option < & Ty > ,
1153
1165
receiver_adjustments : Option < ReceiverAdjustments > ,
1154
1166
visible_from_module : Option < ModuleId > ,
1155
- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
1167
+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
1156
1168
) -> ControlFlow < ( ) > {
1157
1169
let db = table. db ;
1158
1170
let impls_for_self_ty = impls. for_self_ty ( self_ty) ;
1159
1171
for & impl_def in impls_for_self_ty {
1160
1172
for & item in & db. impl_data ( impl_def) . items {
1161
- if !is_valid_candidate ( table, name, receiver_ty, item, self_ty, visible_from_module)
1162
- {
1163
- continue ;
1164
- }
1165
- callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item) ?;
1173
+ let visible = match is_valid_candidate (
1174
+ table,
1175
+ name,
1176
+ receiver_ty,
1177
+ item,
1178
+ self_ty,
1179
+ visible_from_module,
1180
+ ) {
1181
+ IsValidCandidate :: Yes => true ,
1182
+ IsValidCandidate :: NotVisible => false ,
1183
+ IsValidCandidate :: No => continue ,
1184
+ } ;
1185
+ callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item, visible) ?;
1166
1186
}
1167
1187
}
1168
1188
ControlFlow :: Continue ( ( ) )
@@ -1191,7 +1211,7 @@ pub fn resolve_indexing_op(
1191
1211
macro_rules! check_that {
1192
1212
( $cond: expr) => {
1193
1213
if !$cond {
1194
- return false ;
1214
+ return IsValidCandidate :: No ;
1195
1215
}
1196
1216
} ;
1197
1217
}
@@ -1203,7 +1223,7 @@ fn is_valid_candidate(
1203
1223
item : AssocItemId ,
1204
1224
self_ty : & Ty ,
1205
1225
visible_from_module : Option < ModuleId > ,
1206
- ) -> bool {
1226
+ ) -> IsValidCandidate {
1207
1227
let db = table. db ;
1208
1228
match item {
1209
1229
AssocItemId :: FunctionId ( m) => {
@@ -1214,13 +1234,13 @@ fn is_valid_candidate(
1214
1234
check_that ! ( receiver_ty. is_none( ) ) ;
1215
1235
1216
1236
check_that ! ( name. map_or( true , |n| data. name. as_ref( ) == Some ( n) ) ) ;
1217
- check_that ! ( visible_from_module . map_or ( true , |from_module| {
1218
- let v = db . const_visibility ( c ) . is_visible_from ( db . upcast ( ) , from_module ) ;
1219
- if !v {
1237
+
1238
+ if let Some ( from_module ) = visible_from_module {
1239
+ if !db . const_visibility ( c ) . is_visible_from ( db . upcast ( ) , from_module ) {
1220
1240
cov_mark:: hit!( const_candidate_not_visible) ;
1241
+ return IsValidCandidate :: NotVisible ;
1221
1242
}
1222
- v
1223
- } ) ) ;
1243
+ }
1224
1244
if let ItemContainerId :: ImplId ( impl_id) = c. lookup ( db. upcast ( ) ) . container {
1225
1245
let self_ty_matches = table. run_in_snapshot ( |table| {
1226
1246
let expected_self_ty = TyBuilder :: impl_self_ty ( db, impl_id)
@@ -1230,35 +1250,39 @@ fn is_valid_candidate(
1230
1250
} ) ;
1231
1251
if !self_ty_matches {
1232
1252
cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1233
- return false ;
1253
+ return IsValidCandidate :: No ;
1234
1254
}
1235
1255
}
1236
- true
1256
+ IsValidCandidate :: Yes
1237
1257
}
1238
- _ => false ,
1258
+ _ => IsValidCandidate :: No ,
1239
1259
}
1240
1260
}
1241
1261
1262
+ enum IsValidCandidate {
1263
+ Yes ,
1264
+ No ,
1265
+ NotVisible ,
1266
+ }
1267
+
1242
1268
fn is_valid_fn_candidate (
1243
1269
table : & mut InferenceTable < ' _ > ,
1244
1270
fn_id : FunctionId ,
1245
1271
name : Option < & Name > ,
1246
1272
receiver_ty : Option < & Ty > ,
1247
1273
self_ty : & Ty ,
1248
1274
visible_from_module : Option < ModuleId > ,
1249
- ) -> bool {
1275
+ ) -> IsValidCandidate {
1250
1276
let db = table. db ;
1251
1277
let data = db. function_data ( fn_id) ;
1252
1278
1253
1279
check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
1254
- check_that ! ( visible_from_module. map_or( true , |from_module| {
1255
- let v = db. function_visibility( fn_id) . is_visible_from( db. upcast( ) , from_module) ;
1256
- if !v {
1280
+ if let Some ( from_module) = visible_from_module {
1281
+ if !db. function_visibility ( fn_id) . is_visible_from ( db. upcast ( ) , from_module) {
1257
1282
cov_mark:: hit!( autoderef_candidate_not_visible) ;
1283
+ return IsValidCandidate :: NotVisible ;
1258
1284
}
1259
- v
1260
- } ) ) ;
1261
-
1285
+ }
1262
1286
table. run_in_snapshot ( |table| {
1263
1287
let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1264
1288
let ( impl_subst, expect_self_ty) = match container {
@@ -1297,7 +1321,7 @@ fn is_valid_fn_candidate(
1297
1321
// We need to consider the bounds on the impl to distinguish functions of the same name
1298
1322
// for a type.
1299
1323
let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
1300
- predicates
1324
+ let valid = predicates
1301
1325
. iter ( )
1302
1326
. map ( |predicate| {
1303
1327
let ( p, b) = predicate
@@ -1312,12 +1336,16 @@ fn is_valid_fn_candidate(
1312
1336
// It's ok to get ambiguity here, as we may not have enough information to prove
1313
1337
// obligations. We'll check if the user is calling the selected method properly
1314
1338
// later anyway.
1315
- . all ( |p| table. try_obligation ( p. cast ( Interner ) ) . is_some ( ) )
1339
+ . all ( |p| table. try_obligation ( p. cast ( Interner ) ) . is_some ( ) ) ;
1340
+ match valid {
1341
+ true => IsValidCandidate :: Yes ,
1342
+ false => IsValidCandidate :: No ,
1343
+ }
1316
1344
} else {
1317
1345
// For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in
1318
1346
// `iterate_trait_method_candidates()`.
1319
1347
// For others, this function shouldn't be called.
1320
- true
1348
+ IsValidCandidate :: Yes
1321
1349
}
1322
1350
} )
1323
1351
}
0 commit comments