@@ -158,6 +158,30 @@ impl AutorefOrPtrAdjustment {
158158 }
159159}
160160
161+ /// Criteria to apply when searching for a given Pick. This is used during
162+ /// the search for potentially shadowed methods to ensure we don't search
163+ /// more candidates than strictly necessary.
164+ #[ derive( Debug ) ]
165+ struct PickConstraintsForShadowed {
166+ autoderefs : usize ,
167+ receiver_trait_derefs : usize ,
168+ def_id : DefId ,
169+ }
170+
171+ impl PickConstraintsForShadowed {
172+ fn may_shadow_based_on_autoderefs ( & self , autoderefs : usize ) -> bool {
173+ autoderefs == self . autoderefs
174+ }
175+
176+ fn may_shadow_based_on_receiver_trait_derefs ( & self , receiver_trait_derefs : usize ) -> bool {
177+ receiver_trait_derefs != self . receiver_trait_derefs
178+ }
179+
180+ fn may_shadow_based_on_defid ( & self , def_id : DefId ) -> bool {
181+ def_id != self . def_id
182+ }
183+ }
184+
161185#[ derive( Debug , Clone ) ]
162186pub struct Pick < ' tcx > {
163187 pub item : ty:: AssocItem ,
@@ -180,7 +204,6 @@ pub struct Pick<'tcx> {
180204
181205 /// Number of jumps along the Receiver::target chain we followed
182206 /// to identify this method. Used only for deshadowing errors.
183- #[ allow( dead_code) ]
184207 pub receiver_trait_derefs : usize ,
185208}
186209
@@ -1156,6 +1179,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11561179 self_ty,
11571180 hir:: Mutability :: Not ,
11581181 unstable_candidates. as_deref_mut ( ) ,
1182+ None ,
11591183 ) ;
11601184 // Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
11611185 if let Some ( autoref_pick) = autoref_pick {
@@ -1202,6 +1226,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12021226 self_ty,
12031227 hir:: Mutability :: Mut ,
12041228 unstable_candidates. as_deref_mut ( ) ,
1229+ None ,
12051230 )
12061231 . or_else ( || {
12071232 self . pick_const_ptr_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
@@ -1230,7 +1255,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12301255 /// Report an error in this case.
12311256 fn check_for_shadowed_autorefd_method (
12321257 & self ,
1233- _possible_shadower : & Pick < ' tcx > ,
1258+ possible_shadower : & Pick < ' tcx > ,
12341259 step : & CandidateStep < ' tcx > ,
12351260 self_ty : Ty < ' tcx > ,
12361261 mutbl : hir:: Mutability ,
@@ -1239,8 +1264,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12391264 let mut empty_vec = vec ! [ ] ;
12401265 let unstable_candidates_for_shadow_probe =
12411266 if tracking_unstable_candidates { Some ( & mut empty_vec) } else { None } ;
1242- let _potentially_shadowed_pick =
1243- self . pick_autorefd_method ( step, self_ty, mutbl, unstable_candidates_for_shadow_probe) ;
1267+ // Set criteria for how we find methods possibly shadowed by 'possible_shadower'
1268+ let pick_constraints = PickConstraintsForShadowed {
1269+ // It's the same `self` type, other than any autoreffing...
1270+ autoderefs : possible_shadower. autoderefs ,
1271+ // ... but the method was found in an impl block determined
1272+ // by searching further along the Receiver chain than the other,
1273+ // showing that it's arbitrary self types causing the problem...
1274+ receiver_trait_derefs : possible_shadower. receiver_trait_derefs ,
1275+ // ... and they don't end up pointing to the same item in the
1276+ // first place (could happen with things like blanket impls for T)
1277+ def_id : possible_shadower. item . def_id ,
1278+ } ;
1279+ let _potentially_shadowed_pick = self . pick_autorefd_method (
1280+ step,
1281+ self_ty,
1282+ mutbl,
1283+ unstable_candidates_for_shadow_probe,
1284+ Some ( & pick_constraints) ,
1285+ ) ;
12441286
12451287 // At the moment, this function does no checks. A future
12461288 // commit will fill out the body here.
@@ -1263,7 +1305,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12631305 return None ;
12641306 }
12651307
1266- self . pick_method ( self_ty, unstable_candidates) . map ( |r| {
1308+ self . pick_method ( self_ty, unstable_candidates, None ) . map ( |r| {
12671309 r. map ( |mut pick| {
12681310 pick. autoderefs = step. autoderefs ;
12691311
@@ -1287,14 +1329,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12871329 self_ty : Ty < ' tcx > ,
12881330 mutbl : hir:: Mutability ,
12891331 unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1332+ pick_constraints : Option < & PickConstraintsForShadowed > ,
12901333 ) -> Option < PickResult < ' tcx > > {
12911334 let tcx = self . tcx ;
12921335
1336+ if let Some ( pick_constraints) = pick_constraints {
1337+ if !pick_constraints. may_shadow_based_on_autoderefs ( step. autoderefs ) {
1338+ return None ;
1339+ }
1340+ }
1341+
12931342 // In general, during probing we erase regions.
12941343 let region = tcx. lifetimes . re_erased ;
12951344
12961345 let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1297- self . pick_method ( autoref_ty, unstable_candidates) . map ( |r| {
1346+ self . pick_method ( autoref_ty, unstable_candidates, pick_constraints ) . map ( |r| {
12981347 r. map ( |mut pick| {
12991348 pick. autoderefs = step. autoderefs ;
13001349 pick. autoref_or_ptr_adjustment =
@@ -1323,7 +1372,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13231372 } ;
13241373
13251374 let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1326- self . pick_method ( const_ptr_ty, unstable_candidates) . map ( |r| {
1375+ self . pick_method ( const_ptr_ty, unstable_candidates, None ) . map ( |r| {
13271376 r. map ( |mut pick| {
13281377 pick. autoderefs = step. autoderefs ;
13291378 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1336,6 +1385,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13361385 & self ,
13371386 self_ty : Ty < ' tcx > ,
13381387 mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1388+ pick_constraints : Option < & PickConstraintsForShadowed > ,
13391389 ) -> Option < PickResult < ' tcx > > {
13401390 debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
13411391
@@ -1350,6 +1400,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13501400 candidates,
13511401 & mut possibly_unsatisfied_predicates,
13521402 unstable_candidates. as_deref_mut ( ) ,
1403+ pick_constraints,
13531404 ) ;
13541405 if let Some ( pick) = res {
13551406 return Some ( pick) ;
@@ -1358,16 +1409,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13581409
13591410 if self . private_candidate . get ( ) . is_none ( ) {
13601411 if let Some ( Ok ( pick) ) =
1361- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None )
1412+ self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None , None )
13621413 {
13631414 self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
13641415 }
13651416 }
13661417
13671418 // `pick_method` may be called twice for the same self_ty if no stable methods
1368- // match. Only extend once.
1369- // FIXME: this shouldn't be done when we're probing just for shadowing possibilities .
1370- if unstable_candidates. is_some ( ) {
1419+ // match. Only extend once. And don't extend if we're just doing a search for
1420+ // shadowed methods, which will result in a Some pick_constraints .
1421+ if unstable_candidates. is_some ( ) && pick_constraints . is_none ( ) {
13711422 self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
13721423 }
13731424 None
@@ -1383,9 +1434,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13831434 Option < ObligationCause < ' tcx > > ,
13841435 ) > ,
13851436 mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1437+ pick_constraints : Option < & PickConstraintsForShadowed > ,
13861438 ) -> Option < PickResult < ' tcx > > {
13871439 let mut applicable_candidates: Vec < _ > = candidates
13881440 . iter ( )
1441+ . filter ( |candidate| {
1442+ pick_constraints
1443+ . map ( |pick_constraints| {
1444+ pick_constraints. may_shadow_based_on_defid ( candidate. item . def_id )
1445+ && pick_constraints. may_shadow_based_on_receiver_trait_derefs (
1446+ candidate. receiver_trait_derefs ,
1447+ )
1448+ } )
1449+ . unwrap_or ( true )
1450+ } )
13891451 . map ( |probe| {
13901452 ( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
13911453 } )
0 commit comments