@@ -576,30 +576,57 @@ pub(crate) fn iterate_method_candidates<T>(
576576 slot
577577}
578578
579- pub fn lookup_trait_m_for_self_ty (
579+ pub fn lookup_impl_method (
580580 self_ty : & Ty ,
581581 db : & dyn HirDatabase ,
582582 env : Arc < TraitEnvironment > ,
583- implied_trait : TraitId ,
583+ trait_ : TraitId ,
584584 name : & Name ,
585585) -> Option < FunctionId > {
586- let self_ty_tp = TyFingerprint :: for_trait_impl ( self_ty) ?;
586+ let self_ty_fp = TyFingerprint :: for_trait_impl ( self_ty) ?;
587587 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 ) ;
589589 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;
600628 }
601629 }
602- None
603630}
604631
605632pub fn iterate_path_candidates (
@@ -877,7 +904,7 @@ fn iterate_trait_method_candidates(
877904 for & ( _, item) in data. items . iter ( ) {
878905 // Don't pass a `visible_from_module` down to `is_valid_candidate`,
879906 // 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 ) {
881908 continue ;
882909 }
883910 if !known_implemented {
@@ -959,14 +986,8 @@ fn iterate_inherent_methods(
959986 let impls_for_self_ty = impls. for_self_ty ( self_ty) ;
960987 for & impl_def in impls_for_self_ty {
961988 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+ {
970991 continue ;
971992 }
972993 callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item) ?;
@@ -994,130 +1015,92 @@ pub fn resolve_indexing_op(
9941015 }
9951016 None
9961017}
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 ;
10301031 }
1031- }
1032+ } ;
10321033 }
10331034
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) ;
10461045 }
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 ( )
10881054 }
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 )
11011057 }
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 ! ( )
11151061 }
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) ) ;
11161072 }
11171073 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+ }
11181100 }
1119- _ => false ,
1101+ true
11201102 }
1103+ _ => false ,
11211104 }
11221105}
11231106
0 commit comments