@@ -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 ( ) )
@@ -1226,7 +1251,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12261251 /// Report an error in this case.
12271252 fn check_for_shadowed_autorefd_method (
12281253 & self ,
1229- _possible_shadower : & Pick < ' tcx > ,
1254+ possible_shadower : & Pick < ' tcx > ,
12301255 step : & CandidateStep < ' tcx > ,
12311256 self_ty : Ty < ' tcx > ,
12321257 mutbl : hir:: Mutability ,
@@ -1235,8 +1260,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12351260 let mut empty_vec = vec ! [ ] ;
12361261 let unstable_candidates_for_shadow_probe =
12371262 if tracking_unstable_candidates { Some ( & mut empty_vec) } else { None } ;
1238- let _potentially_shadowed_pick =
1239- self . pick_autorefd_method ( step, self_ty, mutbl, unstable_candidates_for_shadow_probe) ;
1263+ // Set criteria for how we find methods possibly shadowed by 'possible_shadower'
1264+ let pick_constraints = PickConstraintsForShadowed {
1265+ // It's the same `self` type, other than any autoreffing...
1266+ autoderefs : possible_shadower. autoderefs ,
1267+ // ... but the method was found in an impl block determined
1268+ // by searching further along the Receiver chain than the other,
1269+ // showing that it's arbitrary self types causing the problem...
1270+ receiver_trait_derefs : possible_shadower. receiver_trait_derefs ,
1271+ // ... and they don't end up pointing to the same item in the
1272+ // first place (could happen with things like blanket impls for T)
1273+ def_id : possible_shadower. item . def_id ,
1274+ } ;
1275+ let _potentially_shadowed_pick = self . pick_autorefd_method (
1276+ step,
1277+ self_ty,
1278+ mutbl,
1279+ unstable_candidates_for_shadow_probe,
1280+ Some ( & pick_constraints) ,
1281+ ) ;
12401282
12411283 // At the moment, this function does no checks. A future
12421284 // commit will fill out the body here.
@@ -1259,7 +1301,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12591301 return None ;
12601302 }
12611303
1262- self . pick_method ( self_ty, unstable_candidates) . map ( |r| {
1304+ self . pick_method ( self_ty, unstable_candidates, None ) . map ( |r| {
12631305 r. map ( |mut pick| {
12641306 pick. autoderefs = step. autoderefs ;
12651307
@@ -1283,14 +1325,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12831325 self_ty : Ty < ' tcx > ,
12841326 mutbl : hir:: Mutability ,
12851327 unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1328+ pick_constraints : Option < & PickConstraintsForShadowed > ,
12861329 ) -> Option < PickResult < ' tcx > > {
12871330 let tcx = self . tcx ;
12881331
1332+ if let Some ( pick_constraints) = pick_constraints {
1333+ if !pick_constraints. may_shadow_based_on_autoderefs ( step. autoderefs ) {
1334+ return None ;
1335+ }
1336+ }
1337+
12891338 // In general, during probing we erase regions.
12901339 let region = tcx. lifetimes . re_erased ;
12911340
12921341 let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1293- self . pick_method ( autoref_ty, unstable_candidates) . map ( |r| {
1342+ self . pick_method ( autoref_ty, unstable_candidates, pick_constraints ) . map ( |r| {
12941343 r. map ( |mut pick| {
12951344 pick. autoderefs = step. autoderefs ;
12961345 pick. autoref_or_ptr_adjustment =
@@ -1319,7 +1368,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13191368 } ;
13201369
13211370 let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1322- self . pick_method ( const_ptr_ty, unstable_candidates) . map ( |r| {
1371+ self . pick_method ( const_ptr_ty, unstable_candidates, None ) . map ( |r| {
13231372 r. map ( |mut pick| {
13241373 pick. autoderefs = step. autoderefs ;
13251374 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1332,6 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13321381 & self ,
13331382 self_ty : Ty < ' tcx > ,
13341383 mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1384+ pick_constraints : Option < & PickConstraintsForShadowed > ,
13351385 ) -> Option < PickResult < ' tcx > > {
13361386 debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
13371387
@@ -1346,6 +1396,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13461396 candidates,
13471397 & mut possibly_unsatisfied_predicates,
13481398 unstable_candidates. as_deref_mut ( ) ,
1399+ pick_constraints,
13491400 ) ;
13501401 if let Some ( pick) = res {
13511402 return Some ( pick) ;
@@ -1354,16 +1405,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13541405
13551406 if self . private_candidate . get ( ) . is_none ( ) {
13561407 if let Some ( Ok ( pick) ) =
1357- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None )
1408+ self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None , None )
13581409 {
13591410 self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
13601411 }
13611412 }
13621413
13631414 // `pick_method` may be called twice for the same self_ty if no stable methods
1364- // match. Only extend once.
1365- // FIXME: this shouldn't be done when we're probing just for shadowing possibilities .
1366- if unstable_candidates. is_some ( ) {
1415+ // match. Only extend once. And don't extend if we're just doing a search for
1416+ // shadowed methods, which will result in a Some pick_constraints .
1417+ if unstable_candidates. is_some ( ) && pick_constraints . is_none ( ) {
13671418 self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
13681419 }
13691420 None
@@ -1379,9 +1430,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13791430 Option < ObligationCause < ' tcx > > ,
13801431 ) > ,
13811432 mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1433+ pick_constraints : Option < & PickConstraintsForShadowed > ,
13821434 ) -> Option < PickResult < ' tcx > > {
13831435 let mut applicable_candidates: Vec < _ > = candidates
13841436 . iter ( )
1437+ . filter ( |candidate| {
1438+ pick_constraints
1439+ . map ( |pick_constraints| {
1440+ pick_constraints. may_shadow_based_on_defid ( candidate. item . def_id )
1441+ && pick_constraints. may_shadow_based_on_receiver_trait_derefs (
1442+ candidate. receiver_trait_derefs ,
1443+ )
1444+ } )
1445+ . unwrap_or ( true )
1446+ } )
13851447 . map ( |probe| {
13861448 ( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
13871449 } )
0 commit comments