@@ -495,19 +495,25 @@ pub(crate) fn lookup_method(
495495 visible_from_module : VisibleFromModule ,
496496 name : & Name ,
497497) -> Option < ( ReceiverAdjustments , FunctionId ) > {
498- iterate_method_candidates (
498+ let mut not_visible = None ;
499+ let res = iterate_method_candidates (
499500 ty,
500501 db,
501502 env,
502503 traits_in_scope,
503504 visible_from_module,
504505 Some ( name) ,
505506 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+ }
508513 _ => None ,
509514 } ,
510- )
515+ ) ;
516+ res. or ( not_visible)
511517}
512518
513519/// 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>(
619625 visible_from_module : VisibleFromModule ,
620626 name : Option < & Name > ,
621627 mode : LookupMode ,
622- mut callback : impl FnMut ( ReceiverAdjustments , AssocItemId ) -> Option < T > ,
628+ mut callback : impl FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> Option < T > ,
623629) -> Option < T > {
624630 let mut slot = None ;
625631 iterate_method_candidates_dyn (
@@ -630,9 +636,9 @@ pub(crate) fn iterate_method_candidates<T>(
630636 visible_from_module,
631637 name,
632638 mode,
633- & mut |adj, item| {
639+ & mut |adj, item, visible | {
634640 assert ! ( slot. is_none( ) ) ;
635- if let Some ( it) = callback ( adj, item) {
641+ if let Some ( it) = callback ( adj, item, visible ) {
636642 slot = Some ( it) ;
637643 return ControlFlow :: Break ( ( ) ) ;
638644 }
@@ -771,7 +777,7 @@ pub fn iterate_path_candidates(
771777 name,
772778 LookupMode :: Path ,
773779 // the adjustments are not relevant for path lookup
774- & mut |_, id| callback ( id) ,
780+ & mut |_, id, _ | callback ( id) ,
775781 )
776782}
777783
@@ -783,7 +789,7 @@ pub fn iterate_method_candidates_dyn(
783789 visible_from_module : VisibleFromModule ,
784790 name : Option < & Name > ,
785791 mode : LookupMode ,
786- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
792+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
787793) -> ControlFlow < ( ) > {
788794 match mode {
789795 LookupMode :: MethodCall => {
@@ -847,7 +853,7 @@ fn iterate_method_candidates_with_autoref(
847853 traits_in_scope : & FxHashSet < TraitId > ,
848854 visible_from_module : VisibleFromModule ,
849855 name : Option < & Name > ,
850- mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
856+ mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
851857) -> ControlFlow < ( ) > {
852858 if receiver_ty. value . is_general_var ( Interner , & receiver_ty. binders ) {
853859 // don't try to resolve methods on unknown types
@@ -908,7 +914,7 @@ fn iterate_method_candidates_by_receiver(
908914 traits_in_scope : & FxHashSet < TraitId > ,
909915 visible_from_module : VisibleFromModule ,
910916 name : Option < & Name > ,
911- mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
917+ mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
912918) -> ControlFlow < ( ) > {
913919 let mut table = InferenceTable :: new ( db, env) ;
914920 let receiver_ty = table. instantiate_canonical ( receiver_ty. clone ( ) ) ;
@@ -954,7 +960,7 @@ fn iterate_method_candidates_for_self_ty(
954960 traits_in_scope : & FxHashSet < TraitId > ,
955961 visible_from_module : VisibleFromModule ,
956962 name : Option < & Name > ,
957- mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
963+ mut callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
958964) -> ControlFlow < ( ) > {
959965 let mut table = InferenceTable :: new ( db, env) ;
960966 let self_ty = table. instantiate_canonical ( self_ty. clone ( ) ) ;
@@ -985,7 +991,7 @@ fn iterate_trait_method_candidates(
985991 name : Option < & Name > ,
986992 receiver_ty : Option < & Ty > ,
987993 receiver_adjustments : Option < ReceiverAdjustments > ,
988- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
994+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
989995) -> ControlFlow < ( ) > {
990996 let db = table. db ;
991997 let env = table. trait_env . clone ( ) ;
@@ -1016,17 +1022,19 @@ fn iterate_trait_method_candidates(
10161022 for & ( _, item) in data. items . iter ( ) {
10171023 // Don't pass a `visible_from_module` down to `is_valid_candidate`,
10181024 // 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+ } ;
10221030 if !known_implemented {
10231031 let goal = generic_implements_goal ( db, env. clone ( ) , t, & canonical_self_ty) ;
10241032 if db. trait_solve ( env. krate , goal. cast ( Interner ) ) . is_none ( ) {
10251033 continue ' traits;
10261034 }
10271035 }
10281036 known_implemented = true ;
1029- callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item) ?;
1037+ callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item, visible ) ?;
10301038 }
10311039 }
10321040 ControlFlow :: Continue ( ( ) )
@@ -1039,7 +1047,7 @@ fn iterate_inherent_methods(
10391047 receiver_ty : Option < & Ty > ,
10401048 receiver_adjustments : Option < ReceiverAdjustments > ,
10411049 visible_from_module : VisibleFromModule ,
1042- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
1050+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
10431051) -> ControlFlow < ( ) > {
10441052 let db = table. db ;
10451053 let env = table. trait_env . clone ( ) ;
@@ -1128,17 +1136,21 @@ fn iterate_inherent_methods(
11281136 name : Option < & Name > ,
11291137 receiver_ty : Option < & Ty > ,
11301138 receiver_adjustments : Option < ReceiverAdjustments > ,
1131- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
1139+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
11321140 traits : impl Iterator < Item = TraitId > ,
11331141 ) -> ControlFlow < ( ) > {
11341142 let db = table. db ;
11351143 for t in traits {
11361144 let data = db. trait_data ( t) ;
11371145 for & ( _, item) in data. items . iter ( ) {
11381146 // 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) ?;
11421154 }
11431155 }
11441156 ControlFlow :: Continue ( ( ) )
@@ -1152,17 +1164,25 @@ fn iterate_inherent_methods(
11521164 receiver_ty : Option < & Ty > ,
11531165 receiver_adjustments : Option < ReceiverAdjustments > ,
11541166 visible_from_module : Option < ModuleId > ,
1155- callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId ) -> ControlFlow < ( ) > ,
1167+ callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
11561168 ) -> ControlFlow < ( ) > {
11571169 let db = table. db ;
11581170 let impls_for_self_ty = impls. for_self_ty ( self_ty) ;
11591171 for & impl_def in impls_for_self_ty {
11601172 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) ?;
11661186 }
11671187 }
11681188 ControlFlow :: Continue ( ( ) )
@@ -1191,7 +1211,7 @@ pub fn resolve_indexing_op(
11911211macro_rules! check_that {
11921212 ( $cond: expr) => {
11931213 if !$cond {
1194- return false ;
1214+ return IsValidCandidate :: No ;
11951215 }
11961216 } ;
11971217}
@@ -1203,7 +1223,7 @@ fn is_valid_candidate(
12031223 item : AssocItemId ,
12041224 self_ty : & Ty ,
12051225 visible_from_module : Option < ModuleId > ,
1206- ) -> bool {
1226+ ) -> IsValidCandidate {
12071227 let db = table. db ;
12081228 match item {
12091229 AssocItemId :: FunctionId ( m) => {
@@ -1214,13 +1234,13 @@ fn is_valid_candidate(
12141234 check_that ! ( receiver_ty. is_none( ) ) ;
12151235
12161236 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 ) {
12201240 cov_mark:: hit!( const_candidate_not_visible) ;
1241+ return IsValidCandidate :: NotVisible ;
12211242 }
1222- v
1223- } ) ) ;
1243+ }
12241244 if let ItemContainerId :: ImplId ( impl_id) = c. lookup ( db. upcast ( ) ) . container {
12251245 let self_ty_matches = table. run_in_snapshot ( |table| {
12261246 let expected_self_ty = TyBuilder :: impl_self_ty ( db, impl_id)
@@ -1230,35 +1250,39 @@ fn is_valid_candidate(
12301250 } ) ;
12311251 if !self_ty_matches {
12321252 cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1233- return false ;
1253+ return IsValidCandidate :: No ;
12341254 }
12351255 }
1236- true
1256+ IsValidCandidate :: Yes
12371257 }
1238- _ => false ,
1258+ _ => IsValidCandidate :: No ,
12391259 }
12401260}
12411261
1262+ enum IsValidCandidate {
1263+ Yes ,
1264+ No ,
1265+ NotVisible ,
1266+ }
1267+
12421268fn is_valid_fn_candidate (
12431269 table : & mut InferenceTable < ' _ > ,
12441270 fn_id : FunctionId ,
12451271 name : Option < & Name > ,
12461272 receiver_ty : Option < & Ty > ,
12471273 self_ty : & Ty ,
12481274 visible_from_module : Option < ModuleId > ,
1249- ) -> bool {
1275+ ) -> IsValidCandidate {
12501276 let db = table. db ;
12511277 let data = db. function_data ( fn_id) ;
12521278
12531279 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) {
12571282 cov_mark:: hit!( autoderef_candidate_not_visible) ;
1283+ return IsValidCandidate :: NotVisible ;
12581284 }
1259- v
1260- } ) ) ;
1261-
1285+ }
12621286 table. run_in_snapshot ( |table| {
12631287 let container = fn_id. lookup ( db. upcast ( ) ) . container ;
12641288 let ( impl_subst, expect_self_ty) = match container {
@@ -1297,7 +1321,7 @@ fn is_valid_fn_candidate(
12971321 // We need to consider the bounds on the impl to distinguish functions of the same name
12981322 // for a type.
12991323 let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
1300- predicates
1324+ let valid = predicates
13011325 . iter ( )
13021326 . map ( |predicate| {
13031327 let ( p, b) = predicate
@@ -1312,12 +1336,16 @@ fn is_valid_fn_candidate(
13121336 // It's ok to get ambiguity here, as we may not have enough information to prove
13131337 // obligations. We'll check if the user is calling the selected method properly
13141338 // 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+ }
13161344 } else {
13171345 // For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in
13181346 // `iterate_trait_method_candidates()`.
13191347 // For others, this function shouldn't be called.
1320- true
1348+ IsValidCandidate :: Yes
13211349 }
13221350 } )
13231351}
0 commit comments