@@ -1071,33 +1071,133 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10711071 . unwrap_or_else ( |_| {
10721072 span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
10731073 } ) ;
1074- self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1075- . or_else ( || {
1076- self . pick_autorefd_method (
1077- step,
1078- self_ty,
1079- hir:: Mutability :: Not ,
1080- unstable_candidates. as_deref_mut ( ) ,
1081- )
1082- . or_else ( || {
1083- self . pick_autorefd_method (
1074+
1075+ let by_value_pick =
1076+ self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) ) ;
1077+
1078+ // Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing)
1079+ if let Some ( by_value_pick) = by_value_pick {
1080+ if let Ok ( by_value_pick) = by_value_pick. as_ref ( ) {
1081+ if by_value_pick. kind == PickKind :: InherentImplPick {
1082+ if let Err ( e) = self . check_for_shadowed_autorefd_method (
1083+ by_value_pick,
1084+ step,
1085+ self_ty,
1086+ hir:: Mutability :: Not ,
1087+ unstable_candidates. is_some ( ) ,
1088+ ) {
1089+ return Some ( Err ( e) ) ;
1090+ }
1091+ if let Err ( e) = self . check_for_shadowed_autorefd_method (
1092+ by_value_pick,
10841093 step,
10851094 self_ty,
10861095 hir:: Mutability :: Mut ,
1087- unstable_candidates. as_deref_mut ( ) ,
1088- )
1089- } )
1090- . or_else ( || {
1091- self . pick_const_ptr_method (
1096+ unstable_candidates. is_some ( ) ,
1097+ ) {
1098+ return Some ( Err ( e) ) ;
1099+ }
1100+ }
1101+ }
1102+ return Some ( by_value_pick) ;
1103+ }
1104+
1105+ let autoref_pick = self . pick_autorefd_method (
1106+ step,
1107+ self_ty,
1108+ hir:: Mutability :: Not ,
1109+ unstable_candidates. as_deref_mut ( ) ,
1110+ ) ;
1111+ // Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
1112+ if let Some ( autoref_pick) = autoref_pick {
1113+ if let Ok ( autoref_pick) = autoref_pick. as_ref ( ) {
1114+ // Check we're not shadowing others
1115+ if autoref_pick. kind == PickKind :: InherentImplPick {
1116+ if let Err ( e) = self . check_for_shadowed_autorefd_method (
1117+ autoref_pick,
10921118 step,
10931119 self_ty,
1094- unstable_candidates. as_deref_mut ( ) ,
1095- )
1096- } )
1097- } )
1120+ hir:: Mutability :: Mut ,
1121+ unstable_candidates. is_some ( ) ,
1122+ ) {
1123+ return Some ( Err ( e) ) ;
1124+ }
1125+ }
1126+ }
1127+ return Some ( autoref_pick) ;
1128+ }
1129+
1130+ // Note that no shadowing errors are produced from here on,
1131+ // as we consider const ptr methods.
1132+ // We allow new methods that take *mut T to shadow
1133+ // methods which took *const T, so there is no entry in
1134+ // this list for the results of `pick_const_ptr_method`.
1135+ // The reason is that the standard pointer cast method
1136+ // (on a mutable pointer) always already shadows the
1137+ // cast method (on a const pointer). So, if we added
1138+ // `pick_const_ptr_method` to this method, the anti-
1139+ // shadowing algorithm would always complain about
1140+ // the conflict between *const::cast and *mut::cast.
1141+ // In practice therefore this does constrain us:
1142+ // we cannot add new
1143+ // self: *mut Self
1144+ // methods to types such as NonNull or anything else
1145+ // which implements Receiver, because this might in future
1146+ // shadow existing methods taking
1147+ // self: *const NonNull<Self>
1148+ // in the pointee. In practice, methods taking raw pointers
1149+ // are rare, and it seems that it should be easily possible
1150+ // to avoid such compatibility breaks.
1151+ self . pick_autorefd_method (
1152+ step,
1153+ self_ty,
1154+ hir:: Mutability :: Mut ,
1155+ unstable_candidates. as_deref_mut ( ) ,
1156+ )
1157+ . or_else ( || {
1158+ self . pick_const_ptr_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1159+ } )
10981160 } )
10991161 }
11001162
1163+ /// Check for cases where arbitrary self types allows shadowing
1164+ /// of methods that might be a compatibility break. Specifically,
1165+ /// we have something like:
1166+ /// ```compile_fail
1167+ /// # use std::ptr::NonNull;
1168+ /// struct A;
1169+ /// impl A {
1170+ /// fn foo(self: &NonNull<A>) {}
1171+ /// // note this is by reference
1172+ /// }
1173+ /// ```
1174+ /// then we've come along and added this method to `NonNull`:
1175+ /// ```
1176+ /// # struct NonNull;
1177+ /// # impl NonNull {
1178+ /// fn foo(self) {} // note this is by value
1179+ /// # }
1180+ /// ```
1181+ /// Report an error in this case.
1182+ fn check_for_shadowed_autorefd_method (
1183+ & self ,
1184+ _possible_shadower : & Pick < ' tcx > ,
1185+ step : & CandidateStep < ' tcx > ,
1186+ self_ty : Ty < ' tcx > ,
1187+ mutbl : hir:: Mutability ,
1188+ tracking_unstable_candidates : bool ,
1189+ ) -> Result < ( ) , MethodError < ' tcx > > {
1190+ let mut empty_vec = vec ! [ ] ;
1191+ let unstable_candidates_for_shadow_probe =
1192+ if tracking_unstable_candidates { Some ( & mut empty_vec) } else { None } ;
1193+ let _potentially_shadowed_pick =
1194+ self . pick_autorefd_method ( step, self_ty, mutbl, unstable_candidates_for_shadow_probe) ;
1195+
1196+ // At the moment, this function does no checks. A future
1197+ // commit will fill out the body here.
1198+ Ok ( ( ) )
1199+ }
1200+
11011201 /// For each type `T` in the step list, this attempts to find a method where
11021202 /// the (transformed) self type is exactly `T`. We do however do one
11031203 /// transformation on the adjustment: if we are passing a region pointer in,
@@ -1217,6 +1317,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12171317
12181318 // `pick_method` may be called twice for the same self_ty if no stable methods
12191319 // match. Only extend once.
1320+ // FIXME: this shouldn't be done when we're probing just for shadowing possibilities.
12201321 if unstable_candidates. is_some ( ) {
12211322 self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
12221323 }
0 commit comments