@@ -1064,6 +1064,14 @@ pub fn resolve_indexing_op(
10641064 None
10651065}
10661066
1067+ macro_rules! check_that {
1068+ ( $cond: expr) => {
1069+ if !$cond {
1070+ return false ;
1071+ }
1072+ } ;
1073+ }
1074+
10671075fn is_valid_candidate (
10681076 table : & mut InferenceTable < ' _ > ,
10691077 name : Option < & Name > ,
@@ -1072,54 +1080,10 @@ fn is_valid_candidate(
10721080 self_ty : & Ty ,
10731081 visible_from_module : Option < ModuleId > ,
10741082) -> bool {
1075- macro_rules! check_that {
1076- ( $cond: expr) => {
1077- if !$cond {
1078- return false ;
1079- }
1080- } ;
1081- }
1082-
10831083 let db = table. db ;
10841084 match item {
10851085 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)
11231087 }
11241088 AssocItemId :: ConstId ( c) => {
11251089 let data = db. const_data ( c) ;
@@ -1152,6 +1116,94 @@ fn is_valid_candidate(
11521116 }
11531117}
11541118
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+
11551207pub fn implements_trait (
11561208 ty : & Canonical < Ty > ,
11571209 db : & dyn HirDatabase ,
0 commit comments